From 2df8145bde101adcb91c810ef0b6804aa60cb3f0 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Mon, 14 Sep 2026 00:22:42 +0700 Subject: [PATCH 1/4] depends: add blst 0.3.17 blst (https://github.com/supranational/blst) is the BLS12-381 backend of the upcoming src/dashbls update. The package runs blst's own build.sh and installs libblst.a plus bindings/blst.h and blst_aux.h into the depends prefix. __BLST_PORTABLE__ selects runtime CPU dispatch so the build does not depend on the builder's CPU flags. --- depends/packages/blst.mk | 24 ++++++++++++++++++++++++ depends/packages/packages.mk | 2 +- doc/dependencies.md | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 depends/packages/blst.mk diff --git a/depends/packages/blst.mk b/depends/packages/blst.mk new file mode 100644 index 000000000000..3fd4d7020734 --- /dev/null +++ b/depends/packages/blst.mk @@ -0,0 +1,24 @@ +package=blst +$(package)_version=0.3.17 +$(package)_download_path=https://github.com/supranational/blst/archive/refs/tags +$(package)_download_file=v$($(package)_version).tar.gz +$(package)_file_name=$(package)-$($(package)_version).tar.gz +$(package)_sha256_hash=c3fef37b566b67419703b2bbb648e15176276af9a880c22aa8f5f2e8cecc2e4d + +# build.sh takes CC/AR/RANLIB/CFLAGS from the environment. __BLST_PORTABLE__ +# selects runtime CPU dispatch instead of letting build.sh probe the builder's +# /proc/cpuinfo for ADX, which keeps the build reproducible; build.sh itself +# adds -D__BLST_NO_ASM__ on hosts other than x86_64/aarch64. +define $(package)_set_vars + $(package)_build_env=CC="$($(package)_cc)" AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CFLAGS="$($(package)_cflags) $($(package)_cppflags) -fno-builtin -fPIC -D__BLST_PORTABLE__" +endef + +define $(package)_build_cmds + ./build.sh +endef + +define $(package)_stage_cmds + mkdir -p $($(package)_staging_prefix_dir)/include $($(package)_staging_prefix_dir)/lib && \ + install -m 644 bindings/blst.h bindings/blst_aux.h $($(package)_staging_prefix_dir)/include && \ + install -m 644 libblst.a $($(package)_staging_prefix_dir)/lib +endef diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 59232930eb38..4a1211d60075 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -1,4 +1,4 @@ -packages:=gmp backtrace +packages:=gmp backtrace blst boost_packages = boost diff --git a/doc/dependencies.md b/doc/dependencies.md index eaf67114fd32..0e9c22ebd946 100644 --- a/doc/dependencies.md +++ b/doc/dependencies.md @@ -19,6 +19,7 @@ You can find installation instructions in the `build-*.md` file for your platfor | --- | --- | --- | --- | --- | | [Boost](../depends/packages/boost.mk) | [link](https://www.boost.org/users/download/) | 1.81.0 | [1.73.0](https://github.com/bitcoin/bitcoin/pull/29066) | No | | [libevent](../depends/packages/libevent.mk) | [link](https://github.com/libevent/libevent/releases) | [2.1.12-stable](https://github.com/bitcoin/bitcoin/pull/21991) | [2.1.8](https://github.com/bitcoin/bitcoin/pull/24681) | No | +| [blst](../depends/packages/blst.mk) | [link](https://github.com/supranational/blst/releases) | 0.3.17 | | No | | glibc | [link](https://www.gnu.org/software/libc/) | N/A | [2.31](https://github.com/bitcoin/bitcoin/pull/29987) | Yes | | Linux Kernel | [link](https://www.kernel.org/) | N/A | [3.17.0](https://github.com/bitcoin/bitcoin/pull/27699) | Yes | From 0970a6875d5ae66db718d3318472704d3676375e Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Tue, 3 Nov 2026 15:45:21 +0700 Subject: [PATCH 2/4] depends: update 'src/dashbls' to dashpay/bls-signatures@77c8da5 --- src/dashbls/.github/workflows/binds-go.yml | 7 +- src/dashbls/.github/workflows/binds-py.yml | 5 - src/dashbls/.github/workflows/binds-rs.yml | 9 +- src/dashbls/.github/workflows/build-test.yaml | 19 +- src/dashbls/.github/workflows/stale-issue.yml | 0 src/dashbls/.gitignore | 9 - src/dashbls/CMakeLists.txt | 108 +- src/dashbls/MANIFEST.in | 5 - src/dashbls/Makefile.am | 39 - src/dashbls/Makefile.bench.include | 22 - src/dashbls/Makefile.bls.include | 66 - src/dashbls/Makefile.mimalloc.include | 46 - src/dashbls/Makefile.relic.include | 470 ------ src/dashbls/Makefile.test.include | 27 - src/dashbls/README.md | 12 +- src/dashbls/apple.rust.deps.sh | 363 +---- src/dashbls/autogen.sh | 13 - src/dashbls/binds/python/CMakeLists.txt | 2 +- src/dashbls/binds/python/pythonbindings.cpp | 1 - .../build-aux/m4/ax_check_compile_flag.m4 | 53 - .../build-aux/m4/ax_check_link_flag.m4 | 53 - .../build-aux/m4/ax_cxx_compile_stdcxx.m4 | 1005 ------------- src/dashbls/build-aux/m4/ax_pthread.m4 | 522 ------- src/dashbls/cmake_modules/Findgmp.cmake | 103 -- src/dashbls/cmake_modules/Findsodium.cmake | 294 ---- src/dashbls/configure.ac | 913 ----------- src/dashbls/go-bindings/Makefile | 28 +- src/dashbls/include/dashbls/bls.hpp | 2 - src/dashbls/include/dashbls/chaincode.hpp | 14 +- src/dashbls/include/dashbls/elements.hpp | 103 +- .../include/dashbls/extendedprivatekey.hpp | 8 - .../include/dashbls/extendedpublickey.hpp | 8 - src/dashbls/include/dashbls/hdkeys.hpp | 145 +- src/dashbls/include/dashbls/hkdf.hpp | 13 +- src/dashbls/include/dashbls/legacy.hpp | 25 +- src/dashbls/include/dashbls/privatekey.hpp | 19 +- src/dashbls/include/dashbls/schemes.hpp | 286 ++-- src/dashbls/include/dashbls/test-utils.hpp | 8 +- src/dashbls/include/dashbls/util.hpp | 44 +- src/dashbls/js-bindings/CMakeLists.txt | 2 - src/dashbls/js-bindings/blsjs.d.ts | 9 - src/dashbls/js-bindings/helpers.cpp | 27 - src/dashbls/js-bindings/helpers.h | 9 - src/dashbls/js-bindings/jsbindings.cpp | 6 - src/dashbls/js-bindings/tests/test.js | 8 - .../js-bindings/wrappers/BignumWrapper.cpp | 48 - .../js-bindings/wrappers/BignumWrapper.h | 42 - .../js-bindings/wrappers/G1ElementWrapper.cpp | 10 - .../js-bindings/wrappers/G1ElementWrapper.h | 3 - .../js-bindings/wrappers/G2ElementWrapper.cpp | 10 - .../js-bindings/wrappers/G2ElementWrapper.h | 3 - src/dashbls/pyproject.toml | 4 - .../rust-bindings/bls-dash-sys/build.rs | 54 +- .../bls-dash-sys/c-bindings/schemes.cpp | 9 +- .../bls-signatures/src/schemes.rs | 76 +- src/dashbls/setup.py | 1 - src/dashbls/src/CMakeLists.txt | 100 +- src/dashbls/src/bls.cpp | 45 - src/dashbls/src/bn_helpers.hpp | 62 - src/dashbls/src/chaincode.cpp | 16 +- src/dashbls/src/elements.cpp | 690 ++++++--- src/dashbls/src/extendedprivatekey.cpp | 21 +- src/dashbls/src/extendedpublickey.cpp | 4 +- src/dashbls/src/legacy.cpp | 602 +++----- src/dashbls/src/privatekey.cpp | 197 ++- src/dashbls/src/schemes.cpp | 662 +++++--- src/dashbls/src/test-bench.cpp | 40 +- src/dashbls/src/test-vectors.hpp | 575 +++++++ src/dashbls/src/test.cpp | 1329 +++++++++++++---- src/dashbls/src/threshold.cpp | 149 +- src/dashbls/test-vectors/reference.txt | 324 ++++ src/dashbls/tools/fuzzgen.cpp | 165 ++ src/dashbls/tools/vectorgen.cpp | 22 + 73 files changed, 3943 insertions(+), 6250 deletions(-) mode change 100755 => 100644 src/dashbls/.github/workflows/stale-issue.yml delete mode 100644 src/dashbls/Makefile.am delete mode 100644 src/dashbls/Makefile.bench.include delete mode 100644 src/dashbls/Makefile.bls.include delete mode 100644 src/dashbls/Makefile.mimalloc.include delete mode 100644 src/dashbls/Makefile.relic.include delete mode 100644 src/dashbls/Makefile.test.include delete mode 100755 src/dashbls/autogen.sh delete mode 100644 src/dashbls/build-aux/m4/ax_check_compile_flag.m4 delete mode 100644 src/dashbls/build-aux/m4/ax_check_link_flag.m4 delete mode 100644 src/dashbls/build-aux/m4/ax_cxx_compile_stdcxx.m4 delete mode 100644 src/dashbls/build-aux/m4/ax_pthread.m4 delete mode 100644 src/dashbls/cmake_modules/Findgmp.cmake delete mode 100644 src/dashbls/cmake_modules/Findsodium.cmake delete mode 100644 src/dashbls/configure.ac delete mode 100644 src/dashbls/js-bindings/wrappers/BignumWrapper.cpp delete mode 100644 src/dashbls/js-bindings/wrappers/BignumWrapper.h delete mode 100644 src/dashbls/src/bn_helpers.hpp create mode 100644 src/dashbls/src/test-vectors.hpp create mode 100644 src/dashbls/test-vectors/reference.txt create mode 100644 src/dashbls/tools/fuzzgen.cpp create mode 100644 src/dashbls/tools/vectorgen.cpp diff --git a/src/dashbls/.github/workflows/binds-go.yml b/src/dashbls/.github/workflows/binds-go.yml index ccda3c190131..71a4ffe004dd 100644 --- a/src/dashbls/.github/workflows/binds-go.yml +++ b/src/dashbls/.github/workflows/binds-go.yml @@ -32,15 +32,10 @@ jobs: if: startsWith(matrix.os, 'ubuntu') run: | sudo apt-get update - sudo apt-get install -qq --yes valgrind libgmp-dev cmake + sudo apt-get install -qq --yes valgrind cmake hash -r cmake --version - - name: Prepare build system for macOS - if: startsWith(matrix.os, 'macos') - run: | - brew install gmp - - name: Build library using CMake run: | cores=$(getconf _NPROCESSORS_ONLN) diff --git a/src/dashbls/.github/workflows/binds-py.yml b/src/dashbls/.github/workflows/binds-py.yml index 803fb37fa4f2..b305a3fffe9b 100644 --- a/src/dashbls/.github/workflows/binds-py.yml +++ b/src/dashbls/.github/workflows/binds-py.yml @@ -92,11 +92,6 @@ jobs: - name: Build the sdist run: uv build --sdist --out-dir dist - - name: Prepare build system - run: | - sudo apt-get update - sudo apt-get install -qq --yes libgmp-dev - - name: Install from the sdist and run the unit tests run: | uv venv .venv-sdist diff --git a/src/dashbls/.github/workflows/binds-rs.yml b/src/dashbls/.github/workflows/binds-rs.yml index 8e3db323db12..5656b32272d0 100644 --- a/src/dashbls/.github/workflows/binds-rs.yml +++ b/src/dashbls/.github/workflows/binds-rs.yml @@ -27,15 +27,10 @@ jobs: if: startsWith(matrix.os, 'ubuntu') run: | sudo apt-get update - sudo apt-get install -qq --yes valgrind libgmp-dev cmake + sudo apt-get install -qq --yes valgrind cmake hash -r cmake --version - - name: Prepare build system for macOS - if: startsWith(matrix.os, 'macos') - run: | - brew install gmp - - name: Install Rust run: | rustup toolchain install ${{ matrix.rust }} @@ -47,3 +42,5 @@ jobs: run: | cd rust-bindings/bls-dash-sys cargo test + cd ../bls-signatures + cargo test diff --git a/src/dashbls/.github/workflows/build-test.yaml b/src/dashbls/.github/workflows/build-test.yaml index 90a550a5e4d2..8b253e05e7a8 100644 --- a/src/dashbls/.github/workflows/build-test.yaml +++ b/src/dashbls/.github/workflows/build-test.yaml @@ -17,19 +17,17 @@ concurrency: jobs: build: - name: ${{ matrix.os }}, ${{ matrix.builder }}, ${{ matrix.compiler.cc }}, ${{ matrix.backend }} backend + name: ${{ matrix.os }}, ${{ matrix.compiler.cc }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ macos-latest, ubuntu-latest ] - builder: [ cmake, autotools ] compiler: - cc: gcc cxx: g++ - cc: clang cxx: clang++ - backend: [ easy, gmp ] steps: - name: Checkout code uses: actions/checkout@v3 @@ -38,32 +36,23 @@ jobs: if: startsWith(matrix.os, 'ubuntu') run: | sudo apt-get update - sudo apt-get install -qq --yes valgrind libgmp-dev cmake + sudo apt-get install -qq --yes valgrind cmake hash -r cmake --version - name: Prepare build system for macOS if: startsWith(matrix.os, 'macos') run: | - ls -l export MACOSX_DEPLOYMENT_TARGET=10.14 - brew install autoconf automake gmp libtool pkg-config + brew install pkg-config - name: Build library using CMake - if: startsWith(matrix.builder, 'cmake') run: | mkdir -p build && cd build - CC=${{ matrix.compiler.cc }} CXX=${{ matrix.compiler.cxx }} cmake .. -DARITH=${{ matrix.backend }} -DBUILD_BLS_PYTHON_BINDINGS=0 -DCMAKE_BUILD_TYPE=Debug + CC=${{ matrix.compiler.cc }} CXX=${{ matrix.compiler.cxx }} cmake .. -DBUILD_BLS_PYTHON_BINDINGS=0 -DCMAKE_BUILD_TYPE=Debug cmake --build . -- -j 6 mv src/runtest .. - - name: Build library using GNU Autotools - if: startsWith(matrix.builder, 'autotools') - run: | - ./autogen.sh - CC=${{ matrix.compiler.cc }} CXX=${{ matrix.compiler.cxx }} ./configure --with-backend=${{ matrix.backend }} - make -j8 - - name: Run tests run: ./runtest diff --git a/src/dashbls/.github/workflows/stale-issue.yml b/src/dashbls/.github/workflows/stale-issue.yml old mode 100755 new mode 100644 diff --git a/src/dashbls/.gitignore b/src/dashbls/.gitignore index f968c1dbe44d..ec8e23435253 100644 --- a/src/dashbls/.gitignore +++ b/src/dashbls/.gitignore @@ -17,15 +17,6 @@ main .o obj/ src/*.o -depends/relic/CTestTestfile.cmake -depends/relic/bench/CTestTestfile.cmake -depends/relic/bin -depends/relic/include/relic_conf.h -depends/relic/include/relic_conf.h.in -depends/relic/include/relic_conf.h.old -depends/relic/include/stamp-h1 -depends/relic/test/CTestTestfile.cmake -contrib/gmp-6.1.2/ .idea .vscode diff --git a/src/dashbls/CMakeLists.txt b/src/dashbls/CMakeLists.txt index a224da20b626..b99a9f750f8a 100644 --- a/src/dashbls/CMakeLists.txt +++ b/src/dashbls/CMakeLists.txt @@ -14,6 +14,12 @@ endif() project(BLS) +if(MSVC) + enable_language(ASM_MASM) +else() + enable_language(ASM) +endif() + set(BUILD_BLS_JS_BINDINGS "1" CACHE STRING "") set(BUILD_BLS_PYTHON_BINDINGS "1" CACHE STRING "") set(BUILD_BLS_TESTS "1" CACHE STRING "") @@ -29,94 +35,27 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules ) -# Relic related options - -set(STBIN "off" CACHE STRING "Relic - Build static binaries") - -find_package(gmp) -if (GMP_FOUND) - message(STATUS "Found libgmp") - set(ARITH "gmp" CACHE STRING "") -else() - set(ARITH "easy" CACHE STRING "") -endif() - -if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(WSIZE "32" CACHE STRING "Relic - Processor word size") -else() - set(WSIZE "64" CACHE STRING "Relic - Processor word size") -endif() - -if(EMSCRIPTEN) - # emscripten needs arch set to be none since it can't compile assembly - set(ARCH "" CACHE STRING "") - # emscripten is a 32 bit compiler - set(WSIZE "32" CACHE STRING "Relic - Processor word size") -endif() - -if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - set(TIMER "ANSI" CACHE STRING "") - set(MULTI "OPENMP" CACHE STRING "") -else() - set(TIMER "CYCLE" CACHE STRING "") - set(MULTI "PTHREAD" CACHE STRING "") -endif() - -set(CHECK "off" CACHE STRING "") -set(VERBS "off" CACHE STRING "") -set(ALLOC "AUTO" CACHE STRING "") -set(SHLIB "off" CACHE STRING "") -set(DOCUM "off" CACHE STRING "") -set(FP_PRIME "381" CACHE STRING "Relic - Prime modulus size") - -if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(SEED "UDEV" CACHE STRING "") - set(FP_QNRES "off" CACHE STRING "") -elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - set(SEED "WCGR" CACHE STRING "") - set(FP_QNRES "on" CACHE STRING "") -else() - set(SEED "UDEV" CACHE STRING "") - set(FP_QNRES "on" CACHE STRING "") -endif() - -set(FP_METHD "INTEG;INTEG;INTEG;MONTY;LOWER;SLIDE" CACHE STRING "") - -if(MSVC) - set(COMP_FLAGS "" CACHE STRING "") -else() - set(COMP_FLAGS "-O3 -funroll-loops -fomit-frame-pointer" CACHE STRING "") -endif() - -set(FP_PMERS "off" CACHE STRING "") -set(FPX_METHD "INTEG;INTEG;LAZYR" CACHE STRING "") -set(EP_PLAIN "off" CACHE STRING "") -set(EP_SUPER "off" CACHE STRING "") -# Disable relic tests and benchmarks -set(TESTS "0" CACHE STRING "Relic - Number of times each test is ran") -set(BENCH "0" CACHE STRING "Relic - Number of times each benchmark is ran") - -set(QUIET "on" CACHE STRING "Relic - Build with printing disabled") - -set(PP_EXT "LAZYR" CACHE STRING "") -set(PP_METHD "LAZYR;OATEP" CACHE STRING "") - # Disable mimalloc shared libraries and tests, enable secure mode set(MI_SECURE "on" CACHE STRING "") set(MI_BUILD_SHARED "off" CACHE STRING "") set(MI_BUILD_TESTS "off" CACHE STRING "") set(MI_OVERRIDE "off" CACHE STRING "") - -add_subdirectory(depends/relic) add_subdirectory(depends/mimalloc) -#message(STATUS "Patching Relic to make setjmp.h inclusion conditional") -# -#execute_process( -# COMMAND bash -c "git apply ${CMAKE_SOURCE_DIR}/setjmp_patch.diff" -# WORKING_DIRECTORY ${RELIC_SRC} -#) +include(FetchContent) + +set(BLST_GIT_TAG "a8cd361c9f671577aeab3f074098443af92a53fc") +set(BLST_REPOSITORY "https://github.com/supranational/blst") + +message(STATUS "blst will be built from: ${BLST_GIT_TAG} and repository ${BLST_REPOSITORY}") + +FetchContent_Declare( + blst + GIT_REPOSITORY ${BLST_REPOSITORY} + GIT_TAG ${BLST_GIT_TAG} +) +FetchContent_MakeAvailable(blst) add_subdirectory(src) @@ -128,14 +67,7 @@ endif() file(APPEND "${CMAKE_CURRENT_LIST_DIR}/build/include_paths.txt" "${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES};") -if(GMP_INCLUDES) - file(APPEND "${CMAKE_CURRENT_LIST_DIR}/build/include_paths.txt" "${GMP_INCLUDES};") -endif() - -# Write gmp library path for rust binding -if(GMP_LIBRARIES) - file(APPEND "${CMAKE_CURRENT_LIST_DIR}/build/gmp_libraries.txt" "${GMP_LIBRARIES}") -endif() +file(APPEND "${CMAKE_CURRENT_LIST_DIR}/build/include_paths.txt" "${blst_SOURCE_DIR}/bindings;") if(EMSCRIPTEN) if(BUILD_BLS_JS_BINDINGS) diff --git a/src/dashbls/MANIFEST.in b/src/dashbls/MANIFEST.in index 62cc22eaeea0..5ae9e0282fb1 100644 --- a/src/dashbls/MANIFEST.in +++ b/src/dashbls/MANIFEST.in @@ -25,11 +25,6 @@ prune depends/relic/preset prune depends/relic/test prune depends/relic/tools -# Autotools build -prune build-aux -prune autom4te.cache -exclude Makefile.am Makefile.*.include Makefile.in Makefile configure.ac aclocal.m4 autogen.sh - # dot{dir,file}s prune .github prune .vscode diff --git a/src/dashbls/Makefile.am b/src/dashbls/Makefile.am deleted file mode 100644 index 1c1e5d19d594..000000000000 --- a/src/dashbls/Makefile.am +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2013-2016 The Bitcoin Core developers -# Copyright (c) 2022 The Dash Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING.MIT or http://www.opensource.org/licenses/mit-license.php. - -print-%: FORCE - @echo '$*'='$($*)' - -ACLOCAL_AMFLAGS = -I build-aux/m4 -.PHONY: deploy FORCE - -AM_LDFLAGS = $(HARDENED_LDFLAGS) $(CORE_LDFLAGS) $(GMP_LDFLAGS) -AM_CFLAGS = $(DEBUG_FLAGS) $(HARDENED_FLAGS) $(CORE_FLAGS) $(WARN_FLAGS) $(NOWARN_FLAGS) -AM_CPPFLAGS = $(CORE_CPPFLAGS) $(GMP_CPPFLAGS) -AM_CXXFLAGS = $(DEBUG_FLAGS) $(HARDENED_FLAGS) $(CORE_FLAGS) $(WARN_FLAGS) $(NOWARN_FLAGS) -PTHREAD_FLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) - -EXTRA_LIBRARIES = - -lib_LTLIBRARIES = -noinst_LTLIBRARIES = - -bin_PROGRAMS = -noinst_PROGRAMS = -EXTRA_DIST = - -CLEANFILES = - -include Makefile.bls.include - -CLEANFILES += $(LIBRELIC) $(LIBDASHBLS) $(LIBMIMALLOC) - -if USE_TESTS -CLEANFILES += $(DASHBLS_RUNTEST) -endif - -if USE_BENCH -CLEANFILES += $(DASHBLS_RUNBENCH) -endif diff --git a/src/dashbls/Makefile.bench.include b/src/dashbls/Makefile.bench.include deleted file mode 100644 index f584102a3294..000000000000 --- a/src/dashbls/Makefile.bench.include +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2021 The PIVX developers -# Copyright (c) 2022 The Dash Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING.MIT or http://www.opensource.org/licenses/mit-license.php. - -DASHBLS_RUNBENCH = runbench - -runbench_SOURCES = \ - src/test-bench.cpp \ - src/test-utils.hpp - -runbench_SOURCES += \ - $(RELIC_H) \ - $(DASHBLS_H) - -runbench_CPPFLAGS = $(AM_CPPFLAGS) $(DASHBLS_INCLUDES) $(RELIC_INCLUDES) -runbench_CXXFLAGS = $(AM_CXXFLAGS) -runbench_LDFLAGS = -static $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS) - -runbench_LDADD = $(LIBDASHBLS) - -noinst_PROGRAMS += $(DASHBLS_RUNBENCH) diff --git a/src/dashbls/Makefile.bls.include b/src/dashbls/Makefile.bls.include deleted file mode 100644 index 7c35b3ced764..000000000000 --- a/src/dashbls/Makefile.bls.include +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright (c) 2021 The PIVX developers -# Copyright (c) 2022 The Dash Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING.MIT or http://www.opensource.org/licenses/mit-license.php. - -LIBDASHBLS = libdashbls.la - -DASHBLS_CPPFLAGS = -DBLSALLOC_MIMALLOC=1 - -DASHBLS_INCLUDES = \ - -I$(builddir) \ - -I$(builddir)/obj \ - -I$(top_srcdir)/include/dashbls - -DASHBLS_H = \ - src/bls.hpp \ - src/chaincode.hpp \ - src/elements.hpp \ - src/extendedprivatekey.hpp \ - src/extendedpublickey.hpp \ - src/hdkeys.hpp \ - src/hkdf.hpp \ - src/legacy.hpp \ - src/privatekey.hpp \ - src/schemes.hpp \ - src/test-utils.hpp \ - src/threshold.hpp \ - src/util.hpp - -libdashbls_la_SOURCES = \ - src/bls.cpp \ - src/chaincode.cpp \ - src/elements.cpp \ - src/extendedprivatekey.cpp \ - src/extendedpublickey.cpp \ - src/legacy.cpp \ - src/privatekey.cpp \ - src/schemes.cpp \ - src/threshold.cpp - -libdashbls_la_SOURCES += \ - $(DASHBLS_H) \ - $(MIMALLOC_H) \ - $(RELIC_H) - -libdashbls_la_LIBADD = \ - $(LIBMIMALLOC) \ - $(LIBRELIC) \ - $(GMP_LIBS) - -libdashbls_la_CPPFLAGS = $(AM_CPPFLAGS) $(RELIC_INCLUDES) $(MIMALLOC_INCLUDES) $(DASHBLS_INCLUDES) $(DASHBLS_CPPFLAGS) -libdashbls_la_CXXFLAGS = $(AM_CXXFLAGS) -libdashbls_la_LDFLAGS = $(AM_LDFLAGS) - -include Makefile.mimalloc.include -include Makefile.relic.include - -if USE_TESTS -include Makefile.test.include -endif - -if USE_BENCH -include Makefile.bench.include -endif - -lib_LTLIBRARIES += $(LIBDASHBLS) diff --git a/src/dashbls/Makefile.mimalloc.include b/src/dashbls/Makefile.mimalloc.include deleted file mode 100644 index fada5fe32819..000000000000 --- a/src/dashbls/Makefile.mimalloc.include +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2022-2025 The Dash Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING.MIT or http://www.opensource.org/licenses/mit-license.php. - -LIBMIMALLOC = libmimalloc-secure.la - -MIMALLOC_CPPFLAGS = \ - -DMI_SECURE=4 \ - -DNDEBUG - -MIMALLOC_INCLUDES = \ - -I$(top_srcdir)/depends/mimalloc/include \ - -I$(top_srcdir)/depends/mimalloc/src - -MIMALLOC_H = \ - depends/mimalloc/include/mimalloc-new-delete.h \ - depends/mimalloc/include/mimalloc-override.h \ - depends/mimalloc/include/mimalloc-stats.h \ - depends/mimalloc/include/mimalloc.h \ - depends/mimalloc/src/bitmap.h - -libmimalloc_secure_la_SOURCES = \ - $(MIMALLOC_H) \ - depends/mimalloc/src/alloc-aligned.c \ - depends/mimalloc/src/alloc-posix.c \ - depends/mimalloc/src/alloc.c \ - depends/mimalloc/src/arena-meta.c \ - depends/mimalloc/src/arena.c \ - depends/mimalloc/src/bitmap.c \ - depends/mimalloc/src/heap.c \ - depends/mimalloc/src/init.c \ - depends/mimalloc/src/libc.c \ - depends/mimalloc/src/options.c \ - depends/mimalloc/src/os.c \ - depends/mimalloc/src/page-map.c \ - depends/mimalloc/src/page.c \ - depends/mimalloc/src/random.c \ - depends/mimalloc/src/stats.c \ - depends/mimalloc/src/prim/prim.c - -libmimalloc_secure_la_CPPFLAGS = $(AM_CPPFLAGS) $(MIMALLOC_CPPFLAGS) $(MIMALLOC_INCLUDES) -libmimalloc_secure_la_CXXFLAGS = $(AM_CXXFLAGS) -libmimalloc_secure_la_CFLAGS = $(AM_CFLAGS) -libmimalloc_secure_la_LDFLAGS = $(AM_LDFLAGS) - -noinst_LTLIBRARIES += $(LIBMIMALLOC) diff --git a/src/dashbls/Makefile.relic.include b/src/dashbls/Makefile.relic.include deleted file mode 100644 index 92bd7c7e8f5b..000000000000 --- a/src/dashbls/Makefile.relic.include +++ /dev/null @@ -1,470 +0,0 @@ -# Copyright (c) 2021 The PIVX developers -# Copyright (c) 2022 The Dash Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING.MIT or http://www.opensource.org/licenses/mit-license.php. - -LIBRELIC = librelic.la - -RELIC_INCLUDES = \ - -I$(top_srcdir)/depends/relic/include \ - -I$(top_srcdir)/depends/relic/include/low \ - -I$(top_srcdir)/depends/relic/src/tmpl - -RELIC_H = \ - depends/relic/include/relic.h \ - depends/relic/include/relic_alloc.h \ - depends/relic/include/relic_arch.h \ - depends/relic/include/relic_bc.h \ - depends/relic/include/relic_bench.h \ - depends/relic/include/relic_bn.h \ - depends/relic/include/relic_conf.h \ - depends/relic/include/relic_core.h \ - depends/relic/include/relic_cp.h \ - depends/relic/include/relic_dv.h \ - depends/relic/include/relic_eb.h \ - depends/relic/include/relic_ec.h \ - depends/relic/include/relic_ed.h \ - depends/relic/include/relic_ep.h \ - depends/relic/include/relic_epx.h \ - depends/relic/include/relic_err.h \ - depends/relic/include/relic_fb.h \ - depends/relic/include/relic_fbx.h \ - depends/relic/include/relic_fp.h \ - depends/relic/include/relic_fpx.h \ - depends/relic/include/relic_label.h \ - depends/relic/include/relic_md.h \ - depends/relic/include/relic_mpc.h \ - depends/relic/include/relic_multi.h \ - depends/relic/include/relic_pc.h \ - depends/relic/include/relic_pp.h \ - depends/relic/include/relic_rand.h \ - depends/relic/include/relic_test.h \ - depends/relic/include/relic_types.h \ - depends/relic/include/relic_util.h \ - depends/relic/include/low/relic_bn_low.h \ - depends/relic/include/low/relic_dv_low.h \ - depends/relic/include/low/relic_fb_low.h \ - depends/relic/include/low/relic_fp_low.h \ - depends/relic/include/low/relic_fpx_low.h \ - depends/relic/src/arch/lzcnt.inc \ - depends/relic/src/tmpl/relic_tmpl_map.h - -RELIC_SOURCES = \ - depends/relic/src/relic_err.c \ - depends/relic/src/relic_core.c \ - depends/relic/src/relic_conf.c \ - depends/relic/src/relic_util.c - -BN_SOURCES = \ - depends/relic/src/bn/relic_bn_add.c \ - depends/relic/src/bn/relic_bn_cmp.c \ - depends/relic/src/bn/relic_bn_div.c \ - depends/relic/src/bn/relic_bn_factor.c \ - depends/relic/src/bn/relic_bn_gcd.c \ - depends/relic/src/bn/relic_bn_inv.c \ - depends/relic/src/bn/relic_bn_lcm.c \ - depends/relic/src/bn/relic_bn_mem.c \ - depends/relic/src/bn/relic_bn_mod.c \ - depends/relic/src/bn/relic_bn_mul.c \ - depends/relic/src/bn/relic_bn_mxp.c \ - depends/relic/src/bn/relic_bn_prime.c \ - depends/relic/src/bn/relic_bn_rec.c \ - depends/relic/src/bn/relic_bn_shift.c \ - depends/relic/src/bn/relic_bn_smb.c \ - depends/relic/src/bn/relic_bn_sqr.c \ - depends/relic/src/bn/relic_bn_srt.c \ - depends/relic/src/bn/relic_bn_util.c - -FP_SOURCES = \ - depends/relic/src/fp/relic_fp_add.c \ - depends/relic/src/fp/relic_fp_cmp.c \ - depends/relic/src/fp/relic_fp_exp.c \ - depends/relic/src/fp/relic_fp_inv.c \ - depends/relic/src/fp/relic_fp_mul.c \ - depends/relic/src/fp/relic_fp_param.c \ - depends/relic/src/fp/relic_fp_prime.c \ - depends/relic/src/fp/relic_fp_rdc.c \ - depends/relic/src/fp/relic_fp_shift.c \ - depends/relic/src/fp/relic_fp_sqr.c \ - depends/relic/src/fp/relic_fp_srt.c \ - depends/relic/src/fp/relic_fp_util.c - -FPX_SOURCES = \ - depends/relic/src/fpx/relic_fp2_mul.c \ - depends/relic/src/fpx/relic_fp2_sqr.c \ - depends/relic/src/fpx/relic_fp3_mul.c \ - depends/relic/src/fpx/relic_fp3_sqr.c \ - depends/relic/src/fpx/relic_fp4_mul.c \ - depends/relic/src/fpx/relic_fp4_sqr.c \ - depends/relic/src/fpx/relic_fp6_mul.c \ - depends/relic/src/fpx/relic_fp6_sqr.c \ - depends/relic/src/fpx/relic_fp8_mul.c \ - depends/relic/src/fpx/relic_fp8_sqr.c \ - depends/relic/src/fpx/relic_fp9_mul.c \ - depends/relic/src/fpx/relic_fp9_sqr.c \ - depends/relic/src/fpx/relic_fp12_mul.c \ - depends/relic/src/fpx/relic_fp12_sqr.c \ - depends/relic/src/fpx/relic_fp18_mul.c \ - depends/relic/src/fpx/relic_fp18_sqr.c \ - depends/relic/src/fpx/relic_fp24_mul.c \ - depends/relic/src/fpx/relic_fp24_sqr.c \ - depends/relic/src/fpx/relic_fp48_mul.c \ - depends/relic/src/fpx/relic_fp48_sqr.c \ - depends/relic/src/fpx/relic_fp54_mul.c \ - depends/relic/src/fpx/relic_fp54_sqr.c \ - depends/relic/src/fpx/relic_fpx_add.c \ - depends/relic/src/fpx/relic_fpx_cmp.c \ - depends/relic/src/fpx/relic_fpx_cyc.c \ - depends/relic/src/fpx/relic_fpx_exp.c \ - depends/relic/src/fpx/relic_fpx_field.c \ - depends/relic/src/fpx/relic_fpx_frb.c \ - depends/relic/src/fpx/relic_fpx_inv.c \ - depends/relic/src/fpx/relic_fpx_pck.c \ - depends/relic/src/fpx/relic_fpx_rdc.c \ - depends/relic/src/fpx/relic_fpx_srt.c \ - depends/relic/src/fpx/relic_fpx_util.c - -FB_SOURCES = \ - depends/relic/src/fb/relic_fb_add.c \ - depends/relic/src/fb/relic_fb_cmp.c \ - depends/relic/src/fb/relic_fb_exp.c \ - depends/relic/src/fb/relic_fb_inv.c \ - depends/relic/src/fb/relic_fb_itr.c \ - depends/relic/src/fb/relic_fb_mul.c \ - depends/relic/src/fb/relic_fb_param.c \ - depends/relic/src/fb/relic_fb_poly.c \ - depends/relic/src/fb/relic_fb_rdc.c \ - depends/relic/src/fb/relic_fb_shift.c \ - depends/relic/src/fb/relic_fb_slv.c \ - depends/relic/src/fb/relic_fb_sqr.c \ - depends/relic/src/fb/relic_fb_srt.c \ - depends/relic/src/fb/relic_fb_trc.c \ - depends/relic/src/fb/relic_fb_util.c - -EP_SOURCES = \ - depends/relic/src/ep/relic_ep_add.c \ - depends/relic/src/ep/relic_ep_cmp.c \ - depends/relic/src/ep/relic_ep_curve.c \ - depends/relic/src/ep/relic_ep_dbl.c \ - depends/relic/src/ep/relic_ep_map.c \ - depends/relic/src/ep/relic_ep_mul.c \ - depends/relic/src/ep/relic_ep_mul_fix.c \ - depends/relic/src/ep/relic_ep_mul_sim.c \ - depends/relic/src/ep/relic_ep_neg.c \ - depends/relic/src/ep/relic_ep_norm.c \ - depends/relic/src/ep/relic_ep_param.c \ - depends/relic/src/ep/relic_ep_pck.c \ - depends/relic/src/ep/relic_ep_psi.c \ - depends/relic/src/ep/relic_ep_util.c - -EPX_SOURCES = \ - depends/relic/src/epx/relic_ep2_add.c \ - depends/relic/src/epx/relic_ep2_cmp.c \ - depends/relic/src/epx/relic_ep2_curve.c \ - depends/relic/src/epx/relic_ep2_dbl.c \ - depends/relic/src/epx/relic_ep2_frb.c \ - depends/relic/src/epx/relic_ep2_map.c \ - depends/relic/src/epx/relic_ep2_mul.c \ - depends/relic/src/epx/relic_ep2_mul_cof.c \ - depends/relic/src/epx/relic_ep2_mul_fix.c \ - depends/relic/src/epx/relic_ep2_mul_sim.c \ - depends/relic/src/epx/relic_ep2_neg.c \ - depends/relic/src/epx/relic_ep2_norm.c \ - depends/relic/src/epx/relic_ep2_pck.c \ - depends/relic/src/epx/relic_ep2_util.c \ - depends/relic/src/epx/relic_ep4_add.c \ - depends/relic/src/epx/relic_ep4_cmp.c \ - depends/relic/src/epx/relic_ep4_curve.c \ - depends/relic/src/epx/relic_ep4_dbl.c \ - depends/relic/src/epx/relic_ep4_frb.c \ - depends/relic/src/epx/relic_ep4_map.c \ - depends/relic/src/epx/relic_ep4_mul.c \ - depends/relic/src/epx/relic_ep4_mul_cof.c \ - depends/relic/src/epx/relic_ep4_mul_fix.c \ - depends/relic/src/epx/relic_ep4_mul_sim.c \ - depends/relic/src/epx/relic_ep4_neg.c \ - depends/relic/src/epx/relic_ep4_norm.c \ - depends/relic/src/epx/relic_ep4_util.c - -EB_SOURCES = \ - depends/relic/src/eb/relic_eb_add.c \ - depends/relic/src/eb/relic_eb_cmp.c \ - depends/relic/src/eb/relic_eb_curve.c \ - depends/relic/src/eb/relic_eb_dbl.c \ - depends/relic/src/eb/relic_eb_frb.c \ - depends/relic/src/eb/relic_eb_hlv.c \ - depends/relic/src/eb/relic_eb_map.c \ - depends/relic/src/eb/relic_eb_mul.c \ - depends/relic/src/eb/relic_eb_mul_fix.c \ - depends/relic/src/eb/relic_eb_mul_sim.c \ - depends/relic/src/eb/relic_eb_neg.c \ - depends/relic/src/eb/relic_eb_norm.c \ - depends/relic/src/eb/relic_eb_param.c \ - depends/relic/src/eb/relic_eb_pck.c \ - depends/relic/src/eb/relic_eb_util.c - -ED_SOURCES = \ - depends/relic/src/ed/relic_ed_add.c \ - depends/relic/src/ed/relic_ed_cmp.c \ - depends/relic/src/ed/relic_ed_curve.c \ - depends/relic/src/ed/relic_ed_dbl.c \ - depends/relic/src/ed/relic_ed_map.c \ - depends/relic/src/ed/relic_ed_mul.c \ - depends/relic/src/ed/relic_ed_mul_fix.c \ - depends/relic/src/ed/relic_ed_mul_sim.c \ - depends/relic/src/ed/relic_ed_neg.c \ - depends/relic/src/ed/relic_ed_norm.c \ - depends/relic/src/ed/relic_ed_param.c \ - depends/relic/src/ed/relic_ed_pck.c \ - depends/relic/src/ed/relic_ed_util.c - -PP_SOURCES = \ - depends/relic/src/pp/relic_pp_add_k2.c \ - depends/relic/src/pp/relic_pp_add_k8.c \ - depends/relic/src/pp/relic_pp_add_k12.c \ - depends/relic/src/pp/relic_pp_add_k24.c \ - depends/relic/src/pp/relic_pp_add_k48.c \ - depends/relic/src/pp/relic_pp_add_k54.c \ - depends/relic/src/pp/relic_pp_dbl_k2.c \ - depends/relic/src/pp/relic_pp_dbl_k8.c \ - depends/relic/src/pp/relic_pp_dbl_k12.c \ - depends/relic/src/pp/relic_pp_dbl_k24.c \ - depends/relic/src/pp/relic_pp_dbl_k48.c \ - depends/relic/src/pp/relic_pp_dbl_k54.c \ - depends/relic/src/pp/relic_pp_exp_k2.c \ - depends/relic/src/pp/relic_pp_exp_k8.c \ - depends/relic/src/pp/relic_pp_exp_k12.c \ - depends/relic/src/pp/relic_pp_exp_k24.c \ - depends/relic/src/pp/relic_pp_exp_k48.c \ - depends/relic/src/pp/relic_pp_exp_k54.c \ - depends/relic/src/pp/relic_pp_map.c \ - depends/relic/src/pp/relic_pp_map_k2.c \ - depends/relic/src/pp/relic_pp_map_k8.c \ - depends/relic/src/pp/relic_pp_map_k12.c \ - depends/relic/src/pp/relic_pp_map_k24.c \ - depends/relic/src/pp/relic_pp_map_k48.c \ - depends/relic/src/pp/relic_pp_map_k54.c \ - depends/relic/src/pp/relic_pp_norm.c - -PC_SOURCES = \ - depends/relic/src/pc/relic_pc_core.c \ - depends/relic/src/pc/relic_pc_exp.c \ - depends/relic/src/pc/relic_pc_util.c - -MD_SOURCES = \ - depends/relic/src/md/blake2.h \ - depends/relic/src/md/blake2-impl.h \ - depends/relic/src/md/blake2s-ref.c \ - depends/relic/src/md/relic_md_blake2s.c \ - depends/relic/src/md/relic_md_hmac.c \ - depends/relic/src/md/relic_md_kdf.c \ - depends/relic/src/md/relic_md_mgf.c \ - depends/relic/src/md/relic_md_sha224.c \ - depends/relic/src/md/relic_md_sha256.c \ - depends/relic/src/md/relic_md_sha384.c \ - depends/relic/src/md/relic_md_sha512.c \ - depends/relic/src/md/relic_md_xmd.c \ - depends/relic/src/md/sha.h \ - depends/relic/src/md/sha224-256.c \ - depends/relic/src/md/sha384-512.c \ - depends/relic/src/md/sha_private.h - -EXTRA_DIST += \ - depends/relic/src/arch/relic_arch_arm.c \ - depends/relic/src/arch/relic_arch_none.c \ - depends/relic/src/arch/relic_arch_x64.c \ - depends/relic/src/arch/relic_arch_x86.c - -RELIC_SOURCES += \ - depends/relic/src/arch/relic_arch_@CPU_ARCH@.c \ - depends/relic/src/rand/relic_rand_call.c \ - depends/relic/src/rand/relic_rand_core.c \ - depends/relic/src/rand/relic_rand_hashd.c \ - depends/relic/src/rand/relic_rand_udev.c - -if WITH_DV -RELIC_SOURCES += \ - depends/relic/src/dv/relic_dv_mem.c \ - depends/relic/src/dv/relic_dv_util.c -endif - -if ARITH_EASY -if WITH_BN -RELIC_SOURCES += $(BN_SOURCES) \ - depends/relic/src/low/easy/relic_bn_add_low.c \ - depends/relic/src/low/easy/relic_bn_div_low.c \ - depends/relic/src/low/easy/relic_bn_mod_low.c \ - depends/relic/src/low/easy/relic_bn_mul_low.c \ - depends/relic/src/low/easy/relic_bn_shift_low.c \ - depends/relic/src/low/easy/relic_bn_sqr_low.c -endif - -if WITH_FP -RELIC_SOURCES += $(FP_SOURCES) \ - depends/relic/src/low/easy/relic_fp_add_low.c \ - depends/relic/src/low/easy/relic_fp_inv_low.c \ - depends/relic/src/low/easy/relic_fp_mul_low.c \ - depends/relic/src/low/easy/relic_fp_rdc_low.c \ - depends/relic/src/low/easy/relic_fp_shift_low.c \ - depends/relic/src/low/easy/relic_fp_sqr_low.c -endif - -if WITH_FPX -RELIC_SOURCES += $(FPX_SOURCES) \ - depends/relic/src/low/easy/relic_fpx_add_low.c \ - depends/relic/src/low/easy/relic_fpx_mul_low.c \ - depends/relic/src/low/easy/relic_fpx_rdc_low.c \ - depends/relic/src/low/easy/relic_fpx_sqr_low.c -endif - -if WITH_FB -RELIC_SOURCES += $(FB_SOURCES) \ - depends/relic/src/low/easy/relic_fb_add_low.c \ - depends/relic/src/low/easy/relic_fb_inv_low.c \ - depends/relic/src/low/easy/relic_fb_itr_low.c \ - depends/relic/src/low/easy/relic_fb_mul_low.c \ - depends/relic/src/low/easy/relic_fb_rdc_low.c \ - depends/relic/src/low/easy/relic_fb_shift_low.c \ - depends/relic/src/low/easy/relic_fb_slv_low.c \ - depends/relic/src/low/easy/relic_fb_sqr_low.c \ - depends/relic/src/low/easy/relic_fb_srt_low.c \ - depends/relic/src/low/easy/relic_fb_trc_low.c -endif -endif - -if ARITH_GMP -if WITH_BN -RELIC_SOURCES += $(BN_SOURCES) \ - depends/relic/src/low/gmp/relic_bn_add_low.c \ - depends/relic/src/low/gmp/relic_bn_div_low.c \ - depends/relic/src/low/gmp/relic_bn_mod_low.c \ - depends/relic/src/low/gmp/relic_bn_mul_low.c \ - depends/relic/src/low/gmp/relic_bn_shift_low.c \ - depends/relic/src/low/gmp/relic_bn_sqr_low.c -endif - -if WITH_FP -RELIC_SOURCES += $(FP_SOURCES) \ - depends/relic/src/low/gmp/relic_fp_add_low.c \ - depends/relic/src/low/gmp/relic_fp_inv_low.c \ - depends/relic/src/low/gmp/relic_fp_mul_low.c \ - depends/relic/src/low/gmp/relic_fp_rdc_low.c \ - depends/relic/src/low/gmp/relic_fp_shift_low.c \ - depends/relic/src/low/gmp/relic_fp_sqr_low.c -endif - -if WITH_FPX -RELIC_SOURCES += $(FPX_SOURCES) \ - depends/relic/src/low/easy/relic_fpx_add_low.c \ - depends/relic/src/low/easy/relic_fpx_mul_low.c \ - depends/relic/src/low/easy/relic_fpx_rdc_low.c \ - depends/relic/src/low/easy/relic_fpx_sqr_low.c -endif - -if WITH_FB -RELIC_SOURCES += $(FB_SOURCES) \ - depends/relic/src/low/gmp/relic_fb_add_low.c \ - depends/relic/src/low/easy/relic_fb_inv_low.c \ - depends/relic/src/low/easy/relic_fb_itr_low.c \ - depends/relic/src/low/easy/relic_fb_mul_low.c \ - depends/relic/src/low/easy/relic_fb_rdc_low.c \ - depends/relic/src/low/gmp/relic_fb_shift_low.c \ - depends/relic/src/low/easy/relic_fb_slv_low.c \ - depends/relic/src/low/easy/relic_fb_sqr_low.c \ - depends/relic/src/low/easy/relic_fb_srt_low.c \ - depends/relic/src/low/easy/relic_fb_trc_low.c -endif -endif - -if WITH_FBX -RELIC_SOURCES += \ - depends/relic/src/fbx/relic_fb2_inv.c \ - depends/relic/src/fbx/relic_fb2_mul.c \ - depends/relic/src/fbx/relic_fb2_slv.c \ - depends/relic/src/fbx/relic_fb2_sqr.c -endif - -if WITH_EP -RELIC_SOURCES += $(EP_SOURCES) -endif - -if WITH_EPX -RELIC_SOURCES += $(EPX_SOURCES) -endif - -if WITH_EB -RELIC_SOURCES += $(EB_SOURCES) -endif - -if WITH_ED -RELIC_SOURCES += $(ED_SOURCES) -endif - -if WITH_PP -RELIC_SOURCES += $(PP_SOURCES) -endif - -if WITH_PC -RELIC_SOURCES += $(PC_SOURCES) -endif - -if WITH_CP -RELIC_SOURCES += \ - depends/relic/src/cp/relic_cp_bbs.c \ - depends/relic/src/cp/relic_cp_bdpe.c \ - depends/relic/src/cp/relic_cp_bgn.c \ - depends/relic/src/cp/relic_cp_bls.c \ - depends/relic/src/cp/relic_cp_cls.c \ - depends/relic/src/cp/relic_cp_cmlhs.c \ - depends/relic/src/cp/relic_cp_ecdh.c \ - depends/relic/src/cp/relic_cp_ecdsa.c \ - depends/relic/src/cp/relic_cp_ecies.c \ - depends/relic/src/cp/relic_cp_ecmqv.c \ - depends/relic/src/cp/relic_cp_ecss.c \ - depends/relic/src/cp/relic_cp_ers.c \ - depends/relic/src/cp/relic_cp_etrs.c \ - depends/relic/src/cp/relic_cp_ghpe.c \ - depends/relic/src/cp/relic_cp_ibe.c \ - depends/relic/src/cp/relic_cp_mklhs.c \ - depends/relic/src/cp/relic_cp_mpss.c \ - depends/relic/src/cp/relic_cp_pcdel.c \ - depends/relic/src/cp/relic_cp_phpe.c \ - depends/relic/src/cp/relic_cp_pok.c \ - depends/relic/src/cp/relic_cp_pss.c \ - depends/relic/src/cp/relic_cp_rabin.c \ - depends/relic/src/cp/relic_cp_rsa.c \ - depends/relic/src/cp/relic_cp_sok.c \ - depends/relic/src/cp/relic_cp_sokaka.c \ - depends/relic/src/cp/relic_cp_vbnn.c \ - depends/relic/src/cp/relic_cp_zss.c -endif - -if WITH_BC -RELIC_SOURCES += \ - depends/relic/src/bc/relic_bc_aes.c \ - depends/relic/src/bc/rijndael-alg-fst.c \ - depends/relic/src/bc/rijndael-alg-fst.h \ - depends/relic/src/bc/rijndael-api-fst.c \ - depends/relic/src/bc/rijndael-api-fst.h -endif - -if WITH_MD -RELIC_SOURCES += $(MD_SOURCES) -endif - -if WITH_MPC -RELIC_SOURCES += \ - depends/relic/src/mpc/relic_mt_mpc.c \ - depends/relic/src/mpc/relic_pc_mpc.c -endif - -librelic_la_SOURCES = \ - $(RELIC_SOURCES) \ - $(RELIC_H) - -librelic_la_CPPFLAGS = $(AM_CPPFLAGS) $(RELIC_CPPFLAGS) $(RELIC_INCLUDES) -librelic_la_CXXFLAGS = $(AM_CXXFLAGS) -librelic_la_CFLAGS = $(AM_CFLAGS) -librelic_la_LDFLAGS = $(AM_LDFLAGS) - -noinst_LTLIBRARIES += $(LIBRELIC) diff --git a/src/dashbls/Makefile.test.include b/src/dashbls/Makefile.test.include deleted file mode 100644 index a8ec86cb59d1..000000000000 --- a/src/dashbls/Makefile.test.include +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2021 The PIVX developers -# Copyright (c) 2022 The Dash Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING.MIT or http://www.opensource.org/licenses/mit-license.php. - -DASHBLS_RUNTEST = runtest - -RUNTEST_INCLUDES = \ - -I$(top_srcdir)/depends/catch2/include - -RUNTEST_H = \ - depends/catch2/include/catch2/catch.hpp - -runtest_SOURCES = \ - $(DASHBLS_H) \ - $(RELIC_H) \ - $(RUNTEST_H) \ - src/test.cpp \ - src/test-utils.hpp - -runtest_CPPFLAGS = $(AM_CPPFLAGS) $(DASHBLS_INCLUDES) $(RELIC_INCLUDES) $(RUNTEST_INCLUDES) -runtest_CXXFLAGS = $(AM_CXXFLAGS) -runtest_LDFLAGS = -static $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS) - -runtest_LDADD = $(LIBDASHBLS) - -noinst_PROGRAMS += $(DASHBLS_RUNTEST) diff --git a/src/dashbls/README.md b/src/dashbls/README.md index 1d22cdfd4d66..d3292e46df68 100644 --- a/src/dashbls/README.md +++ b/src/dashbls/README.md @@ -11,20 +11,19 @@ > **This library has not undergone a formal security review.** `bls-signatures` is a cross-platform library implementing BLS12-381 primitives for Dash built on -the [`relic`](https://github.com/relic-toolkit/relic) toolkit with bindings available in +the [`blst library`](https://github.com/supranational/blst.git) toolkit with bindings available in [Python](./binds/python), [Rust](./rust-bindings/), [Go](./go-bindings/) and [Javascript](./js-bindings). ## Dependencies * A C++17 capable compiler (GCC 9, Clang 7 or higher) -* CMake 3.18 or higher (or Autoconf 2.71 or higher; with libtool and automake) -* [`libgmp`](https://gmplib.org/) (for fast arithmetic, **optional**) +* CMake 3.18 or higher Additionally, the following dependencies are supplied by the codebase * [`catch2`](https://github.com/catchorg/Catch2) (for tests) * [`mimalloc`](https://github.com/microsoft/mimalloc) (for secure memory operations) -* [`relic`](https://github.com/relic-toolkit/relic) (for cryptographic operations) +* [`blst`](https://github.com/supranational/blst.git) (for cryptographic operations) ## Build library @@ -100,6 +99,11 @@ uv run pytest -v binds/python/test_unit.py uv run pytest -v binds/python/test_bench.py --benchmark-only ``` +## BLST license + +BLST is used with the +[Apache 2.0 license](https://github.com/supranational/blst/blob/master/LICENSE) + ## License ```text diff --git a/src/dashbls/apple.rust.deps.sh b/src/dashbls/apple.rust.deps.sh index b2ebc41a4ff2..ad9f3b9809e9 100755 --- a/src/dashbls/apple.rust.deps.sh +++ b/src/dashbls/apple.rust.deps.sh @@ -1,337 +1,87 @@ -#!/bin/sh -set -x +#!/bin/bash +# +# Builds libdashbls (with the blst backend CMake fetches) for Apple platforms, +# for consumption by rust-bindings' "apple" feature. +# +# Usage: apple.rust.deps.sh +# +# Artefacts are placed in build/artefacts//: libdashbls.a and +# libmimalloc-secure.a. The former contains the blst objects; no external +# arithmetic library (the relic-era GMP dependency is gone). + set -e -# "x86_64-apple-ios" -# "aarch64-apple-ios" -# "aarch64-apple-ios-sim" -# "x86_64-apple-darwin" -# "aarch64-apple-darwin" -# TODO: it's probably needs to be optimized in order to increase better build velocity -# TODO: so we need to combine multiple targets + TARGET=$1 -git submodule update --init -MIN_IOS="13.0" -MIN_WATCHOS="5.0" -MIN_TVOS=$MIN_IOS -MIN_MACOS="10.15" -IPHONEOS=iphoneos -IPHONESIMULATOR=iphonesimulator -WATCHOS=watchos -WATCHSIMULATOR=watchsimulator -TVOS=appletvos -TVSIMULATOR=appletvsimulator -MACOS=macosx +MACOS="macosx" +IPHONEOS="iphoneos" +IPHONESIMULATOR="iphonesimulator" -LOGICALCPU_MAX=$(sysctl -n hw.logicalcpu_max) -BUILD=build - -version_min_flag() { - PLATFORM=$1 - FLAG="" - # shellcheck disable=SC2039 - # shellcheck disable=SC2053 - if [[ $PLATFORM = $IPHONEOS ]]; then - FLAG="-miphoneos-version-min=${MIN_IOS}" - elif [[ $PLATFORM = $IPHONESIMULATOR ]]; then - FLAG="-mios-simulator-version-min=${MIN_IOS}" - elif [[ $PLATFORM = $WATCHOS ]]; then - FLAG="-mwatchos-version-min=${MIN_WATCHOS}" - elif [[ $PLATFORM = $WATCHSIMULATOR ]]; then - FLAG="-mwatchos-simulator-version-min=${MIN_WATCHOS}" - elif [[ $PLATFORM = $TVOS ]]; then - FLAG="-mtvos-version-min=${MIN_TVOS}" - elif [[ $PLATFORM = $TVSIMULATOR ]]; then - FLAG="-mtvos-simulator-version-min=${MIN_TVOS}" - elif [[ $PLATFORM = $MACOS ]]; then - FLAG="-mmacosx-version-min=${MIN_MACOS}" - fi - echo $FLAG -} +BUILD="build" +LOGICALCPU_MAX=$(sysctl -n hw.logicalcpu_max) prepare() { - download_gmp() { - GMP_VERSION="6.3.0" - CURRENT_DIR=$(pwd) - echo "$CURRENT_DIR" - # shellcheck disable=SC2039,SC2164 - pushd ${BUILD} - mkdir -p "contrib" - if [ ! -s "contrib/gmp-${GMP_VERSION}.tar.bz2" ]; then - curl -L -o "contrib/gmp-${GMP_VERSION}.tar.bz2" https://ftp.gnu.org/gnu/gmp/gmp-${GMP_VERSION}.tar.bz2 - fi - rm -rf "contrib/gmp" - # shellcheck disable=SC2039,SC2164 - pushd contrib - tar xfj "gmp-${GMP_VERSION}.tar.bz2" - mv gmp-${GMP_VERSION} gmp - # shellcheck disable=SC2039,SC2164 - popd #contrib - # shellcheck disable=SC2039,SC2164 - popd #build - } + # shellcheck disable=SC2039,SC2164 + pushd ${BUILD} download_cmake_toolchain() { - if [ ! -s "${BUILD}/ios.toolchain.cmake" ]; then + if [ ! -s "ios.toolchain.cmake" ]; then SHA256_HASH="d02857ff6bd64f1d7109ca59c3e4f3b2f89d0663c412146e6977c679801b3243" - curl -o "${BUILD}/ios.toolchain.cmake" https://raw.githubusercontent.com/leetal/ios-cmake/c55677a4445b138c9ef2650d3c21f22cc78c2357/ios.toolchain.cmake - DOWNLOADED_HASH=$(shasum -a 256 ${BUILD}/ios.toolchain.cmake | cut -f 1 -d " ") - if [ $SHA256_HASH != "$DOWNLOADED_HASH" ]; then + echo "Downloading ios.toolchain.cmake" + curl -o "ios.toolchain.cmake" https://raw.githubusercontent.com/leetal/ios-cmake/c55677a4445b138c9ef2650d3c21f22cc78c2357/ios.toolchain.cmake + DOWNLOADED_HASH=$(shasum -a 256 ios.toolchain.cmake | cut -f 1 -d " ") + if [ "$SHA256_HASH" != "$DOWNLOADED_HASH" ]; then echo "Error: sha256 checksum of ios.toolchain.cmake mismatch" >&2 exit 1 fi fi } - download_relic() { - CURRENT_DIR=$(pwd) - echo "$CURRENT_DIR" - mkdir -p "${CURRENT_DIR}/${BUILD}/depends" - if [ ! -s "${CURRENT_DIR}/${BUILD}/depends/relic" ]; then - # shellcheck disable=SC2039,SC2164 - pushd "${CURRENT_DIR}/${BUILD}/depends" - git clone --depth 1 --branch "feat/ios-support" https://github.com/pankcuf/relic - # shellcheck disable=SC2039,SC2164 - pushd relic - git fetch --depth 1 origin 19fb6d79a77ade4ae8cd70d2b0ef7aab8720d1ae - git checkout 19fb6d79a77ade4ae8cd70d2b0ef7aab8720d1ae - # shellcheck disable=SC2039,SC2164 - popd #relic - # shellcheck disable=SC2039,SC2164 - popd #depends - fi - } - rm -rf ${BUILD} - mkdir -p ${BUILD} - download_relic - download_gmp download_cmake_toolchain -} -build_gmp_arch() { - PLATFORM=$1 - ARCH=$2 - PFX=${PLATFORM}-${ARCH} - # why this works with this host only? - HOST=aarch64-apple-darwin - # shellcheck disable=SC2039,SC2164 - pushd ${BUILD} - SDK=$(xcrun --sdk "$PLATFORM" --show-sdk-path) - PLATFORM_PATH=$(xcrun --sdk "$PLATFORM" --show-sdk-platform-path) - CLANG=$(xcrun --sdk "$PLATFORM" --find clang) - DEVELOPER=$(xcode-select --print-path) - CURRENT_DIR=$(pwd) - export PATH="${PLATFORM_PATH}/Developer/usr/bin:${DEVELOPER}/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin" - mkdir gmplib-"${PLATFORM}"-"${ARCH}" - CFLAGS="-Wno-unused-value -fembed-bitcode -arch ${ARCH} --sysroot=${SDK} $(version_min_flag "$PLATFORM")" - CONFIGURESCRIPT="gmp_configure_script.sh" - # shellcheck disable=SC2039,SC2164 - pushd contrib - # shellcheck disable=SC2039,SC2164 - pushd gmp - make clean || true - make distclean || true - echo "HOST: $HOST" - echo "PREFIX: ${CURRENT_DIR}/gmplib-${PFX}" - - cat >"$CONFIGURESCRIPT" << EOF -#!/bin/sh -./configure \ -CC="$CLANG" CFLAGS="$CFLAGS" CPPFLAGS="$CFLAGS" LDFLAGS="$CFLAGS" \ ---host=${HOST} --prefix="${CURRENT_DIR}/gmplib-${PFX}" \ ---disable-shared --enable-static --disable-assembly -v -EOF - - chmod a+x "$CONFIGURESCRIPT" - sh "$CONFIGURESCRIPT" - rm "$CONFIGURESCRIPT" - - # shellcheck disable=SC2039 - mkdir -p "${CURRENT_DIR}/log" - # shellcheck disable=SC2039 - make -j "$LOGICALCPU_MAX" &> "${CURRENT_DIR}"/log/gmplib-"${PFX}"-build.log - # shellcheck disable=SC2039 - make install &> "${CURRENT_DIR}"/log/gmplib-"${PFX}"-install.log - #make check - #exit 1 - # shellcheck disable=SC2039,SC2164 - popd # gmp - # shellcheck disable=SC2039,SC2164 - popd # contrib # shellcheck disable=SC2039,SC2164 popd # build } -build_relic_arch() { +# Maps (platform, arch) onto the leetal/ios-cmake PLATFORM value. +cmake_platform() { PLATFORM=$1 ARCH=$2 - PFX=${PLATFORM}-${ARCH} - - # shellcheck disable=SC2039,SC2164 - pushd ${BUILD} - - SDK=$(xcrun --sdk "$PLATFORM" --show-sdk-path) - - BUILDDIR=relic-"${PFX}" - TOOLCHAIN=$(pwd)/ios.toolchain.cmake - GMP_PFX=$(pwd)/gmplib-${PFX} - rm -rf "$BUILDDIR" - mkdir "$BUILDDIR" - # shellcheck disable=SC2039,SC2164 - pushd "$BUILDDIR" - - unset CC - # shellcheck disable=SC2155 - export CC=$(xcrun --sdk "${PLATFORM}" --find clang) - - WSIZE=0 - IOS_PLATFORM="" - OPTIMIZATIONFLAGS="" - DEPLOYMENT_TARGET="" - - # shellcheck disable=SC2039 - # shellcheck disable=SC2053 - if [[ $PLATFORM = $IPHONEOS ]]; then - if [[ $ARCH = "arm64" ]] || [[ $ARCH = "arm64e" ]]; then - IOS_PLATFORM=OS64 - DEPLOYMENT_TARGET=$MIN_IOS - WSIZE=64 - OPTIMIZATIONFLAGS=-fomit-frame-pointer - else - IOS_PLATFORM=OS - WSIZE=32 - fi - elif [[ $PLATFORM = $IPHONESIMULATOR ]]; then - if [[ $ARCH = "x86_64" ]]; then - IOS_PLATFORM=SIMULATOR64 - DEPLOYMENT_TARGET=$MIN_IOS - WSIZE=64 - OPTIMIZATIONFLAGS=-fomit-frame-pointer - elif [[ $ARCH = "arm64" ]]; then - IOS_PLATFORM=SIMULATORARM64 - DEPLOYMENT_TARGET=$MIN_IOS - WSIZE=64 - else - IOS_PLATFORM=SIMULATOR - WSIZE=32 - fi - elif [[ $PLATFORM = $WATCHOS ]]; then - IOS_PLATFORM=WATCHOS - DEPLOYMENT_TARGET=$MIN_WATCHOS - WSIZE=32 - elif [[ $PLATFORM = $WATCHSIMULATOR ]]; then - IOS_PLATFORM=SIMULATOR_WATCHOS - DEPLOYMENT_TARGET=$MIN_WATCHOS - WSIZE=32 - elif [[ $PLATFORM = $TVOS ]]; then - IOS_PLATFORM=TVOS - DEPLOYMENT_TARGET=$MIN_TVOS - WSIZE=64 - OPTIMIZATIONFLAGS=-fomit-frame-pointer - elif [[ $PLATFORM = $TVSIMULATOR ]]; then - IOS_PLATFORM=SIMULATOR_TVOS - #TODO - if [[ $ARCH = "arm64" ]] - then - IOS_PLATFORM=OS64 - fi - DEPLOYMENT_TARGET=$MIN_TVOS - WSIZE=64 - OPTIMIZATIONFLAGS=-fomit-frame-pointer - elif [[ $PLATFORM = $MACOS ]]; then - WSIZE=64 - IOS_PLATFORM=MAC - if [[ $ARCH = "arm64" ]] - then - IOS_PLATFORM=MAC_ARM64 - fi - DEPLOYMENT_TARGET=$MIN_MACOS - OPTIMIZATIONFLAGS=-fomit-frame-pointer + if [[ $PLATFORM = "$IPHONEOS" ]]; then + echo "OS64" + elif [[ $PLATFORM = "$IPHONESIMULATOR" && $ARCH = "x86_64" ]]; then + echo "SIMULATOR64" + elif [[ $PLATFORM = "$IPHONESIMULATOR" && $ARCH = "arm64" ]]; then + echo "SIMULATORARM64" + elif [[ $PLATFORM = "$MACOS" && $ARCH = "x86_64" ]]; then + echo "MAC" + elif [[ $PLATFORM = "$MACOS" && $ARCH = "arm64" ]]; then + echo "MAC_ARM64" fi - - COMPILER_ARGS="$(version_min_flag "$PLATFORM") -Wno-unused-functions" - - EXTRA_ARGS="-DOPSYS=NONE -DPLATFORM=$IOS_PLATFORM -DDEPLOYMENT_TARGET=$DEPLOYMENT_TARGET -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN" - - # shellcheck disable=SC2039 - if [[ $ARCH = "i386" ]]; then - EXTRA_ARGS+=" -DARCH=X86" - elif [[ $ARCH = "x86_64" ]]; then - EXTRA_ARGS+=" -DARCH=X64" - elif [[ $ARCH = "arm64" ]]; then - # Relic doesn't support aarch64 yet, "ARCH=ARM" is for ARM 32-bit architecture only - EXTRA_ARGS+=" -DIOS_ARCH=arm64 -DARCH=" - elif [[ $ARCH = "armv7s" ]]; then - EXTRA_ARGS+=" -DIOS_ARCH=armv7s -DARCH=ARM" - elif [[ $ARCH = "armv7k" ]]; then - EXTRA_ARGS+=" -DIOS_ARCH=armv7k -DARCH=ARM" - elif [[ $ARCH = "arm64_32" ]]; then - EXTRA_ARGS+=" -DIOS_ARCH=arm64_32 -DARCH=ARM" - fi - - CURRENT_DIR=$(pwd) - cmake -DCMAKE_PREFIX_PATH:PATH="${GMP_PFX}" -DTESTS=0 -DBENCH=0 -DBUILD_BLS_JS_BINDINGS=0 -DBUILD_BLS_PYTHON_BINDINGS=0 \ - -DBUILD_BLS_BENCHMARKS=0 -DBUILD_BLS_TESTS=0 -DCHECK=off -DARITH=gmp -DTIMER=HPROC -DFP_PRIME=381 -DMULTI=PTHREAD \ - -DFP_QNRES=on -DFP_METHD="INTEG;INTEG;INTEG;MONTY;EXGCD;SLIDE" -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" \ - -DCOMP_FLAGS="-pipe -std=c99 -O3 -funroll-loops $OPTIMIZATIONFLAGS -isysroot $SDK -arch $ARCH -fembed-bitcode ${COMPILER_ARGS}" \ - -DWSIZE=$WSIZE -DVERBS=off -DSHLIB=off -DALLOC="AUTO" -DEP_PLAIN=off -DEP_SUPER=off -DPP_EXT="LAZYR" \ - -DWITH="DV;BN;MD;FP;EP;FPX;EPX;PP;PC;CP" -DBN_METHD="COMBA;COMBA;MONTY;SLIDE;STEIN;BASIC" ${EXTRA_ARGS} ../../ - - make -j "$LOGICALCPU_MAX" - # shellcheck disable=SC2039,SC2164 - popd # "$BUILDDIR" - # shellcheck disable=SC2039,SC2164 - popd # depends/relic } build_bls_arch() { - # shellcheck disable=SC2039 - BLS_FILES=( "bls" "chaincode" "elements" "extendedprivatekey" "extendedpublickey" "legacy" "privatekey" "schemes" "threshold" ) - # shellcheck disable=SC2039 - ALL_BLS_OBJ_FILES=$(printf "%s.o " "${BLS_FILES[@]}") - PLATFORM=$1 ARCH=$2 PFX=${PLATFORM}-${ARCH} - SDK=$(xcrun --sdk "$PLATFORM" --show-sdk-path) - + CMAKE_PLATFORM=$(cmake_platform "$PLATFORM" "$ARCH") BUILDDIR=${BUILD}/bls-"${PFX}" - rm -rf "$BUILDDIR" - mkdir "$BUILDDIR" - # shellcheck disable=SC2039,SC2164 - pushd "$BUILDDIR" - - EXTRA_ARGS="$(version_min_flag "$PLATFORM")" - - CURRENT_DIR=$(pwd) - - # shellcheck disable=SC2039 - for F in "${BLS_FILES[@]}" - do - clang -I"../contrib/relic/include" \ - -I"../../depends/relic/include" \ - -I"../../include/dashbls" \ - -I"../relic-${PFX}/depends/relic/include" \ - -I"../../src/" \ - -I"../gmplib-${PFX}/include" \ - -x c++ -std=c++14 -stdlib=libc++ -fembed-bitcode -arch "${ARCH}" -isysroot "${SDK}" "${EXTRA_ARGS}" \ - -c "../../src/${F}.cpp" -o "${F}.o" - done - # shellcheck disable=SC2086 - xcrun -sdk "$PLATFORM" ar -cvq libbls.a $ALL_BLS_OBJ_FILES + rm -rf "$BUILDDIR" - # shellcheck disable=SC2039,SC2164 - popd # "$BUILDDIR" -} - -build_all_arch() { - PLATFORM=$1 - ARCH=$2 - build_gmp_arch "$PLATFORM" "$ARCH" - build_relic_arch "$PLATFORM" "$ARCH" - build_bls_arch "$PLATFORM" "$ARCH" + cmake -S . -B "$BUILDDIR" \ + -DCMAKE_TOOLCHAIN_FILE="$(pwd)/${BUILD}/ios.toolchain.cmake" \ + -DPLATFORM="${CMAKE_PLATFORM}" \ + -DDEPLOYMENT_TARGET=13.0 \ + -DENABLE_BITCODE=OFF \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_BLS_TESTS=0 \ + -DBUILD_BLS_BENCHMARKS=0 \ + -DBUILD_BLS_JS_BINDINGS=0 \ + -DBUILD_BLS_PYTHON_BINDINGS=0 + + cmake --build "$BUILDDIR" --parallel "$LOGICALCPU_MAX" --target dashbls } build_target() { @@ -356,19 +106,14 @@ build_target() { ARCH=arm64 PLATFORM=$MACOS fi - build_all_arch "$PLATFORM" "$ARCH" + build_bls_arch "$PLATFORM" "$ARCH" PFX="${PLATFORM}"-"${ARCH}" rm -rf "build/artefacts/${BUILD_IN}" mkdir -p "build/artefacts/${BUILD_IN}" - cp "build/gmplib-${PFX}/lib/libgmp.a" "build/artefacts/${BUILD_IN}" - cp "build/relic-${PFX}/depends/relic/lib/librelic_s.a" "build/artefacts/${BUILD_IN}" -# cp "build/relic-${PFX}/depends/sodium/libsodium.a" "build/artefacts/${BUILD_IN}" - cp "build/bls-${PFX}/libbls.a" "build/artefacts/${BUILD_IN}" -# cp -rf build/bls-"${PFX}"/*.o build/artefacts/"${BUILD_IN}"/include -# cp -rf src/*.hpp build/artefacts/"${BUILD_IN}"/include -# cp -rf build/gmplib-"${PFX}"/include/gmp.h build/artefacts/"${BUILD_IN}"/include -# cp -rf build/relic-"${PFX}"/_deps/relic-build/include/*.h build/artefacts/"${BUILD_IN}"/include + cp "build/bls-${PFX}/src/libdashbls.a" "build/artefacts/${BUILD_IN}" + cp "build/bls-${PFX}/depends/mimalloc/libmimalloc-secure.a" "build/artefacts/${BUILD_IN}" } +mkdir -p ${BUILD} prepare build_target "$TARGET" diff --git a/src/dashbls/autogen.sh b/src/dashbls/autogen.sh deleted file mode 100755 index f3e943e167db..000000000000 --- a/src/dashbls/autogen.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -export LC_ALL=C -set -e -srcdir="$(dirname "$0")" -cd "$srcdir" -if [ -z "${LIBTOOLIZE}" ] && GLIBTOOLIZE="$(command -v glibtoolize)"; then - LIBTOOLIZE="${GLIBTOOLIZE}" - export LIBTOOLIZE -fi -command -v autoreconf >/dev/null || \ - (echo "configuration failed, please install autoconf first" && exit 1) -autoreconf --install --force --warnings=all -autoheader --force --replace-handwritten || autoheader --force diff --git a/src/dashbls/binds/python/CMakeLists.txt b/src/dashbls/binds/python/CMakeLists.txt index 98a776e4b19e..9117ade8f3cf 100644 --- a/src/dashbls/binds/python/CMakeLists.txt +++ b/src/dashbls/binds/python/CMakeLists.txt @@ -6,7 +6,7 @@ if(NOT pybind11_FOUND) FetchContent_Declare( pybind11 GIT_REPOSITORY https://github.com/pybind/pybind11.git - GIT_TAG v2.13.6 + GIT_TAG v2.13.6 ) FetchContent_MakeAvailable(pybind11) endif() diff --git a/src/dashbls/binds/python/pythonbindings.cpp b/src/dashbls/binds/python/pythonbindings.cpp index b037a74d6aa6..0723e2b1bb2f 100644 --- a/src/dashbls/binds/python/pythonbindings.cpp +++ b/src/dashbls/binds/python/pythonbindings.cpp @@ -657,7 +657,6 @@ PYBIND11_MODULE(dashbls, m) return other * self; }, py::is_operator()) - .def( "__repr__", [](const G2Element &ele) { diff --git a/src/dashbls/build-aux/m4/ax_check_compile_flag.m4 b/src/dashbls/build-aux/m4/ax_check_compile_flag.m4 deleted file mode 100644 index bd753b34d7dc..000000000000 --- a/src/dashbls/build-aux/m4/ax_check_compile_flag.m4 +++ /dev/null @@ -1,53 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) -# -# DESCRIPTION -# -# Check whether the given FLAG works with the current language's compiler -# or gives an error. (Warnings, however, are ignored) -# -# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on -# success/failure. -# -# If EXTRA-FLAGS is defined, it is added to the current language's default -# flags (e.g. CFLAGS) when the check is done. The check is thus made with -# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to -# force the compiler to issue an error when a bad flag is given. -# -# INPUT gives an alternative input source to AC_COMPILE_IFELSE. -# -# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this -# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. -# -# LICENSE -# -# Copyright (c) 2008 Guido U. Draheim -# Copyright (c) 2011 Maarten Bosmans -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 6 - -AC_DEFUN([AX_CHECK_COMPILE_FLAG], -[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF -AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl -AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ - ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS - _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" - AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], - [AS_VAR_SET(CACHEVAR,[yes])], - [AS_VAR_SET(CACHEVAR,[no])]) - _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) -AS_VAR_IF(CACHEVAR,yes, - [m4_default([$2], :)], - [m4_default([$3], :)]) -AS_VAR_POPDEF([CACHEVAR])dnl -])dnl AX_CHECK_COMPILE_FLAGS diff --git a/src/dashbls/build-aux/m4/ax_check_link_flag.m4 b/src/dashbls/build-aux/m4/ax_check_link_flag.m4 deleted file mode 100644 index 03a30ce4c739..000000000000 --- a/src/dashbls/build-aux/m4/ax_check_link_flag.m4 +++ /dev/null @@ -1,53 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) -# -# DESCRIPTION -# -# Check whether the given FLAG works with the linker or gives an error. -# (Warnings, however, are ignored) -# -# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on -# success/failure. -# -# If EXTRA-FLAGS is defined, it is added to the linker's default flags -# when the check is done. The check is thus made with the flags: "LDFLAGS -# EXTRA-FLAGS FLAG". This can for example be used to force the linker to -# issue an error when a bad flag is given. -# -# INPUT gives an alternative input source to AC_LINK_IFELSE. -# -# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this -# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. -# -# LICENSE -# -# Copyright (c) 2008 Guido U. Draheim -# Copyright (c) 2011 Maarten Bosmans -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 6 - -AC_DEFUN([AX_CHECK_LINK_FLAG], -[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF -AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl -AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ - ax_check_save_flags=$LDFLAGS - LDFLAGS="$LDFLAGS $4 $1" - AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], - [AS_VAR_SET(CACHEVAR,[yes])], - [AS_VAR_SET(CACHEVAR,[no])]) - LDFLAGS=$ax_check_save_flags]) -AS_VAR_IF(CACHEVAR,yes, - [m4_default([$2], :)], - [m4_default([$3], :)]) -AS_VAR_POPDEF([CACHEVAR])dnl -])dnl AX_CHECK_LINK_FLAGS diff --git a/src/dashbls/build-aux/m4/ax_cxx_compile_stdcxx.m4 b/src/dashbls/build-aux/m4/ax_cxx_compile_stdcxx.m4 deleted file mode 100644 index 51a35054d08c..000000000000 --- a/src/dashbls/build-aux/m4/ax_cxx_compile_stdcxx.m4 +++ /dev/null @@ -1,1005 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) -# -# DESCRIPTION -# -# Check for baseline language coverage in the compiler for the specified -# version of the C++ standard. If necessary, add switches to CXX and -# CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for -# the respective C++ standard version. -# -# The second argument, if specified, indicates whether you insist on an -# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. -# -std=c++11). If neither is specified, you get whatever works, with -# preference for no added switch, and then for an extended mode. -# -# The third argument, if specified 'mandatory' or if left unspecified, -# indicates that baseline support for the specified C++ standard is -# required and that the macro should error out if no mode with that -# support is found. If specified 'optional', then configuration proceeds -# regardless, after defining HAVE_CXX${VERSION} if and only if a -# supporting mode is found. -# -# LICENSE -# -# Copyright (c) 2008 Benjamin Kosnik -# Copyright (c) 2012 Zack Weinberg -# Copyright (c) 2013 Roy Stogner -# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov -# Copyright (c) 2015 Paul Norman -# Copyright (c) 2015 Moritz Klammler -# Copyright (c) 2016, 2018 Krzesimir Nowak -# Copyright (c) 2019 Enji Cooper -# Copyright (c) 2020 Jason Merrill -# Copyright (c) 2021 Jörn Heusipp -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 14 - -dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro -dnl (serial version number 13). - -AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl - m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], - [$1], [14], [ax_cxx_compile_alternatives="14 1y"], - [$1], [17], [ax_cxx_compile_alternatives="17 1z"], - [$1], [20], [ax_cxx_compile_alternatives="20"], - [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl - m4_if([$2], [], [], - [$2], [ext], [], - [$2], [noext], [], - [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl - m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], - [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], - [$3], [optional], [ax_cxx_compile_cxx$1_required=false], - [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) - AC_LANG_PUSH([C++])dnl - ac_success=no - - m4_if([$2], [], [dnl - AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, - ax_cv_cxx_compile_cxx$1, - [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], - [ax_cv_cxx_compile_cxx$1=yes], - [ax_cv_cxx_compile_cxx$1=no])]) - if test x$ax_cv_cxx_compile_cxx$1 = xyes; then - ac_success=yes - fi]) - - m4_if([$2], [noext], [], [dnl - if test x$ac_success = xno; then - for alternative in ${ax_cxx_compile_alternatives}; do - switch="-std=gnu++${alternative}" - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, - $cachevar, - [ac_save_CXX="$CXX" - CXX="$CXX $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXX="$ac_save_CXX"]) - if eval test x\$$cachevar = xyes; then - CXX="$CXX $switch" - if test -n "$CXXCPP" ; then - CXXCPP="$CXXCPP $switch" - fi - ac_success=yes - break - fi - done - fi]) - - m4_if([$2], [ext], [], [dnl - if test x$ac_success = xno; then - dnl HP's aCC needs +std=c++11 according to: - dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf - dnl Cray's crayCC needs "-h std=c++11" - for alternative in ${ax_cxx_compile_alternatives}; do - for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, - $cachevar, - [ac_save_CXX="$CXX" - CXX="$CXX $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXX="$ac_save_CXX"]) - if eval test x\$$cachevar = xyes; then - CXX="$CXX $switch" - if test -n "$CXXCPP" ; then - CXXCPP="$CXXCPP $switch" - fi - ac_success=yes - break - fi - done - if test x$ac_success = xyes; then - break - fi - done - fi]) - AC_LANG_POP([C++]) - if test x$ax_cxx_compile_cxx$1_required = xtrue; then - if test x$ac_success = xno; then - AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) - fi - fi - if test x$ac_success = xno; then - HAVE_CXX$1=0 - AC_MSG_NOTICE([No compiler with C++$1 support was found]) - else - HAVE_CXX$1=1 - AC_DEFINE(HAVE_CXX$1,1, - [define if the compiler supports basic C++$1 syntax]) - fi - AC_SUBST(HAVE_CXX$1) -]) - - -dnl Test body for checking C++11 support - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 -) - -dnl Test body for checking C++14 support - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 -) - -dnl Test body for checking C++17 support - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 -) - -dnl Test body for checking C++20 support - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 -) - - -dnl Tests for new features in C++11 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ - -// If the compiler admits that it is not ready for C++11, why torture it? -// Hopefully, this will speed up the test. - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 201103L - -#error "This is not a C++11 compiler" - -#else - -namespace cxx11 -{ - - namespace test_static_assert - { - - template - struct check - { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); - }; - - } - - namespace test_final_override - { - - struct Base - { - virtual ~Base() {} - virtual void f() {} - }; - - struct Derived : public Base - { - virtual ~Derived() override {} - virtual void f() override {} - }; - - } - - namespace test_double_right_angle_brackets - { - - template < typename T > - struct check {}; - - typedef check single_type; - typedef check> double_type; - typedef check>> triple_type; - typedef check>>> quadruple_type; - - } - - namespace test_decltype - { - - int - f() - { - int a = 1; - decltype(a) b = 2; - return a + b; - } - - } - - namespace test_type_deduction - { - - template < typename T1, typename T2 > - struct is_same - { - static const bool value = false; - }; - - template < typename T > - struct is_same - { - static const bool value = true; - }; - - template < typename T1, typename T2 > - auto - add(T1 a1, T2 a2) -> decltype(a1 + a2) - { - return a1 + a2; - } - - int - test(const int c, volatile int v) - { - static_assert(is_same::value == true, ""); - static_assert(is_same::value == false, ""); - static_assert(is_same::value == false, ""); - auto ac = c; - auto av = v; - auto sumi = ac + av + 'x'; - auto sumf = ac + av + 1.0; - static_assert(is_same::value == true, ""); - static_assert(is_same::value == true, ""); - static_assert(is_same::value == true, ""); - static_assert(is_same::value == false, ""); - static_assert(is_same::value == true, ""); - return (sumf > 0.0) ? sumi : add(c, v); - } - - } - - namespace test_noexcept - { - - int f() { return 0; } - int g() noexcept { return 0; } - - static_assert(noexcept(f()) == false, ""); - static_assert(noexcept(g()) == true, ""); - - } - - namespace test_constexpr - { - - template < typename CharT > - unsigned long constexpr - strlen_c_r(const CharT *const s, const unsigned long acc) noexcept - { - return *s ? strlen_c_r(s + 1, acc + 1) : acc; - } - - template < typename CharT > - unsigned long constexpr - strlen_c(const CharT *const s) noexcept - { - return strlen_c_r(s, 0UL); - } - - static_assert(strlen_c("") == 0UL, ""); - static_assert(strlen_c("1") == 1UL, ""); - static_assert(strlen_c("example") == 7UL, ""); - static_assert(strlen_c("another\0example") == 7UL, ""); - - } - - namespace test_rvalue_references - { - - template < int N > - struct answer - { - static constexpr int value = N; - }; - - answer<1> f(int&) { return answer<1>(); } - answer<2> f(const int&) { return answer<2>(); } - answer<3> f(int&&) { return answer<3>(); } - - void - test() - { - int i = 0; - const int c = 0; - static_assert(decltype(f(i))::value == 1, ""); - static_assert(decltype(f(c))::value == 2, ""); - static_assert(decltype(f(0))::value == 3, ""); - } - - } - - namespace test_uniform_initialization - { - - struct test - { - static const int zero {}; - static const int one {1}; - }; - - static_assert(test::zero == 0, ""); - static_assert(test::one == 1, ""); - - } - - namespace test_lambdas - { - - void - test1() - { - auto lambda1 = [](){}; - auto lambda2 = lambda1; - lambda1(); - lambda2(); - } - - int - test2() - { - auto a = [](int i, int j){ return i + j; }(1, 2); - auto b = []() -> int { return '0'; }(); - auto c = [=](){ return a + b; }(); - auto d = [&](){ return c; }(); - auto e = [a, &b](int x) mutable { - const auto identity = [](int y){ return y; }; - for (auto i = 0; i < a; ++i) - a += b--; - return x + identity(a + b); - }(0); - return a + b + c + d + e; - } - - int - test3() - { - const auto nullary = [](){ return 0; }; - const auto unary = [](int x){ return x; }; - using nullary_t = decltype(nullary); - using unary_t = decltype(unary); - const auto higher1st = [](nullary_t f){ return f(); }; - const auto higher2nd = [unary](nullary_t f1){ - return [unary, f1](unary_t f2){ return f2(unary(f1())); }; - }; - return higher1st(nullary) + higher2nd(nullary)(unary); - } - - } - - namespace test_variadic_templates - { - - template - struct sum; - - template - struct sum - { - static constexpr auto value = N0 + sum::value; - }; - - template <> - struct sum<> - { - static constexpr auto value = 0; - }; - - static_assert(sum<>::value == 0, ""); - static_assert(sum<1>::value == 1, ""); - static_assert(sum<23>::value == 23, ""); - static_assert(sum<1, 2>::value == 3, ""); - static_assert(sum<5, 5, 11>::value == 21, ""); - static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); - - } - - // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae - // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function - // because of this. - namespace test_template_alias_sfinae - { - - struct foo {}; - - template - using member = typename T::member_type; - - template - void func(...) {} - - template - void func(member*) {} - - void test(); - - void test() { func(0); } - - } - -} // namespace cxx11 - -#endif // __cplusplus >= 201103L - -]]) - - -dnl Tests for new features in C++14 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ - -// If the compiler admits that it is not ready for C++14, why torture it? -// Hopefully, this will speed up the test. - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 201402L - -#error "This is not a C++14 compiler" - -#else - -namespace cxx14 -{ - - namespace test_polymorphic_lambdas - { - - int - test() - { - const auto lambda = [](auto&&... args){ - const auto istiny = [](auto x){ - return (sizeof(x) == 1UL) ? 1 : 0; - }; - const int aretiny[] = { istiny(args)... }; - return aretiny[0]; - }; - return lambda(1, 1L, 1.0f, '1'); - } - - } - - namespace test_binary_literals - { - - constexpr auto ivii = 0b0000000000101010; - static_assert(ivii == 42, "wrong value"); - - } - - namespace test_generalized_constexpr - { - - template < typename CharT > - constexpr unsigned long - strlen_c(const CharT *const s) noexcept - { - auto length = 0UL; - for (auto p = s; *p; ++p) - ++length; - return length; - } - - static_assert(strlen_c("") == 0UL, ""); - static_assert(strlen_c("x") == 1UL, ""); - static_assert(strlen_c("test") == 4UL, ""); - static_assert(strlen_c("another\0test") == 7UL, ""); - - } - - namespace test_lambda_init_capture - { - - int - test() - { - auto x = 0; - const auto lambda1 = [a = x](int b){ return a + b; }; - const auto lambda2 = [a = lambda1(x)](){ return a; }; - return lambda2(); - } - - } - - namespace test_digit_separators - { - - constexpr auto ten_million = 100'000'000; - static_assert(ten_million == 100000000, ""); - - } - - namespace test_return_type_deduction - { - - auto f(int& x) { return x; } - decltype(auto) g(int& x) { return x; } - - template < typename T1, typename T2 > - struct is_same - { - static constexpr auto value = false; - }; - - template < typename T > - struct is_same - { - static constexpr auto value = true; - }; - - int - test() - { - auto x = 0; - static_assert(is_same::value, ""); - static_assert(is_same::value, ""); - return x; - } - - } - -} // namespace cxx14 - -#endif // __cplusplus >= 201402L - -]]) - - -dnl Tests for new features in C++17 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ - -// If the compiler admits that it is not ready for C++17, why torture it? -// Hopefully, this will speed up the test. - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 201703L - -#error "This is not a C++17 compiler" - -#else - -#include -#include -#include - -namespace cxx17 -{ - - namespace test_constexpr_lambdas - { - - constexpr int foo = [](){return 42;}(); - - } - - namespace test::nested_namespace::definitions - { - - } - - namespace test_fold_expression - { - - template - int multiply(Args... args) - { - return (args * ... * 1); - } - - template - bool all(Args... args) - { - return (args && ...); - } - - } - - namespace test_extended_static_assert - { - - static_assert (true); - - } - - namespace test_auto_brace_init_list - { - - auto foo = {5}; - auto bar {5}; - - static_assert(std::is_same, decltype(foo)>::value); - static_assert(std::is_same::value); - } - - namespace test_typename_in_template_template_parameter - { - - template typename X> struct D; - - } - - namespace test_fallthrough_nodiscard_maybe_unused_attributes - { - - int f1() - { - return 42; - } - - [[nodiscard]] int f2() - { - [[maybe_unused]] auto unused = f1(); - - switch (f1()) - { - case 17: - f1(); - [[fallthrough]]; - case 42: - f1(); - } - return f1(); - } - - } - - namespace test_extended_aggregate_initialization - { - - struct base1 - { - int b1, b2 = 42; - }; - - struct base2 - { - base2() { - b3 = 42; - } - int b3; - }; - - struct derived : base1, base2 - { - int d; - }; - - derived d1 {{1, 2}, {}, 4}; // full initialization - derived d2 {{}, {}, 4}; // value-initialized bases - - } - - namespace test_general_range_based_for_loop - { - - struct iter - { - int i; - - int& operator* () - { - return i; - } - - const int& operator* () const - { - return i; - } - - iter& operator++() - { - ++i; - return *this; - } - }; - - struct sentinel - { - int i; - }; - - bool operator== (const iter& i, const sentinel& s) - { - return i.i == s.i; - } - - bool operator!= (const iter& i, const sentinel& s) - { - return !(i == s); - } - - struct range - { - iter begin() const - { - return {0}; - } - - sentinel end() const - { - return {5}; - } - }; - - void f() - { - range r {}; - - for (auto i : r) - { - [[maybe_unused]] auto v = i; - } - } - - } - - namespace test_lambda_capture_asterisk_this_by_value - { - - struct t - { - int i; - int foo() - { - return [*this]() - { - return i; - }(); - } - }; - - } - - namespace test_enum_class_construction - { - - enum class byte : unsigned char - {}; - - byte foo {42}; - - } - - namespace test_constexpr_if - { - - template - int f () - { - if constexpr(cond) - { - return 13; - } - else - { - return 42; - } - } - - } - - namespace test_selection_statement_with_initializer - { - - int f() - { - return 13; - } - - int f2() - { - if (auto i = f(); i > 0) - { - return 3; - } - - switch (auto i = f(); i + 4) - { - case 17: - return 2; - - default: - return 1; - } - } - - } - - namespace test_template_argument_deduction_for_class_templates - { - - template - struct pair - { - pair (T1 p1, T2 p2) - : m1 {p1}, - m2 {p2} - {} - - T1 m1; - T2 m2; - }; - - void f() - { - [[maybe_unused]] auto p = pair{13, 42u}; - } - - } - - namespace test_non_type_auto_template_parameters - { - - template - struct B - {}; - - B<5> b1; - B<'a'> b2; - - } - - namespace test_structured_bindings - { - - int arr[2] = { 1, 2 }; - std::pair pr = { 1, 2 }; - - auto f1() -> int(&)[2] - { - return arr; - } - - auto f2() -> std::pair& - { - return pr; - } - - struct S - { - int x1 : 2; - volatile double y1; - }; - - S f3() - { - return {}; - } - - auto [ x1, y1 ] = f1(); - auto& [ xr1, yr1 ] = f1(); - auto [ x2, y2 ] = f2(); - auto& [ xr2, yr2 ] = f2(); - const auto [ x3, y3 ] = f3(); - - } - - namespace test_exception_spec_type_system - { - - struct Good {}; - struct Bad {}; - - void g1() noexcept; - void g2(); - - template - Bad - f(T*, T*); - - template - Good - f(T1*, T2*); - - static_assert (std::is_same_v); - - } - - namespace test_inline_variables - { - - template void f(T) - {} - - template inline T g(T) - { - return T{}; - } - - template<> inline void f<>(int) - {} - - template<> int g<>(int) - { - return 5; - } - - } - -} // namespace cxx17 - -#endif // __cplusplus < 201703L - -]]) - - -dnl Tests for new features in C++20 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 202002L - -#error "This is not a C++20 compiler" - -#else - -#include - -namespace cxx20 -{ - -// As C++20 supports feature test macros in the standard, there is no -// immediate need to actually test for feature availability on the -// Autoconf side. - -} // namespace cxx20 - -#endif // __cplusplus < 202002L - -]]) diff --git a/src/dashbls/build-aux/m4/ax_pthread.m4 b/src/dashbls/build-aux/m4/ax_pthread.m4 deleted file mode 100644 index 9f35d139149f..000000000000 --- a/src/dashbls/build-aux/m4/ax_pthread.m4 +++ /dev/null @@ -1,522 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_pthread.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) -# -# DESCRIPTION -# -# This macro figures out how to build C programs using POSIX threads. It -# sets the PTHREAD_LIBS output variable to the threads library and linker -# flags, and the PTHREAD_CFLAGS output variable to any special C compiler -# flags that are needed. (The user can also force certain compiler -# flags/libs to be tested by setting these environment variables.) -# -# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is -# needed for multi-threaded programs (defaults to the value of CC -# respectively CXX otherwise). (This is necessary on e.g. AIX to use the -# special cc_r/CC_r compiler alias.) -# -# NOTE: You are assumed to not only compile your program with these flags, -# but also to link with them as well. For example, you might link with -# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS -# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS -# -# If you are only building threaded programs, you may wish to use these -# variables in your default LIBS, CFLAGS, and CC: -# -# LIBS="$PTHREAD_LIBS $LIBS" -# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" -# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" -# CC="$PTHREAD_CC" -# CXX="$PTHREAD_CXX" -# -# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant -# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to -# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). -# -# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the -# PTHREAD_PRIO_INHERIT symbol is defined when compiling with -# PTHREAD_CFLAGS. -# -# ACTION-IF-FOUND is a list of shell commands to run if a threads library -# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it -# is not found. If ACTION-IF-FOUND is not specified, the default action -# will define HAVE_PTHREAD. -# -# Please let the authors know if this macro fails on any platform, or if -# you have any other suggestions or comments. This macro was based on work -# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help -# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by -# Alejandro Forero Cuervo to the autoconf macro repository. We are also -# grateful for the helpful feedback of numerous users. -# -# Updated for Autoconf 2.68 by Daniel Richard G. -# -# LICENSE -# -# Copyright (c) 2008 Steven G. Johnson -# Copyright (c) 2011 Daniel Richard G. -# Copyright (c) 2019 Marc Stevens -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 31 - -AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) -AC_DEFUN([AX_PTHREAD], [ -AC_REQUIRE([AC_CANONICAL_HOST]) -AC_REQUIRE([AC_PROG_CC]) -AC_REQUIRE([AC_PROG_SED]) -AC_LANG_PUSH([C]) -ax_pthread_ok=no - -# We used to check for pthread.h first, but this fails if pthread.h -# requires special compiler flags (e.g. on Tru64 or Sequent). -# It gets checked for in the link test anyway. - -# First of all, check if the user has set any of the PTHREAD_LIBS, -# etcetera environment variables, and if threads linking works using -# them: -if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then - ax_pthread_save_CC="$CC" - ax_pthread_save_CFLAGS="$CFLAGS" - ax_pthread_save_LIBS="$LIBS" - AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) - AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"]) - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) - AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) - AC_MSG_RESULT([$ax_pthread_ok]) - if test "x$ax_pthread_ok" = "xno"; then - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" - fi - CC="$ax_pthread_save_CC" - CFLAGS="$ax_pthread_save_CFLAGS" - LIBS="$ax_pthread_save_LIBS" -fi - -# We must check for the threads library under a number of different -# names; the ordering is very important because some systems -# (e.g. DEC) have both -lpthread and -lpthreads, where one of the -# libraries is broken (non-POSIX). - -# Create a list of thread flags to try. Items with a "," contain both -# C compiler flags (before ",") and linker flags (after ","). Other items -# starting with a "-" are C compiler flags, and remaining items are -# library names, except for "none" which indicates that we try without -# any flags at all, and "pthread-config" which is a program returning -# the flags for the Pth emulation library. - -ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" - -# The ordering *is* (sometimes) important. Some notes on the -# individual items follow: - -# pthreads: AIX (must check this before -lpthread) -# none: in case threads are in libc; should be tried before -Kthread and -# other compiler flags to prevent continual compiler warnings -# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 -# (Note: HP C rejects this with "bad form for `-t' option") -# -pthreads: Solaris/gcc (Note: HP C also rejects) -# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads and -# -D_REENTRANT too), HP C (must be checked before -lpthread, which -# is present but should not be used directly; and before -mthreads, -# because the compiler interprets this as "-mt" + "-hreads") -# -mthreads: Mingw32/gcc, Lynx/gcc -# pthread: Linux, etcetera -# --thread-safe: KAI C++ -# pthread-config: use pthread-config program (for GNU Pth library) - -case $host_os in - - freebsd*) - - # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) - # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) - - ax_pthread_flags="-kthread lthread $ax_pthread_flags" - ;; - - hpux*) - - # From the cc(1) man page: "[-mt] Sets various -D flags to enable - # multi-threading and also sets -lpthread." - - ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" - ;; - - openedition*) - - # IBM z/OS requires a feature-test macro to be defined in order to - # enable POSIX threads at all, so give the user a hint if this is - # not set. (We don't define these ourselves, as they can affect - # other portions of the system API in unpredictable ways.) - - AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], - [ -# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) - AX_PTHREAD_ZOS_MISSING -# endif - ], - [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) - ;; - - solaris*) - - # On Solaris (at least, for some versions), libc contains stubbed - # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (N.B.: The stubs are missing - # pthread_cleanup_push, or rather a function called by this macro, - # so we could check for that, but who knows whether they'll stub - # that too in a future libc.) So we'll check first for the - # standard Solaris way of linking pthreads (-mt -lpthread). - - ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags" - ;; -esac - -# Are we compiling with Clang? - -AC_CACHE_CHECK([whether $CC is Clang], - [ax_cv_PTHREAD_CLANG], - [ax_cv_PTHREAD_CLANG=no - # Note that Autoconf sets GCC=yes for Clang as well as GCC - if test "x$GCC" = "xyes"; then - AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], - [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ -# if defined(__clang__) && defined(__llvm__) - AX_PTHREAD_CC_IS_CLANG -# endif - ], - [ax_cv_PTHREAD_CLANG=yes]) - fi - ]) -ax_pthread_clang="$ax_cv_PTHREAD_CLANG" - - -# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) - -# Note that for GCC and Clang -pthread generally implies -lpthread, -# except when -nostdlib is passed. -# This is problematic using libtool to build C++ shared libraries with pthread: -# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460 -# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333 -# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555 -# To solve this, first try -pthread together with -lpthread for GCC - -AS_IF([test "x$GCC" = "xyes"], - [ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"]) - -# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first - -AS_IF([test "x$ax_pthread_clang" = "xyes"], - [ax_pthread_flags="-pthread,-lpthread -pthread"]) - - -# The presence of a feature test macro requesting re-entrant function -# definitions is, on some systems, a strong hint that pthreads support is -# correctly enabled - -case $host_os in - darwin* | hpux* | linux* | osf* | solaris*) - ax_pthread_check_macro="_REENTRANT" - ;; - - aix*) - ax_pthread_check_macro="_THREAD_SAFE" - ;; - - *) - ax_pthread_check_macro="--" - ;; -esac -AS_IF([test "x$ax_pthread_check_macro" = "x--"], - [ax_pthread_check_cond=0], - [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) - - -if test "x$ax_pthread_ok" = "xno"; then -for ax_pthread_try_flag in $ax_pthread_flags; do - - case $ax_pthread_try_flag in - none) - AC_MSG_CHECKING([whether pthreads work without any flags]) - ;; - - *,*) - PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"` - PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"` - AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"]) - ;; - - -*) - AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) - PTHREAD_CFLAGS="$ax_pthread_try_flag" - ;; - - pthread-config) - AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) - AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) - PTHREAD_CFLAGS="`pthread-config --cflags`" - PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" - ;; - - *) - AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) - PTHREAD_LIBS="-l$ax_pthread_try_flag" - ;; - esac - - ax_pthread_save_CFLAGS="$CFLAGS" - ax_pthread_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - - # Check for various functions. We must include pthread.h, - # since some functions may be macros. (On the Sequent, we - # need a special flag -Kthread to make this header compile.) - # We check for pthread_join because it is in -lpthread on IRIX - # while pthread_create is in libc. We check for pthread_attr_init - # due to DEC craziness with -lpthreads. We check for - # pthread_cleanup_push because it is one of the few pthread - # functions on Solaris that doesn't have a non-functional libc stub. - # We try pthread_create on general principles. - - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include -# if $ax_pthread_check_cond -# error "$ax_pthread_check_macro must be defined" -# endif - static void *some_global = NULL; - static void routine(void *a) - { - /* To avoid any unused-parameter or - unused-but-set-parameter warning. */ - some_global = a; - } - static void *start_routine(void *a) { return a; }], - [pthread_t th; pthread_attr_t attr; - pthread_create(&th, 0, start_routine, 0); - pthread_join(th, 0); - pthread_attr_init(&attr); - pthread_cleanup_push(routine, 0); - pthread_cleanup_pop(0) /* ; */])], - [ax_pthread_ok=yes], - []) - - CFLAGS="$ax_pthread_save_CFLAGS" - LIBS="$ax_pthread_save_LIBS" - - AC_MSG_RESULT([$ax_pthread_ok]) - AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) - - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" -done -fi - - -# Clang needs special handling, because older versions handle the -pthread -# option in a rather... idiosyncratic way - -if test "x$ax_pthread_clang" = "xyes"; then - - # Clang takes -pthread; it has never supported any other flag - - # (Note 1: This will need to be revisited if a system that Clang - # supports has POSIX threads in a separate library. This tends not - # to be the way of modern systems, but it's conceivable.) - - # (Note 2: On some systems, notably Darwin, -pthread is not needed - # to get POSIX threads support; the API is always present and - # active. We could reasonably leave PTHREAD_CFLAGS empty. But - # -pthread does define _REENTRANT, and while the Darwin headers - # ignore this macro, third-party headers might not.) - - # However, older versions of Clang make a point of warning the user - # that, in an invocation where only linking and no compilation is - # taking place, the -pthread option has no effect ("argument unused - # during compilation"). They expect -pthread to be passed in only - # when source code is being compiled. - # - # Problem is, this is at odds with the way Automake and most other - # C build frameworks function, which is that the same flags used in - # compilation (CFLAGS) are also used in linking. Many systems - # supported by AX_PTHREAD require exactly this for POSIX threads - # support, and in fact it is often not straightforward to specify a - # flag that is used only in the compilation phase and not in - # linking. Such a scenario is extremely rare in practice. - # - # Even though use of the -pthread flag in linking would only print - # a warning, this can be a nuisance for well-run software projects - # that build with -Werror. So if the active version of Clang has - # this misfeature, we search for an option to squash it. - - AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], - [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], - [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown - # Create an alternate version of $ac_link that compiles and - # links in two steps (.c -> .o, .o -> exe) instead of one - # (.c -> exe), because the warning occurs only in the second - # step - ax_pthread_save_ac_link="$ac_link" - ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' - ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"` - ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" - ax_pthread_save_CFLAGS="$CFLAGS" - for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do - AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) - CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" - ac_link="$ax_pthread_save_ac_link" - AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], - [ac_link="$ax_pthread_2step_ac_link" - AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], - [break]) - ]) - done - ac_link="$ax_pthread_save_ac_link" - CFLAGS="$ax_pthread_save_CFLAGS" - AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) - ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" - ]) - - case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in - no | unknown) ;; - *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; - esac - -fi # $ax_pthread_clang = yes - - - -# Various other checks: -if test "x$ax_pthread_ok" = "xyes"; then - ax_pthread_save_CFLAGS="$CFLAGS" - ax_pthread_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - - # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. - AC_CACHE_CHECK([for joinable pthread attribute], - [ax_cv_PTHREAD_JOINABLE_ATTR], - [ax_cv_PTHREAD_JOINABLE_ATTR=unknown - for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], - [int attr = $ax_pthread_attr; return attr /* ; */])], - [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], - []) - done - ]) - AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ - test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ - test "x$ax_pthread_joinable_attr_defined" != "xyes"], - [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], - [$ax_cv_PTHREAD_JOINABLE_ATTR], - [Define to necessary symbol if this constant - uses a non-standard name on your system.]) - ax_pthread_joinable_attr_defined=yes - ]) - - AC_CACHE_CHECK([whether more special flags are required for pthreads], - [ax_cv_PTHREAD_SPECIAL_FLAGS], - [ax_cv_PTHREAD_SPECIAL_FLAGS=no - case $host_os in - solaris*) - ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" - ;; - esac - ]) - AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ - test "x$ax_pthread_special_flags_added" != "xyes"], - [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" - ax_pthread_special_flags_added=yes]) - - AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], - [ax_cv_PTHREAD_PRIO_INHERIT], - [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[int i = PTHREAD_PRIO_INHERIT; - return i;]])], - [ax_cv_PTHREAD_PRIO_INHERIT=yes], - [ax_cv_PTHREAD_PRIO_INHERIT=no]) - ]) - AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ - test "x$ax_pthread_prio_inherit_defined" != "xyes"], - [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) - ax_pthread_prio_inherit_defined=yes - ]) - - CFLAGS="$ax_pthread_save_CFLAGS" - LIBS="$ax_pthread_save_LIBS" - - # More AIX lossage: compile with *_r variant - if test "x$GCC" != "xyes"; then - case $host_os in - aix*) - AS_CASE(["x/$CC"], - [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], - [#handle absolute path differently from PATH based program lookup - AS_CASE(["x$CC"], - [x/*], - [ - AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"]) - AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])]) - ], - [ - AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC]) - AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])]) - ] - ) - ]) - ;; - esac - fi -fi - -test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" -test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX" - -AC_SUBST([PTHREAD_LIBS]) -AC_SUBST([PTHREAD_CFLAGS]) -AC_SUBST([PTHREAD_CC]) -AC_SUBST([PTHREAD_CXX]) - -# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test "x$ax_pthread_ok" = "xyes"; then - ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) - : -else - ax_pthread_ok=no - $2 -fi -AC_LANG_POP -])dnl AX_PTHREAD diff --git a/src/dashbls/cmake_modules/Findgmp.cmake b/src/dashbls/cmake_modules/Findgmp.cmake deleted file mode 100644 index 3e59ede0a4f3..000000000000 --- a/src/dashbls/cmake_modules/Findgmp.cmake +++ /dev/null @@ -1,103 +0,0 @@ -# Try to find the GMP library -# https://gmplib.org/ -# -# This module supports requiring a minimum version, e.g. you can do -# find_package(GMP 6.0.0) -# to require version 6.0.0 to newer of GMP. -# -# Once done this will define -# -# GMP_FOUND - system has GMP lib with correct version -# GMP_INCLUDES - the GMP include directory -# GMP_LIBRARIES - the GMP library -# GMP_VERSION - GMP version -# -# Copyright (c) 2016 Jack Poulson, -# Redistribution and use is allowed according to the terms of the BSD license. - -include(BrewHelper) -find_brew_prefix(_GMP_BREW_HINT gmp) - -find_path(GMP_INCLUDES - NAMES - gmp.h - PATHS - $ENV{GMPDIR} ${INCLUDE_INSTALL_DIR} - PATH_SUFFIXES - include - HINTS - ${_GMP_BREW_HINT} -) - -# Set GMP_FIND_VERSION to 5.1.0 if no minimum version is specified -if(NOT GMP_FIND_VERSION) - if(NOT GMP_FIND_VERSION_MAJOR) - set(GMP_FIND_VERSION_MAJOR 5) - endif() - if(NOT GMP_FIND_VERSION_MINOR) - set(GMP_FIND_VERSION_MINOR 1) - endif() - if(NOT GMP_FIND_VERSION_PATCH) - set(GMP_FIND_VERSION_PATCH 0) - endif() - set(GMP_FIND_VERSION - "${GMP_FIND_VERSION_MAJOR}.${GMP_FIND_VERSION_MINOR}.${GMP_FIND_VERSION_PATCH}") -endif() - -message("GMP_INCLUDES=${GMP_INCLUDES}") -if(GMP_INCLUDES) - # Since the GMP version macros may be in a file included by gmp.h of the form - # gmp-.*[_]?.*.h (e.g., gmp-x86_64.h), we search each of them. - file(GLOB GMP_HEADERS "${GMP_INCLUDES}/gmp.h" "${GMP_INCLUDES}/gmp-*.h") - foreach(gmp_header_filename ${GMP_HEADERS}) - file(READ "${gmp_header_filename}" _gmp_version_header) - string(REGEX MATCH - "define[ \t]+__GNU_MP_VERSION[ \t]+([0-9]+)" _gmp_major_version_match - "${_gmp_version_header}") - if(_gmp_major_version_match) - set(GMP_MAJOR_VERSION "${CMAKE_MATCH_1}") - string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_MINOR[ \t]+([0-9]+)" - _gmp_minor_version_match "${_gmp_version_header}") - set(GMP_MINOR_VERSION "${CMAKE_MATCH_1}") - string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_PATCHLEVEL[ \t]+([0-9]+)" - _gmp_patchlevel_version_match "${_gmp_version_header}") - set(GMP_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") - set(GMP_VERSION - ${GMP_MAJOR_VERSION}.${GMP_MINOR_VERSION}.${GMP_PATCHLEVEL_VERSION}) - endif() - endforeach() - - # Check whether found version exists and exceeds the minimum requirement - if(NOT GMP_VERSION) - set(GMP_VERSION_OK FALSE) - message(STATUS "GMP version was not detected") - elseif(${GMP_VERSION} VERSION_LESS ${GMP_FIND_VERSION}) - set(GMP_VERSION_OK FALSE) - message(STATUS "GMP version ${GMP_VERSION} found in ${GMP_INCLUDES}, " - "but at least version ${GMP_FIND_VERSION} is required") - else() - set(GMP_VERSION_OK TRUE) - endif() -endif() - -if(STBIN) - set(_gmp_lib_name libgmp.a) -else() - set(_gmp_lib_name libgmp.so) -endif() - -find_library(GMP_LIBRARIES - NAMES - ${_gmp_lib_name} gmp.lib libgmp-10 libgmp gmp - HINTS - ${_GMP_BREW_HINT} - INCLUDE_DIRS - ${GMP_INCLUDES} - PATHS - $ENV{GMPDIR} ${LIB_INSTALL_DIR} -) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(gmp DEFAULT_MSG - GMP_INCLUDES GMP_LIBRARIES GMP_VERSION_OK) -mark_as_advanced(GMP_INCLUDES GMP_LIBRARIES) diff --git a/src/dashbls/cmake_modules/Findsodium.cmake b/src/dashbls/cmake_modules/Findsodium.cmake deleted file mode 100644 index 0350b67fce9b..000000000000 --- a/src/dashbls/cmake_modules/Findsodium.cmake +++ /dev/null @@ -1,294 +0,0 @@ -# Written in 2016 by Henrik Steffen Gaßmann -# -# To the extent possible under law, the author(s) have dedicated all -# copyright and related and neighboring rights to this software to the -# public domain worldwide. This software is distributed without any warranty. -# -# You should have received a copy of the CC0 Public Domain Dedication -# along with this software. If not, see -# -# http://creativecommons.org/publicdomain/zero/1.0/ -# -######################################################################## -# Tries to find the local libsodium installation. -# -# On Windows the sodium_DIR environment variable is used as a default -# hint which can be overridden by setting the corresponding cmake variable. -# -# Once done the following variables will be defined: -# -# sodium_FOUND -# sodium_INCLUDE_DIR -# sodium_LIBRARY_DEBUG -# sodium_LIBRARY_RELEASE -# -# -# Furthermore an imported "sodium" target is created. -# - -if (CMAKE_C_COMPILER_ID STREQUAL "GNU" - OR CMAKE_C_COMPILER_ID STREQUAL "Clang") - set(_GCC_COMPATIBLE 1) -endif() - -# static library option -if (NOT DEFINED sodium_USE_STATIC_LIBS) - option(sodium_USE_STATIC_LIBS "enable to statically link against sodium" OFF) -endif() -if(NOT (sodium_USE_STATIC_LIBS EQUAL sodium_USE_STATIC_LIBS_LAST)) - unset(sodium_LIBRARY CACHE) - unset(sodium_LIBRARY_DEBUG CACHE) - unset(sodium_LIBRARY_RELEASE CACHE) - unset(sodium_DLL_DEBUG CACHE) - unset(sodium_DLL_RELEASE CACHE) - set(sodium_USE_STATIC_LIBS_LAST ${sodium_USE_STATIC_LIBS} CACHE INTERNAL "internal change tracking variable") -endif() - - -######################################################################## -# UNIX -if (UNIX) - # import pkg-config - find_package(PkgConfig QUIET) - if (PKG_CONFIG_FOUND) - pkg_check_modules(sodium_PKG QUIET libsodium) - endif() - - if(sodium_USE_STATIC_LIBS) - foreach(_libname ${sodium_PKG_STATIC_LIBRARIES}) - if (NOT _libname MATCHES "^lib.*\\.a$") # ignore strings already ending with .a - list(INSERT sodium_PKG_STATIC_LIBRARIES 0 "lib${_libname}.a") - endif() - endforeach() - list(REMOVE_DUPLICATES sodium_PKG_STATIC_LIBRARIES) - - # if pkgconfig for libsodium doesn't provide - # static lib info, then override PKG_STATIC here.. - if (NOT sodium_PKG_STATIC_FOUND) - set(sodium_PKG_STATIC_LIBRARIES libsodium.a) - endif() - - set(XPREFIX sodium_PKG_STATIC) - else() - if (NOT sodium_PKG_FOUND) - set(sodium_PKG_LIBRARIES sodium) - endif() - - set(XPREFIX sodium_PKG) - endif() - - find_path(sodium_INCLUDE_DIR sodium.h - HINTS ${${XPREFIX}_INCLUDE_DIRS} - ) - find_library(sodium_LIBRARY_DEBUG NAMES ${${XPREFIX}_LIBRARIES} - HINTS ${${XPREFIX}_LIBRARY_DIRS} - ) - find_library(sodium_LIBRARY_RELEASE NAMES ${${XPREFIX}_LIBRARIES} - HINTS ${${XPREFIX}_LIBRARY_DIRS} - ) - - -######################################################################## -# Windows -elseif (WIN32) - set(sodium_DIR "$ENV{sodium_DIR}" CACHE FILEPATH "sodium install directory") - mark_as_advanced(sodium_DIR) - - find_path(sodium_INCLUDE_DIR sodium.h - HINTS ${sodium_DIR} - PATH_SUFFIXES include - ) - - if (MSVC) - # detect target architecture - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/arch.cpp" [=[ - #if defined _M_IX86 - #error ARCH_VALUE x86_32 - #elif defined _M_X64 - #error ARCH_VALUE x86_64 - #endif - #error ARCH_VALUE unknown - ]=]) - try_compile(_UNUSED_VAR "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/arch.cpp" - OUTPUT_VARIABLE _COMPILATION_LOG - ) - string(REGEX REPLACE ".*ARCH_VALUE ([a-zA-Z0-9_]+).*" "\\1" _TARGET_ARCH "${_COMPILATION_LOG}") - - # construct library path - if (_TARGET_ARCH STREQUAL "x86_32") - string(APPEND _PLATFORM_PATH "Win32") - elseif(_TARGET_ARCH STREQUAL "x86_64") - string(APPEND _PLATFORM_PATH "x64") - else() - message(FATAL_ERROR "the ${_TARGET_ARCH} architecture is not supported by Findsodium.cmake.") - endif() - string(APPEND _PLATFORM_PATH "/$$CONFIG$$") - - if (MSVC_VERSION LESS 1900) - math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 60") - else() - math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 50") - endif() - string(APPEND _PLATFORM_PATH "/v${_VS_VERSION}") - - if (sodium_USE_STATIC_LIBS) - string(APPEND _PLATFORM_PATH "/static") - else() - string(APPEND _PLATFORM_PATH "/dynamic") - endif() - - string(REPLACE "$$CONFIG$$" "Debug" _DEBUG_PATH_SUFFIX "${_PLATFORM_PATH}") - string(REPLACE "$$CONFIG$$" "Release" _RELEASE_PATH_SUFFIX "${_PLATFORM_PATH}") - - find_library(sodium_LIBRARY_DEBUG libsodium.lib - HINTS ${sodium_DIR} - PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX} - ) - find_library(sodium_LIBRARY_RELEASE libsodium.lib - HINTS ${sodium_DIR} - PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX} - ) - if (NOT sodium_USE_STATIC_LIBS) - set(CMAKE_FIND_LIBRARY_SUFFIXES_BCK ${CMAKE_FIND_LIBRARY_SUFFIXES}) - set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll") - find_library(sodium_DLL_DEBUG libsodium - HINTS ${sodium_DIR} - PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX} - ) - find_library(sodium_DLL_RELEASE libsodium - HINTS ${sodium_DIR} - PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX} - ) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_BCK}) - endif() - - elseif(_GCC_COMPATIBLE) - if (sodium_USE_STATIC_LIBS) - find_library(sodium_LIBRARY_DEBUG libsodium.a - HINTS ${sodium_DIR} - PATH_SUFFIXES lib - ) - find_library(sodium_LIBRARY_RELEASE libsodium.a - HINTS ${sodium_DIR} - PATH_SUFFIXES lib - ) - else() - find_library(sodium_LIBRARY_DEBUG libsodium.dll.a - HINTS ${sodium_DIR} - PATH_SUFFIXES lib - ) - find_library(sodium_LIBRARY_RELEASE libsodium.dll.a - HINTS ${sodium_DIR} - PATH_SUFFIXES lib - ) - - file(GLOB _DLL - LIST_DIRECTORIES false - RELATIVE "${sodium_DIR}/bin" - "${sodium_DIR}/bin/libsodium*.dll" - ) - find_library(sodium_DLL_DEBUG ${_DLL} libsodium - HINTS ${sodium_DIR} - PATH_SUFFIXES bin - ) - find_library(sodium_DLL_RELEASE ${_DLL} libsodium - HINTS ${sodium_DIR} - PATH_SUFFIXES bin - ) - endif() - else() - message(FATAL_ERROR "this platform is not supported by FindSodium.cmake") - endif() - - -######################################################################## -# unsupported -else() - message(FATAL_ERROR "this platform is not supported by FindSodium.cmake") -endif() - - -######################################################################## -# common stuff - -# extract sodium version -if (sodium_INCLUDE_DIR) - set(_VERSION_HEADER "${_INCLUDE_DIR}/sodium/version.h") - if (EXISTS _VERSION_HEADER) - file(READ "${_VERSION_HEADER}" _VERSION_HEADER_CONTENT) - string(REGEX REPLACE ".*#[ \t]*define[ \t]*SODIUM_VERSION_STRING[ \t]*\"([^\n]*)\".*" "\\1" - sodium_VERSION "${_VERSION_HEADER_CONTENT}") - set(sodium_VERSION "${sodium_VERSION}" PARENT_SCOPE) - endif() -endif() - -# communicate results -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args( - sodium # The name must be either uppercase or match the filename case. - REQUIRED_VARS - sodium_LIBRARY_RELEASE - sodium_LIBRARY_DEBUG - sodium_INCLUDE_DIR - VERSION_VAR - sodium_VERSION -) - -if(Sodium_FOUND) - set(sodium_LIBRARIES - optimized ${sodium_LIBRARY_RELEASE} debug ${sodium_LIBRARY_DEBUG}) -endif() - -# mark file paths as advanced -mark_as_advanced(sodium_INCLUDE_DIR) -mark_as_advanced(sodium_LIBRARY_DEBUG) -mark_as_advanced(sodium_LIBRARY_RELEASE) -if (WIN32) - mark_as_advanced(sodium_DLL_DEBUG) - mark_as_advanced(sodium_DLL_RELEASE) -endif() - -# create imported target -if(sodium_USE_STATIC_LIBS) - set(_LIB_TYPE STATIC) -else() - set(_LIB_TYPE SHARED) -endif() -add_library(sodium ${_LIB_TYPE} IMPORTED) - -set_target_properties(sodium PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${sodium_INCLUDE_DIR}" - IMPORTED_LINK_INTERFACE_LANGUAGES "C" -) - -if (sodium_USE_STATIC_LIBS) - set_target_properties(sodium PROPERTIES - INTERFACE_COMPILE_DEFINITIONS "SODIUM_STATIC" - IMPORTED_LOCATION "${sodium_LIBRARY_RELEASE}" - IMPORTED_LOCATION_DEBUG "${sodium_LIBRARY_DEBUG}" - ) -else() - if (UNIX) - set_target_properties(sodium PROPERTIES - IMPORTED_LOCATION "${sodium_LIBRARY_RELEASE}" - IMPORTED_LOCATION_DEBUG "${sodium_LIBRARY_DEBUG}" - ) - elseif (WIN32) - set_target_properties(sodium PROPERTIES - IMPORTED_IMPLIB "${sodium_LIBRARY_RELEASE}" - IMPORTED_IMPLIB_DEBUG "${sodium_LIBRARY_DEBUG}" - ) - if (NOT (sodium_DLL_DEBUG MATCHES ".*-NOTFOUND")) - set_target_properties(sodium PROPERTIES - IMPORTED_LOCATION_DEBUG "${sodium_DLL_DEBUG}" - ) - endif() - if (NOT (sodium_DLL_RELEASE MATCHES ".*-NOTFOUND")) - set_target_properties(sodium PROPERTIES - IMPORTED_LOCATION_RELWITHDEBINFO "${sodium_DLL_RELEASE}" - IMPORTED_LOCATION_MINSIZEREL "${sodium_DLL_RELEASE}" - IMPORTED_LOCATION_RELEASE "${sodium_DLL_RELEASE}" - ) - endif() - endif() -endif() diff --git a/src/dashbls/configure.ac b/src/dashbls/configure.ac deleted file mode 100644 index 9878a39ec174..000000000000 --- a/src/dashbls/configure.ac +++ /dev/null @@ -1,913 +0,0 @@ -AC_PREREQ([2.60]) -AC_INIT([libdashbls],[2.1]) -AC_CONFIG_AUX_DIR([build-aux]) -AC_CONFIG_MACRO_DIR([build-aux/m4]) - -dnl Unless the user specified ARFLAGS, force it to be cr -AC_ARG_VAR(ARFLAGS, [Flags for the archiver, defaults to if not set]) -if test "x${ARFLAGS+set}" != "xset"; then - ARFLAGS="qc" -fi - -AC_CANONICAL_HOST - -AH_TOP([#ifndef RLC_CONF_H]) -AH_TOP([#define RLC_CONF_H]) -AH_BOTTOM([#endif /*RLC_CONF_H*/]) -AM_INIT_AUTOMAKE([foreign no-define subdir-objects]) - -dnl faketime messes with timestamps and causes configure to be re-run. -dnl --disable-maintainer-mode can be used to bypass this. -AM_MAINTAINER_MODE([enable]) - -dnl make the compilation flags quiet unless V=1 is used -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) - -dnl Compiler checks (here before libtool). -if test "x${CFLAGS+set}" = "xset"; then - CFLAGS_overridden=yes -else - CFLAGS_overridden=no -fi -if test "x${CXXFLAGS+set}" = "xset"; then - CXXFLAGS_overridden=yes -else - CXXFLAGS_overridden=no -fi - -AC_PROG_CC - -AC_PROG_CXX - -dnl By default, libtool for mingw refuses to link static libs into a dll for -dnl fear of mixing pic/non-pic objects, and import/export complications. Since -dnl we have those under control, re-enable that functionality. -case $host in - *mingw*) - lt_cv_deplibs_check_method="pass_all" - ;; -esac -dnl Require C++14 compiler (no GNU extensions) -AX_CXX_COMPILE_STDCXX([14], [noext], [mandatory], [nodefault]) - -dnl Libtool init checks. -LT_INIT([pic-only]) - -AC_PATH_TOOL(AR, ar) -AC_PATH_TOOL(RANLIB, ranlib) -AC_PATH_TOOL(STRIP, strip) - -AM_PROG_AS - -AC_ARG_ENABLE([tests], - [AS_HELP_STRING([--enable-tests], - [Compile with tests [default=yes]])], - [use_tests=$enableval], - [use_tests=yes]) - -AC_ARG_ENABLE([bench], - [AS_HELP_STRING([--enable-bench], - [Compile with benchmarks [default=yes]])], - [use_bench=$enableval], - [use_bench=yes]) - -AC_ARG_ENABLE([hardening], - [AS_HELP_STRING([--enable-hardening], - [Enable hardening flags and arguments [default=auto]])], - [use_hardening=$enableval], - [use_hardening=auto]) - -AC_ARG_ENABLE([optimizations], - [AS_HELP_STRING([--enable-optimizations], - [Enable compiler and library optimizations [default=yes]])], - [use_optimizations=$enableval], - [use_optimizations=yes]) - -AC_ARG_ENABLE([debug], - [AS_HELP_STRING([--enable-debug], - [Build with debugging support [default=no]])], - [use_debug=$enableval], - [use_debug=no]) - -AC_LANG_PUSH([C]) - -dnl Check for a flag to turn compiler warnings into errors. This is helpful for checks which may -dnl appear to succeed because by default they merely emit warnings when they fail. -dnl -dnl Note that this is not necessarily a check to see if -Werror is supported, but rather to see if -dnl a compile with -Werror can succeed. This is important because the compiler may already be -dnl warning about something unrelated, for example about some path issue. If that is the case, -dnl -Werror cannot be used because all of those warnings would be turned into errors. -AX_CHECK_COMPILE_FLAG([-Werror], [FLAG_WERROR="-Werror"], [FLAG_WERROR=""]) - -if test x"$use_debug" = x"yes" -o x"$use_optimizations" = x"no"; then - dnl Clear default -g -O2 flags - if test x"$CFLAGS_overridden" = x"no"; then - CFLAGS="" - fi - if test x"$CXXFLAGS_overridden" = x"no"; then - CXXFLAGS="" - fi - - dnl Disable optimizations - AX_CHECK_COMPILE_FLAG([-O0], [[DEBUG_FLAGS="$DEBUG_FLAGS -O0"]], [], [[$FLAG_WERROR]]) - - if test x"$use_debug" = x"yes"; then - dnl Prefer -g3, fall back to -g if that is unavailable. - AX_CHECK_COMPILE_FLAG( - [-g3], - [[DEBUG_FLAGS="$DEBUG_FLAGS -g3"]], - [AX_CHECK_COMPILE_FLAG([-g],[[DEBUG_FLAGS="$DEBUG_FLAGS -g"]])], [[$FLAG_WERROR]]) - - AX_CHECK_COMPILE_FLAG([-ftrapv],[DEBUG_FLAGS="$DEBUG_FLAGS -ftrapv"], [], [[$FLAG_WERROR]]) - else - dnl Reintroduce -g flag deleted during C(XX)FLAGS reset - AX_CHECK_COMPILE_FLAG([-g],[[DEBUG_FLAGS="$DEBUG_FLAGS -g"]], [], [[$FLAG_WERROR]]) - - dnl -ftrapv and -fwrapv conflict, so we only set this if use_debug=no - AX_CHECK_COMPILE_FLAG([-fwrapv],[DEBUG_FLAGS="$DEBUG_FLAGS -fwrapv"], [], [[$FLAG_WERROR]]) - fi -fi - -dnl Define enum mappings for relic config -AC_DEFINE([RLC_VERSION], ["0.5.0"], [Relic Version]) - -dnl dashbls: Library processor architecture -AC_DEFINE([AVR], [1], [Atmel AVR ATMega128 8-bit architecture.]) -AC_DEFINE([MSP], [2], [MSP430 16-bit architecture.]) -AC_DEFINE([ARM], [3], [ARM 32-bit architecture.]) -AC_DEFINE([X86], [4], [Intel x86-compatible 32-bit architecture.]) -AC_DEFINE([X64], [5], [AMD64-compatible 64-bit architecture.]) - -dnl Relic: Generic options -AC_DEFINE([RELIC_NONE], [0], [Unknown or unrecognized parameter.]) - -dnl Relic: Arithmetic backends -AC_DEFINE([EASY], [1], [Easy C-only backend.]) -AC_DEFINE([GMP], [2], [Backend based on GNU Multiple Precision library.]) -AC_DEFINE([GMP_SEC], [3], [Backend based on GNU Multiple Precision library, but using constant-time code.]) - -AC_DEFUN([GMP_CHECK],[ - AC_REQUIRE([AC_PROG_CC]) - - CPPFLAGS_TEMP="$CPPFLAGS" - CPPFLAGS="$GMP_CPPFLAGS $CPPFLAGS" - LIBS_TEMP="$LIBS" - LIBS="$GMP_LDFLAGS $LIBS" - - AC_CHECK_HEADER( - gmp.h, - [AC_CHECK_LIB(gmp, __gmpz_init, [], [gmp_fail_reason="libgmp not found or unusable"; has_gmp=no;])], - [gmp_fail_reason="gmp header not found"; has_gmp=no;] - ) - - if test x"$has_gmp" != x"no"; then - # Proper support for macOS aarch64 was introduced in 6.3.0, but LTS distros - # like Ubuntu 20.04 (focal) use 6.2.0, so, the minimum supported version is - # determined by platform and architecture. - case $host in - *darwin*) - case $host_cpu in - aarch*) - gmp_major_version=6 - gmp_minor_version=3 - ;; - esac - ;; - *) - gmp_major_version=6 - gmp_minor_version=2 - ;; - esac - AC_MSG_CHECKING([gmp version >= $gmp_major_version.$gmp_minor_version]) - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[@%:@include ]], - [[ - @%:@if __GNU_MP_VERSION < $gmp_major_version || __GNU_MP_VERSION_MINOR < $gmp_minor_version - @%:@error Unsupported GMP version - @%:@endif]])], - [AC_MSG_RESULT([yes]); GMP_LIBS="-lgmp"; has_gmp=yes;], - [AC_MSG_RESULT([no]); gmp_fail_reason="unsupported gmp version"; has_gmp=no;] - ) - fi - - if test x"$want_backend" = x"gmp" && test x"$has_gmp" = x"no"; then - AC_MSG_ERROR([$gmp_fail_reason]) - fi - - CPPFLAGS="$CPPFLAGS_TEMP" - LIBS="$LIBS_TEMP" -]) - -AC_ARG_WITH([backend], - [AS_HELP_STRING([--with-backend=auto|easy|gmp], - [backend implementation to use [default=auto]])], - [want_backend=$withval], - [want_backend=auto] -) - -case $host in - *darwin*) - AC_PATH_PROG([BREW],brew,) - if test x$BREW != x; then - # These Homebrew packages may be keg-only, meaning that they won't be found - # in expected paths because they may conflict with system files. Ask - # Homebrew where each one is located, then adjust paths accordingly. - gmp_prefix=`$BREW --prefix gmp 2>/dev/null` - if test x$gmp_prefix != x; then - GMP_CPPFLAGS="-I$gmp_prefix/include" - GMP_LDFLAGS="-L$gmp_prefix/lib" - fi - fi - ;; - *freebsd*) - GMP_CPPFLAGS="-I/usr/local/include" - GMP_LDFLAGS="-L/usr/local/lib" - ;; -esac - -if test x"$want_backend" = x"auto"; then - if test x"$use_optimizations" = x"no"; then - want_backend=easy - else - GMP_CHECK - if test x"$has_gmp" = x"yes"; then - want_backend=gmp - else - want_backend=easy - fi - fi -else - case $want_backend in - gmp) - dnl GMP_CHECK will report the reason if and why the backend cannot be used. - GMP_CHECK - ;; - easy) - ;; - *) - AC_MSG_ERROR([invalid backend explicitly requested]) - ;; - esac -fi - -case $want_backend in -gmp) - AC_DEFINE(ARITH, GMP, [Define if GNU MP backend is requested]) - ;; -easy) - AC_DEFINE(ARITH, EASY, [Define if C-only backend is requested].) - ;; -*) - AC_MSG_ERROR([invalid backend explicitly requested]) - ;; -esac - -dnl Relic: Multithreading APIs -AC_DEFINE([OPENMP], [1], [OpenMP multithreading support.]) -AC_DEFINE([PTHREAD], [2], [POSIX multithreading support.]) - -dnl Relic: Supported operating systems -AC_DEFINE([LINUX], [1], [GNU/Linux operating system.]) -AC_DEFINE([FREEBSD], [2], [FreeBSD operating system.]) -AC_DEFINE([MACOSX], [3], [MacOS operating system.]) -AC_DEFINE([WINDOWS], [4], [Windows operating system.]) -AC_DEFINE([DROID], [5], [Android operating system.]) -AC_DEFINE([DUINO], [6], [Arduino platform.]) -dnl AC_DEFINE([OPENBSD], [7], [OpenBSD operating system.]) - -dnl Relic: Supported timers -AC_DEFINE([HREAL], [1], [Per-process high-resolution timer.]) -AC_DEFINE([HPROC], [2], [Per-process high-resolution timer.]) -AC_DEFINE([HTHRD], [3], [Per-thread high-resolution timer.]) -AC_DEFINE([ANSI], [5], [ANSI-compatible timer.]) -AC_DEFINE([POSIX], [4], [POSIX-compatible timer.]) -AC_DEFINE([CYCLE], [6], [Cycle-counting timer.]) -AC_DEFINE([PERF], [7], [Performance monitoring framework.]) - -dnl Relic: Memory-allocation policies -AC_DEFINE([AUTO], [1], [Automatic memory allocation.]) -AC_DEFINE([DYNAMIC], [2], [Dynamic memory allocation.]) - -dnl Relic (CP): Support for faster CRT-based exponentiation in factoring-based cryptosystems -AC_DEFINE([PKCS1], [2], [RSA PKCS#1 v1.5 padding.]) -AC_DEFINE([PKCS2], [3], [RSA PKCS#1 v2.1 padding.]) - -dnl Relic (MD): Available hash functions -AC_DEFINE([SH224], [2], [SHA-224 hash function.]) -AC_DEFINE([SH256], [3], [SHA-256 hash function.]) -AC_DEFINE([SH384], [4], [SHA-384 hash function.]) -AC_DEFINE([SH512], [5], [SHA-512 hash function.]) -AC_DEFINE([B2S160], [6], [BLAKE2s-160 hash function.]) -AC_DEFINE([B2S256], [7], [BLAKE2s-256 hash function.]) - -dnl Relic (RAND): Available pseudo-random number generators -AC_DEFINE([HASHD], [1], [NIST HASH-DRBG generator.]) -AC_DEFINE([RDRND], [2], [Intel RdRand instruction.]) -AC_DEFINE([UDEV], [3], [Operating system underlying generator.]) -AC_DEFINE([CALL], [4], [Override library generator with the callback.]) - -dnl Relic (RAND): Available random number generator seeders -AC_DEFINE([LIBC], [1], [Standard C library generator.]) -dnl AC_DEFINE([RDRND], [2], [Intel RdRand instruction.]) -dnl AC_DEFINE([UDEV], [3], [Operating system underlying generator.]) -AC_DEFINE([WCGR], [4], [Use Windows' CryptGenRandom.]) - -dnl Relic (BN): Options for the multiple precision -AC_DEFINE([SINGLE], [1], [A multiple precision integer can store w words.]) -AC_DEFINE([CARRY], [2], [A multiple precision integer can store the result of an addition.]) -AC_DEFINE([DOUBLE], [3], [A multiple precision integer can store the result of a multiplication.]) - -AC_DEFINE([BASIC], [1], [Basic method.]) -AC_DEFINE([PRIME], [1], [Prime curves.]) -AC_DEFINE([TATEP], [1], [Tate pairing.]) -AC_DEFINE([COMBA], [2], [Comba method.]) -AC_DEFINE([LEHME], [2], [Lehmer's fast GCD Algorithm.]) -AC_DEFINE([SAFEP], [2], [Safe prime generation.]) -AC_DEFINE([QUICK], [2], [Fast reduction modulo special form prime.]) -AC_DEFINE([BINAR], [2], [Binary inversion.]) -AC_DEFINE([LAZYR], [2], [Lazy-reduced extension field arithmetic.]) -AC_DEFINE([LODAH], [2], [Lopez-Dahab multiplication.]) -AC_DEFINE([SLIDE], [2], [Sliding window modular exponentiation.]) -AC_DEFINE([PROJC], [2], [Projective coordinates.]) -AC_DEFINE([COMBS], [2], [Single-table comb method.]) -AC_DEFINE([TRICK], [2], [Shamir's trick.]) -AC_DEFINE([CHAR2], [2], [Binary curves.]) -AC_DEFINE([WEILP], [2], [Weil pairing.]) -AC_DEFINE([MONTY], [3], [Montgomery method.]) -AC_DEFINE([STEIN], [3], [Stein's binary GCD Algorithm.]) -AC_DEFINE([STRON], [3], [Strong prime generation.]) -AC_DEFINE([INTEG], [3], [Integrated modular addtion.]) -AC_DEFINE([INTER], [3], [Interleaving of w-(T)NAFs.]) -AC_DEFINE([ALMOS], [3], [Almost inverse algorithm.]) -AC_DEFINE([JACOB], [3], [Jacobian coordinates.]) -AC_DEFINE([COMBD], [3], [Double-table comb method.]) -AC_DEFINE([HALVE], [3], [Halving.]) -AC_DEFINE([EDDIE], [3], [Edwards curves.]) -AC_DEFINE([EXTND], [3], [Extended projective twisted Edwards coordinates.]) -AC_DEFINE([OATEP], [3], [Optimal ate pairing.]) -AC_DEFINE([PMERS], [4], [Pseudo-Mersenne method.]) -AC_DEFINE([MULTP], [4], [Reuse multiplication for squaring.]) -AC_DEFINE([EXGCD], [4], [Extended Euclidean algorithm.]) -AC_DEFINE([LWNAF], [4], [Left-to-right Width-w NAF.]) -AC_DEFINE([JOINT], [4], [Joint sparse form.]) -AC_DEFINE([DIVST], [5], [Constant-time inversion by Bernstein-Yang division steps.]) -AC_DEFINE([ITOHT], [5], [Itoh-Tsuji inversion.]) -AC_DEFINE([LWREG], [5], [Left-to-right Width-w NAF.]) -AC_DEFINE([BRUCH], [6], [Hardware-friendly inversion by Brunner-Curiger-Hofstetter.]) -AC_DEFINE([CTAIA], [7], [Constant-time version of almost inverse.]) -AC_DEFINE([LOWER], [8], [Use implementation provided by the lower layer.]) - -if test x"$use_debug" = x"yes"; then - AC_DEFINE([DEBUG], [1], [Define this symbol if debugging support is enabled]) -fi - -dnl Define relic switches -AC_ARG_ENABLE([profiling], - [AS_HELP_STRING([--enable-profiling], - [Build with profiling support [default=no]])], - [use_profiling=$enableval], - [use_profiling=no]) - -if test x$use_profiling = xyes; then - AC_DEFINE([PROFL], [1], [Define this symbol if profiling support is enabled]) -fi - -AC_ARG_ENABLE([check], - [AS_HELP_STRING([--enable-check], - [Build with error-checking support [default=no]])], - [use_check=$enableval], - [use_check=no]) - -if test x$use_check = xyes; then - AC_DEFINE([CHECK], [1], [Define this symbol if error-checking support is enabled]) -fi - -AC_ARG_ENABLE([verbs], - [AS_HELP_STRING([--enable-verbs], - [Build with detailed error messages [default=no]])], - [use_verbs=$enableval], - [use_verbs=no]) - -if test x$use_verbs = xyes; then - AC_DEFINE([VERBS], [1], [Define this symbol if detailed error messages are enabled]) -fi - -AC_ARG_ENABLE([overhead], - [AS_HELP_STRING([--enable-overhead], - [Build with overhead estimation [default=no]])], - [use_overhead=$enableval], - [use_overhead=no]) - -if test x$use_overhead = xyes; then - AC_DEFINE([OVERH], [1], [Define this symbol if overhead estimation is enabled]) -fi - -AC_ARG_ENABLE([quiet], - [AS_HELP_STRING([--enable-quiet], - [Build with printing disabled [default=yes]])], - [use_quiet=$enableval], - [use_quiet=yes]) - -if test x$use_quiet = xyes; then - AC_DEFINE([QUIET], [1], [Define this symbol if printing is disabled]) -fi - -AC_ARG_ENABLE([color], - [AS_HELP_STRING([--enable-color], - [Build with colored output support [default=yes]])], - [use_color=$enableval], - [use_color=yes]) - -if test x$use_color = xyes; then - AC_DEFINE([COLOR], [1], [Define this symbol if colored output is enabled]) -fi - -AC_ARG_ENABLE([big_endian], - [AS_HELP_STRING([--enable-big-endian], - [Build with big-endian support [default=no]])], - [use_big_endian=$enableval], - [use_big_endian=no]) - -if test x$use_big_endian = xyes; then - AC_DEFINE([BIGED], [1], [Define this symbol if big-endian support is enabled]) -fi - -use_pkgconfig=yes - -if test x"$use_optimizations" = x"yes"; then - case $host_cpu in - amd64 | x86_64) - dnl Support for AMD64 (also known as x86_64 on some platforms) processors - CPU_ARCH="x64" - AC_DEFINE([ARCH], [X64], [Architecture.]) - AC_DEFINE([WSIZE], [64], [Size of word in this architecture.]) - ;; - aarch*) - dnl Support for 64-bit ARM processors - dnl Relic does not support aarch64 yet, set CPU_ARCH to none and ARCH to RELIC_NONE. - CPU_ARCH="none" - AC_DEFINE([ARCH], [RELIC_NONE], [Architecture.]) - AC_DEFINE([WSIZE], [64], [Size of word in this architecture.]) - ;; - i?86) - dnl Support for Intel x86 processors - CPU_ARCH="x86" - AC_DEFINE([ARCH], [X86], [Architecture.]) - AC_DEFINE([WSIZE], [32], [Size of word in this architecture.]) - ;; - arm*) - dnl Support for 32-bit native ARM processors - CPU_ARCH="arm" - AC_DEFINE([ARCH], [ARM], [Architecture.]) - AC_DEFINE([WSIZE], [32], [Size of word in this architecture.]) - ;; - *64*) - dnl Support for an undefined 64-bit architecture - CPU_ARCH="none" - AC_DEFINE([ARCH], [RELIC_NONE], [Architecture.]) - AC_DEFINE([WSIZE], [64], [Size of word in this architecture.]) - ;; - *32*) - dnl Support for an undefined 32-bit architecture - CPU_ARCH="none" - AC_DEFINE([ARCH], [RELIC_NONE], [Architecture.]) - AC_DEFINE([WSIZE], [32], [Size of word in this architecture.]) - ;; - *) - AC_MSG_ERROR([Unable to determine host architecture, may not be supported!]) - ;; - esac -else - case $host_cpu in - *64*) - dnl Support for an undefined 64-bit architecture - CPU_ARCH="none" - AC_DEFINE([ARCH], [RELIC_NONE], [Architecture.]) - AC_DEFINE([WSIZE], [64], [Size of word in this architecture.]) - ;; - *32* | arm* | i?86) - dnl Support for an undefined 32-bit architecture - CPU_ARCH="none" - AC_DEFINE([ARCH], [RELIC_NONE], [Architecture.]) - AC_DEFINE([WSIZE], [32], [Size of word in this architecture.]) - ;; - *) - AC_MSG_ERROR([Unable to determine host architecture, may not be supported!]) - ;; - esac -fi - -case $host in - *darwin*) - AC_DEFINE([OPSYS], [MACOSX], [Detected operation system.]) - TARGET_OS=darwin - - AC_PATH_PROG([BREW],brew,) - if test x$BREW = x; then - AC_PATH_PROG([PORT],port,) - # If homebrew isn't installed and macports is, add the macports default paths - # as a last resort. - if test x$PORT != x; then - CPPFLAGS="$CPPFLAGS -isystem /opt/local/include" - LDFLAGS="$LDFLAGS -L/opt/local/lib" - fi - fi - ;; - *mingw*) - AC_DEFINE([OPSYS], [WINDOWS], [Detected operation system.]) - TARGET_OS=windows - - use_pkgconfig=no - LIBTOOL_APP_LDFLAGS="$LIBTOOL_APP_LDFLAGS -all-static" - - dnl libtool insists upon adding -nostdlib and a list of objects/libs to link against. - dnl That breaks our ability to build dll's with static libgcc/libstdc++/libssp. Override - dnl its command here, with the predeps/postdeps removed, and -static inserted. Postdeps are - dnl also overridden to prevent their insertion later. - dnl This should only affect dll's. - archive_cmds_CXX="\$CC -shared \$libobjs \$deplibs \$compiler_flags -static -o \$output_objdir/\$soname \${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker \$lib" - postdeps_CXX= - ;; - *linux*) - AC_DEFINE([OPSYS], [LINUX], [Detected operation system.]) - TARGET_OS=linux - - RELIC_CPPFLAGS="-D_GNU_SOURCE" - ;; - *android*) - AC_DEFINE([OPSYS], [DROID], [Detected operation system.]) - TARGET_OS=android - ;; - *freebsd*) - AC_DEFINE([OPSYS], [FREEBSD], [Detected operation system.]) - TARGET_OS=freebsd - ;; - *netbsd*) - AC_DEFINE([OPSYS], [NETBSD], [Detected operation system.]) - TARGET_OS=netbsd - ;; - *) - AC_DEFINE([OPSYS], [RELIC_NONE], [Detected operation system.]) - ;; -esac - -case $host in - *darwin*) - dnl Relic: Don't define FP_QNRES on Darwin - AC_DEFINE([SEED], [UDEV], [Chosen random generator seeder.]) - ;; - *mingw*) - AC_DEFINE([FP_QNRES], [], [Use -1 as quadratic non-residue.]) - AC_DEFINE([SEED], [WCGR], [Chosen random generator seeder.]) - ;; - *) - AC_DEFINE([FP_QNRES], [], [Use -1 as quadratic non-residue.]) - AC_DEFINE([SEED], [UDEV], [Chosen random generator seeder.]) - ;; -esac - -if test x$use_pkgconfig = xyes; then - m4_ifndef([PKG_PROG_PKG_CONFIG], [AC_MSG_ERROR(PKG_PROG_PKG_CONFIG macro not found. Please install pkg-config and re-run autogen.sh.)]) - m4_ifdef([PKG_PROG_PKG_CONFIG], [ - PKG_PROG_PKG_CONFIG - if test x"$PKG_CONFIG" = "x"; then - AC_MSG_ERROR(pkg-config not found.) - fi - ]) -fi - -saved_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS -pipe" -AC_MSG_CHECKING([if ${CC} supports -pipe]) -AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], - [ AC_MSG_RESULT([yes]) ], - [ AC_MSG_RESULT([no]) - CFLAGS="$saved_CFLAGS" - ]) - -saved_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS -fomit-frame-pointer" -AC_MSG_CHECKING([if ${CC} supports -fomit-frame-pointer]) -AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], - [ AC_MSG_RESULT([yes]) ], - [ AC_MSG_RESULT([no]) - CFLAGS="$saved_CFLAGS" - ]) - -if test x"$CFLAGS_overridden" = x"no" -a x"$CXXFLAGS_overridden" = x"no"; then - dnl Enable warnings - AX_CHECK_COMPILE_FLAG([-Wall],[WARN_FLAGS="$WARN_FLAGS -Wall"], [], [[$FLAG_WERROR]]) - AX_CHECK_COMPILE_FLAG([-Wcast-align],[WARN_FLAGS="$WARN_FLAGS -Wcast-align"], [], [[$FLAG_WERROR]]) - AX_CHECK_COMPILE_FLAG([-Wextra],[WARN_FLAGS="$WARN_FLAGS -Wextra"], [], [[$FLAG_WERROR]]) - - dnl Exclude known warnings - AX_CHECK_COMPILE_FLAG([-Wlong-long],[NOWARN_FLAGS="$NOWARN_FLAGS -Wno-long-long"], [], [[$FLAG_WERROR]]) - AX_CHECK_COMPILE_FLAG([-Wshadow],[NOWARN_FLAGS="$NOWARN_FLAGS -Wno-shadow"], [], [[$FLAG_WERROR]]) - AX_CHECK_COMPILE_FLAG([-Wsign-compare],[NOWARN_FLAGS="$NOWARN_FLAGS -Wno-sign-compare"], [], [[$FLAG_WERROR]]) - AX_CHECK_COMPILE_FLAG([-Wstrict-prototypes],[NOWARN_FLAGS="$NOWARN_FLAGS -Wno-strict-prototypes"], [], [[$FLAG_WERROR]]) - AX_CHECK_COMPILE_FLAG([-Wunused-function],[NOWARN_FLAGS="$NOWARN_FLAGS -Wno-unused-function"], [], [[$FLAG_WERROR]]) - AX_CHECK_COMPILE_FLAG([-Wunused-parameter],[NOWARN_FLAGS="$NOWARN_FLAGS -Wno-unused-parameter"], [], [[$FLAG_WERROR]]) -fi - -dnl set default settings for relic -AC_DEFINE([ALIGN], [1], [Byte boundary to align digit vectors.]) - -AC_DEFINE(WITH_BN,, Build multiple precision integer module.) -AC_DEFINE(WITH_DV,, Temporary double-precision digit vectors.) -AC_DEFINE(WITH_FP,, Build prime field module.) -AC_DEFINE(WITH_FPX,, Build prime field extension module.) -AC_DEFINE(WITH_FB,, Build binary field module.) -AC_DEFINE(WITH_FBX,, Build binary field extension module.) -AC_DEFINE(WITH_EP,, Build prime elliptic curve module.) -AC_DEFINE(WITH_EPX,, Build prime field extension elliptic curve module.) -AC_DEFINE(WITH_EB,, Build binary elliptic curve module.) -AC_DEFINE(WITH_ED,, Build elliptic Edwards curve module.) -AC_DEFINE(WITH_EC,, Build elliptic curve cryptography module.) -AC_DEFINE(WITH_PP,, Build pairings over prime curves module.) -AC_DEFINE(WITH_PC,, Build pairing-based cryptography module.) -AC_DEFINE(WITH_BC,, Build block ciphers.) -AC_DEFINE(WITH_MD,, Build hash functions.) -AC_DEFINE(WITH_CP,, Build cryptographic protocols.) -AC_DEFINE(WITH_MPC,, Build Multi-party computation primitives.) - -AC_DEFINE(BN_PRECI, 1024, Required precision in bits.) -AC_DEFINE(BN_KARAT, 0, Number of Karatsuba steps.) -AC_DEFINE(BN_MAGNI, [DOUBLE], Effective size of a multiple precision integer.) - -AC_DEFINE(BN_METHD, "COMBA;COMBA;MONTY;SLIDE;BASIC;BASIC", Multiple precision arithmetic method.) -AC_DEFINE(BN_MUL, COMBA, Chosen multiple precision multiplication method.) -AC_DEFINE(BN_SQR, COMBA, Chosen multiple precision multiplication method.) -AC_DEFINE(BN_MOD, MONTY, Chosen multiple precision modular reduction method.) -AC_DEFINE(BN_MXP, SLIDE, Chosen multiple precision modular exponentiation method.) -AC_DEFINE(BN_GCD, BASIC, Chosen multiple precision greatest common divisor method.) -AC_DEFINE(BN_GEN, BASIC, Chosen prime generation algorithm.) - -AC_DEFINE(FP_PRIME, 381, Prime field size in bits.) -AC_DEFINE(FP_METHD, "INTEG;INTEG;INTEG;MONTY;LOWER;SLIDE", Prime field arithmetic method.) -AC_DEFINE(FP_KARAT, 0, Number of Karatsuba steps.) -AC_DEFINE(FP_WIDTH, 4, Width of window processing for exponentiation methods.) -AC_DEFINE(FP_ADD, INTEG, Chosen prime field multiplication method.) -AC_DEFINE(FP_MUL, INTEG, Chosen prime field multiplication method.) -AC_DEFINE(FP_SQR, INTEG, Chosen prime field multiplication method.) -AC_DEFINE(FP_RDC, MONTY, Chosen prime field reduction method.) -AC_DEFINE(FP_INV, LOWER, Chosen prime field inversion method.) -AC_DEFINE(FP_EXP, SLIDE, Chosen multiple precision modular exponentiation method.) - -AC_DEFINE(FPX_METHD, "INTEG;INTEG;LAZYR", Prime extension field arithmetic method.) -AC_DEFINE(FPX_QDR, INTEG, Chosen extension field arithmetic method.) -AC_DEFINE(FPX_CBC, INTEG, Chosen extension field arithmetic method.) -AC_DEFINE(FPX_RDC, LAZYR, Chosen extension field arithmetic method.) - -AC_DEFINE(FB_METHD, "LODAH;QUICK;QUICK;QUICK;QUICK;QUICK;EXGCD;SLIDE;QUICK", Binary field arithmetic method) -AC_DEFINE(FB_POLYN, 283, Irreducible polynomial size in bits.) -AC_DEFINE(FB_KARAT, 0, Number of Karatsuba levels.) -AC_DEFINE(FB_TRINO,, Prefer trinomials over pentanomials.) -AC_DEFINE(FB_PRECO,, Precompute multiplication table for sqrt(z).) -AC_DEFINE(FB_WIDTH, 4, Width of window processing for exponentiation methods.) -AC_DEFINE(FB_MUL, LODAH, Chosen binary field multiplication method.) -AC_DEFINE(FB_SQR, QUICK, Chosen binary field squaring method.) -AC_DEFINE(FB_RDC, QUICK, Chosen binary field modular reduction method.) -AC_DEFINE(FB_SRT, QUICK, Chosen binary field modular reduction method.) -AC_DEFINE(FB_TRC, QUICK, Chosen trace computation method.) -AC_DEFINE(FB_SLV, QUICK, Chosen method to solve a quadratic equation.) -AC_DEFINE(FB_INV, EXGCD, Chosen binary field inversion method.) -AC_DEFINE(FB_EXP, SLIDE, Chosen multiple precision modular exponentiation method.) -AC_DEFINE(FB_ITR, QUICK, Chosen method to solve a quadratic equation.) - -AC_DEFINE(EP_METHD, "PROJC;LWNAF;COMBS;INTER", Prime elliptic curve arithmetic method.) -AC_DEFINE(EP_ENDOM,, Support for prime curves with efficient endormorphisms.) -AC_DEFINE(EP_MIXED,, Use mixed coordinates.) -AC_DEFINE(EP_PRECO,, Build precomputation table for generator.) -AC_DEFINE(EP_CTMAP,, Enable isogeny map for SSWU map-to-curve.) -AC_DEFINE(EP_DEPTH, 4, Width of precomputation table for fixed point methods.) -AC_DEFINE(EP_WIDTH, 4, Width of window processing for unknown point methods.) -AC_DEFINE(EP_ADD, PROJC, Chosen prime elliptic curve coordinate method.) -AC_DEFINE(EP_MUL, LWNAF, Chosen prime elliptic curve point multiplication method.) -AC_DEFINE(EP_FIX, COMBS, Chosen prime elliptic curve point multiplication method.) -AC_DEFINE(EP_SIM, INTER, Chosen prime elliptic curve simulteanous point multiplication method.) - -AC_DEFINE(EB_METHD, "PROJC;LWNAF;COMBS;INTER", Binary elliptic curve arithmetic method.) -AC_DEFINE(EB_PLAIN,, Support for ordinary curves without endormorphisms.) -AC_DEFINE(EB_KBLTZ,, Support for Koblitz anomalous binary curves.) -AC_DEFINE(EB_MIXED,, Use mixed coordinates.) -AC_DEFINE(EB_PRECO,, Build precomputation table for generator.) -AC_DEFINE(EB_DEPTH, 4, Width of precomputation table for fixed point methods.) -AC_DEFINE(EB_WIDTH, 4, Width of window processing for unknown point methods.) -AC_DEFINE(EB_ADD, PROJC, Chosen binary elliptic curve coordinate method.) -AC_DEFINE(EB_MUL, LWNAF, Chosen binary elliptic curve point multiplication method.) -AC_DEFINE(EB_FIX, COMBS, Chosen binary elliptic curve point multiplication method.) -AC_DEFINE(EB_SIM, INTER, Chosen binary elliptic curve simulteanous point multiplication method.) - -AC_DEFINE(ED_METHD, "PROJC;LWNAF;COMBS;INTER", Edwards elliptic curve arithmetic method.) -AC_DEFINE(ED_PRECO,, Build precomputation table for generator.) -AC_DEFINE(ED_DEPTH, 4, Width of precomputation table for fixed point methods.) -AC_DEFINE(ED_WIDTH, 4, Width of window processing for unknown point methods.) -AC_DEFINE(ED_ADD, PROJC, Chosen binary elliptic curve coordinate method.) -AC_DEFINE(ED_MUL, LWNAF, Chosen prime elliptic twisted Edwards curve point multiplication method.) -AC_DEFINE(ED_FIX, COMBS, Chosen prime elliptic twisted Edwards curve point multiplication method.) -AC_DEFINE(ED_SIM, INTER, Chosen prime elliptic curve simulteanous point multiplication method.) - -AC_DEFINE(EC_METHD, "PRIME", Chosen elliptic curve cryptography method.) -AC_DEFINE(EC_CUR, PRIME, Chosen elliptic curve type.) - -AC_DEFINE(PP_METHD, "LAZYR;OATEP", Bilinear pairing method.) -AC_DEFINE(PP_EXT, LAZYR, Chosen extension field arithmetic method.) -AC_DEFINE(PP_MAP, OATEP, Chosen pairing method over prime elliptic curves.) - -AC_DEFINE(MD_METHD, "SH256", Choice of hash function.) -AC_DEFINE(MD_MAP, SH256, Chosen hash function.) - -AC_DEFINE(CP_CRT,, Support for faster CRT-based exponentiation in factoring-based cryptosystems.) -AC_DEFINE(CP_RSAPD, PKCS2, Chosen RSA padding method.) - -AC_DEFINE(ALLOC, AUTO, Chosen memory allocation policy.) -AC_DEFINE(RAND, HASHD, Chosen random generator.) -AC_DEFINE(MULTI, PTHREAD, Chosen multithreading API.) -AC_DEFINE(TIMER, CYCLE, Chosen timer.) - -dnl Check for pthread compile/link requirements -AX_PTHREAD - -AC_SEARCH_LIBS([clock_gettime],[rt]) - -if test "$TARGET_OS" != "windows"; then - dnl All windows code is PIC, forcing it on just adds useless compile warnings - AX_CHECK_COMPILE_FLAG([-fPIC], [HARDENED_FLAGS="$HARDENED_FLAGS -fPIC"], [], [[$FLAG_WERROR]]) -fi - -dnl All versions of gcc that we commonly use for building are subject to bug -dnl https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90348. To work around that, set -dnl -fstack-reuse=none for all gcc builds. (Only gcc understands this flag) -AX_CHECK_COMPILE_FLAG([-fstack-reuse=none], [HARDENED_FLAGS="$HARDENED_FLAGS -fstack-reuse=none"], [], [[$FLAG_WERROR]]) -if test "$use_hardening" != "no"; then - use_hardening=yes - AX_CHECK_COMPILE_FLAG([-Wstack-protector], [HARDENED_FLAGS="$HARDENED_FLAGS -Wstack-protector"]) - AX_CHECK_COMPILE_FLAG([-fstack-protector-all], [HARDENED_FLAGS="$HARDENED_FLAGS -fstack-protector-all"], [], [[$FLAG_WERROR]]) - - AX_CHECK_COMPILE_FLAG([-fcf-protection=full], [HARDENED_FLAGS="$HARDENED_FLAGS -fcf-protection=full"], [], [[$FLAG_WERROR]]) - - case $host in - *mingw*) - dnl stack-clash-protection doesn't currently work, and likely should just be skipped for Windows. - dnl See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90458 for more details. - ;; - *) - AX_CHECK_COMPILE_FLAG([-fstack-clash-protection], [HARDENED_FLAGS="$HARDENED_FLAGS -fstack-clash-protection"], [], [[$FLAG_WERROR]]) - ;; - esac - - case $host in - *aarch64*) - AX_CHECK_COMPILE_FLAG([-mbranch-protection=bti], [HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -mbranch-protection=bti"], [], [[$CXXFLAG_WERROR]]) - ;; - esac - - AX_CHECK_LINK_FLAG([-Wl,--enable-reloc-section], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--enable-reloc-section"], [], []) - AX_CHECK_LINK_FLAG([-Wl,--dynamicbase], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--dynamicbase"], [], []) - AX_CHECK_LINK_FLAG([-Wl,--nxcompat], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--nxcompat"], [], []) - AX_CHECK_LINK_FLAG([-Wl,--high-entropy-va], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--high-entropy-va"], [], []) - AX_CHECK_LINK_FLAG([-Wl,-z,relro], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,relro"], [], []) - AX_CHECK_LINK_FLAG([-Wl,-z,now], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,now"], [], []) - AX_CHECK_LINK_FLAG([-Wl,-z,separate-code], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,separate-code"], [], []) - AX_CHECK_LINK_FLAG([-fPIE -pie], [HARDENED_FLAGS="$HARDENED_FLAGS -fPIE"; HARDENED_LDFLAGS="$HARDENED_LDFLAGS -pie"], [], []) -fi - -CORE_CPPFLAGS="$CORE_CPPFLAGS -DHAVE_BUILD_INFO" - -case $host in - *mingw*) - AC_CHECK_LIB([user32], [main], [], [AC_MSG_ERROR([libuser32 missing])]) - AC_CHECK_LIB([shell32], [SHGetSpecialFolderPathW], [], [AC_MSG_ERROR([libshell32 missing])]) - AC_CHECK_LIB([advapi32], [CryptAcquireContextW], [], [AC_MSG_ERROR([libadvapi32 missing])]) - AC_CHECK_LIB([psapi], [GetProcessMemoryInfo], [], [AC_MSG_ERROR([libpsapi missing])]) - AC_CHECK_LIB([bcrypt], [main], [], [AC_MSG_ERROR([libbcrypt missing])]) - - dnl -static is interpreted by libtool, where it has a different meaning. - dnl In libtool-speak, it's -all-static. - AX_CHECK_LINK_FLAG([-static], [LIBTOOL_APP_LDFLAGS="$LIBTOOL_APP_LDFLAGS -all-static"]) - - CORE_CPPFLAGS="$CORE_CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -D_WIN32_WINNT=0x0601 -D_WIN32_IE=0x0501 -DWIN32_LEAN_AND_MEAN" - dnl Prevent the definition of min/max macros. - dnl We always want to use the standard library. - CORE_CPPFLAGS="$CORE_CPPFLAGS -DNOMINMAX" - - dnl libtool insists upon adding -nostdlib and a list of objects/libs to link against. - dnl That breaks our ability to build dll's with static libgcc/libstdc++/libssp. Override - dnl its command here, with the predeps/postdeps removed, and -static inserted. Postdeps are - dnl also overridden to prevent their insertion later. - dnl This should only affect dll's. - archive_cmds_CXX="\$CC -shared \$libobjs \$deplibs \$compiler_flags -static -o \$output_objdir/\$soname \${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker \$lib" - postdeps_CXX= - - dnl We require Windows 7 (NT 6.1) or later - AX_CHECK_LINK_FLAG([-Wl,--major-subsystem-version -Wl,6 -Wl,--minor-subsystem-version -Wl,1], [CORE_LDFLAGS="$CORE_LDFLAGS -Wl,--major-subsystem-version -Wl,6 -Wl,--minor-subsystem-version -Wl,1"], [], []) - ;; - *darwin*) - AX_CHECK_LINK_FLAG([-Wl,-headerpad_max_install_names], [CORE_LDFLAGS="$CORE_LDFLAGS -Wl,-headerpad_max_install_names"], [], []) - CORE_CPPFLAGS="$CORE_CPPFLAGS -DMAC_OSX -DOBJC_OLD_DISPATCH_PROTOTYPES=0" - OBJCXXFLAGS="$CXXFLAGS" - ;; -esac - -dnl These flags are specific to ld64, and may cause issues with other linkers. -dnl For example: GNU ld will interpret -dead_strip as -de and then try and use -dnl "ad_strip" as the symbol for the entry point. -if test "$TARGET_OS" = "darwin"; then - AX_CHECK_LINK_FLAG([-Wl,-dead_strip], [CORE_LDFLAGS="$CORE_LDFLAGS -Wl,-dead_strip"], [], []) - AX_CHECK_LINK_FLAG([-Wl,-dead_strip_dylibs], [CORE_LDFLAGS="$CORE_LDFLAGS -Wl,-dead_strip_dylibs"], [], []) - AX_CHECK_LINK_FLAG([-Wl,-bind_at_load], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-bind_at_load"], [], []) -fi - -dnl Don't allow extended (non-ASCII) symbols in identifiers. This is easier for code review. -AX_CHECK_COMPILE_FLAG([-fno-extended-identifiers], [CORE_FLAGS="$CORE_FLAGS -fno-extended-identifiers"], [], [[$FLAG_WERROR]]) - -AC_LANG_POP([C]) - -AC_MSG_CHECKING([whether to build runtest]) -if test x$use_tests = xyes; then - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi - -AC_MSG_CHECKING([whether to build runbench]) -if test x$use_bench = xyes; then - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi - -AM_CONDITIONAL([TARGET_DARWIN], [test "$TARGET_OS" = "darwin"]) -AM_CONDITIONAL([TARGET_LINUX], [test "$TARGET_OS" = "linux"]) -AM_CONDITIONAL([TARGET_WINDOWS], [test "$TARGET_OS" = "windows"]) - -AM_CONDITIONAL(WITH_BN, test 1 -eq 1) -AM_CONDITIONAL(WITH_FP, test 1 -eq 1) -AM_CONDITIONAL(WITH_FPX, test 1 -eq 1) -AM_CONDITIONAL(WITH_FB, test 1 -eq 1) -AM_CONDITIONAL(WITH_EP, test 1 -eq 1) -AM_CONDITIONAL(WITH_EPX, test 1 -eq 1) -AM_CONDITIONAL(WITH_EB, test 1 -eq 1) -AM_CONDITIONAL(WITH_ED, test 1 -eq 1) -AM_CONDITIONAL(WITH_EC, test 1 -eq 1) -AM_CONDITIONAL(WITH_PP, test 1 -eq 1) -AM_CONDITIONAL(WITH_PC, test 1 -eq 1) -AM_CONDITIONAL(WITH_BC, test 1 -eq 1) -AM_CONDITIONAL(WITH_MD, test 1 -eq 1) -AM_CONDITIONAL(WITH_CP, test 1 -eq 1) -AM_CONDITIONAL(WITH_MPC, test 1 -eq 1) -AM_CONDITIONAL(WITH_DV, test 1 -eq 1) -AM_CONDITIONAL(WITH_FBX, test 1 -eq 1) - -AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" = x"yes"]) -AM_CONDITIONAL([USE_BENCH], [test x"$use_bench" = x"yes"]) -AM_CONDITIONAL([HARDEN], [test "$use_hardening" = "yes"]) -AM_CONDITIONAL([OPTIMIZE], [test "$use_optimizations" = "yes"]) - -AM_CONDITIONAL([ARITH_EASY], [test "$want_backend" = "easy"]) -AM_CONDITIONAL([ARITH_GMP], [test "$want_backend" = "gmp"]) - -AC_SUBST(CPU_ARCH) -AC_SUBST(DEBUG_FLAGS) -AC_SUBST(RAND_PATH, hashd) -AC_SUBST(RELIC_CPPFLAGS) -AC_SUBST(WARN_FLAGS) -AC_SUBST(NOWARN_FLAGS) -AC_SUBST(LIBTOOL_APP_LDFLAGS) -AC_SUBST(HARDENED_FLAGS) -AC_SUBST(HARDENED_LDFLAGS) -AC_SUBST(CORE_LDFLAGS) -AC_SUBST(CORE_CPPFLAGS) -AC_SUBST(CORE_FLAGS) - -AC_SUBST(GMP_LDFLAGS) -AC_SUBST(GMP_CPPFLAGS) -AC_SUBST(GMP_LIBS) - -AC_CONFIG_HEADERS([depends/relic/include/relic_conf.h]) -AC_CONFIG_FILES([Makefile]) - -AC_OUTPUT - -dnl Peplace conflict-prone PACKAGE-prefixed macros with DASHBLS -sed -i.old 's/PACKAGE/DASHBLS/g' depends/relic/include/relic_conf.h -sed -i.old 's/PACKAGE/DASHBLS/g' config.status - -echo -echo "Options used to compile and link:" -echo " target os = $TARGET_OS" -echo " backend = $want_backend" -echo " build bench = $use_tests" -echo " build test = $use_bench" -echo " use debug = $use_debug" -echo " use hardening = $use_hardening" -echo " use optimizations = $use_optimizations" -echo -echo " LDFLAGS = $HARDENED_LDFLAGS $CORE_LDFLAGS $GMP_LDFLAGS" -echo " CFLAGS = $DEBUG_FLAGS $HARDENED_FLAGS $CORE_FLAGS $WARN_FLAGS $NOWARN_FLAGS" -echo " CPPFLAGS = $CORE_CPPFLAGS $GMP_CPPFLAGS" -echo " CXXFLAGS = $DEBUG_FLAGS $HARDENED_FLAGS $CORE_FLAGS $WARN_FLAGS $NOWARN_FLAGS" -echo " PTHREAD_FLAGS = $PTHREAD_CFLAGS $PTHREAD_LIBS" -echo diff --git a/src/dashbls/go-bindings/Makefile b/src/dashbls/go-bindings/Makefile index dcea3f24f2d3..0c4e33b0e0eb 100644 --- a/src/dashbls/go-bindings/Makefile +++ b/src/dashbls/go-bindings/Makefile @@ -12,23 +12,6 @@ BUILD_DIR=$(CURDIR)/../build CURR_DIR := $(dir $(MAKEFILE_PATH)) SRC_DIR=$(CURDIR)/../src -GMP_PREFIX := /usr/local - -ifeq ("$(OS)", "Darwin") - ifneq ($(wildcard /opt/local/bin/port),) - GMP_PREFIX := /opt/local - endif - ifeq ("$(ARCH)", "arm64") - ifneq ($(wildcard /opt/homebrew/bin/brew),) - GMP_PREFIX := /opt/homebrew - endif - endif -else ifeq ("$(OS)", "Linux") - ifneq ($(wildcard /home/linuxbrew/.linuxbrew/bin/brew),) - GMP_PREFIX := /home/linuxbrew/.linuxbrew - endif -endif - MIMALLOC_LIB := mimalloc-secure MIMALLOC_LIB_PATH := $(CURR_DIR)../build/depends/mimalloc @@ -36,18 +19,15 @@ ifneq ($(wildcard $(MIMALLOC_LIB_PATH)/libmimalloc-secure-debug.a),) MIMALLOC_LIB := mimalloc-secure-debug endif +# blst is compiled into libdashbls; its headers come from the CMake build CGO_CXXFLAGS ?= "\ --I$(CURR_DIR)../build/depends/relic/include \ +-I$(CURR_DIR)../build/_deps/blst-src/bindings \ -I$(CURR_DIR)../depends/mimalloc/include \ --I$(CURR_DIR)../depends/relic/include \ --I$(CURR_DIR)../include \ --I$(GMP_PREFIX)/include" +-I$(CURR_DIR)../include" CGO_LDFLAGS ?= "\ -L$(CURR_DIR)../build/src -ldashbls \ --L$(MIMALLOC_LIB_PATH) -l$(MIMALLOC_LIB) \ --L$(CURR_DIR)../build/depends/relic/lib -lrelic_s \ --L$(GMP_PREFIX)/lib -lgmp" +-L$(MIMALLOC_LIB_PATH) -l$(MIMALLOC_LIB)" .PHONY: default prepare fmt test cover vet help clean config diff --git a/src/dashbls/include/dashbls/bls.hpp b/src/dashbls/include/dashbls/bls.hpp index cd6922a58cd6..d9108873511c 100644 --- a/src/dashbls/include/dashbls/bls.hpp +++ b/src/dashbls/include/dashbls/bls.hpp @@ -40,8 +40,6 @@ class BLS { static bool Init(); static void SetSecureAllocator(Util::SecureAllocCallback allocCb, Util::SecureFreeCallback freeCb); - - static void CheckRelicErrors(bool should_throw = true); }; } // end namespace bls diff --git a/src/dashbls/include/dashbls/chaincode.hpp b/src/dashbls/include/dashbls/chaincode.hpp index bd3e57b4d779..ecd5db79fd39 100644 --- a/src/dashbls/include/dashbls/chaincode.hpp +++ b/src/dashbls/include/dashbls/chaincode.hpp @@ -15,19 +15,10 @@ #ifndef SRC_CHAINCODE_HPP_ #define SRC_CHAINCODE_HPP_ +#include #include #include -#include "relic_conf.h" - -#if defined GMP && ARITH == GMP -#include -#endif - - -#include "relic.h" -#include "relic_test.h" - #include "util.hpp" namespace bls { @@ -51,9 +42,8 @@ class ChainCode { ChainCode() {} private: - bn_t chainCode; + std::array chainCode{}; }; } // end namespace bls #endif // SRC_CHAINCODE_HPP_ - diff --git a/src/dashbls/include/dashbls/elements.hpp b/src/dashbls/include/dashbls/elements.hpp index 95937f62dbc6..cbc4154d5fc4 100644 --- a/src/dashbls/include/dashbls/elements.hpp +++ b/src/dashbls/include/dashbls/elements.hpp @@ -16,17 +16,12 @@ #define SRC_BLSELEMENTS_HPP_ extern "C" { -#include "relic.h" +#include "blst.h" } -#include "relic_conf.h" -#include "util.hpp" - -#if defined GMP && ARITH == GMP -#include -#endif - #include +#include "util.hpp" + namespace bls { class G1Element; class G2Element; @@ -36,25 +31,27 @@ class G1Element { public: static const size_t SIZE = 48; - G1Element() { - g1_set_infty(p); - } - - static G1Element FromBytes(Bytes bytes, bool fLegacy = false); - static G1Element FromBytesUnchecked(Bytes bytes, bool fLegacy = false); - static G1Element FromByteVector(const std::vector &bytevec, bool fLegacy = false); - static G1Element FromNative(const g1_t element); - static G1Element FromMessage(const std::vector &message, - const uint8_t *dst, - int dst_len); - static G1Element FromMessage(Bytes message, - const uint8_t* dst, - int dst_len); + G1Element() { memset(&p, 0x00, sizeof(blst_p1)); } + + static G1Element FromBytes(Bytes bytes, bool legacy_encoding = false); + static G1Element FromBytesUnchecked(Bytes bytes, bool legacy_encoding = false); + static G1Element FromByteVector(const std::vector &bytevec, bool legacy_encoding = false); + static G1Element FromNative(const blst_p1 &element); + static G1Element FromAffine(const blst_p1_affine &element); + static G1Element FromMessage( + const std::vector &message, + const uint8_t *dst, + size_t dst_len); + static G1Element FromMessage( + Bytes message, + const uint8_t *dst, + size_t dst_len); static G1Element Generator(); bool IsValid() const; void CheckValid() const; - void ToNative(g1_t output) const; + void ToNative(blst_p1 *output) const; + void ToAffine(blst_p1_affine *output) const; G1Element Negate() const; GTElement Pair(const G2Element &b) const; uint32_t GetFingerprint(bool fLegacy = false) const; @@ -65,41 +62,41 @@ class G1Element { friend bool operator==(const G1Element &a, const G1Element &b); friend bool operator!=(const G1Element &a, const G1Element &b); friend std::ostream &operator<<(std::ostream &os, const G1Element &s); - friend G1Element& operator+=(G1Element& a, const G1Element& b); + friend G1Element &operator+=(G1Element &a, const G1Element &b); friend G1Element operator+(const G1Element &a, const G1Element &b); - friend G1Element operator*(const G1Element &a, const bn_t &k); - friend G1Element operator*(const bn_t &k, const G1Element &a); + friend G1Element operator*(const G1Element &a, const blst_scalar &k); + friend G1Element operator*(const blst_scalar &k, const G1Element &a); friend GTElement operator&(const G1Element &a, const G2Element &b); private: - g1_t p; + blst_p1 p; }; class G2Element { public: static const size_t SIZE = 96; - G2Element() { - g2_set_infty(q); - } - - static G2Element FromBytes(Bytes bytes, bool fLegacy = false); - static G2Element FromBytesUnchecked(Bytes bytes, bool fLegacy = false); - static G2Element FromByteVector(const std::vector &bytevec, bool fLegacy = false); - static G2Element FromNative(const g2_t element); - static G2Element FromMessage(const std::vector& message, - const uint8_t* dst, - int dst_len, - bool fLegacy = false); - static G2Element FromMessage(Bytes message, - const uint8_t* dst, - int dst_len, - bool fLegacy = false); + G2Element() { memset(&q, 0x00, sizeof(blst_p2)); } + + static G2Element FromBytes(Bytes bytes, bool legacy_encoding = false); + static G2Element FromBytesUnchecked(Bytes bytes, bool legacy_encoding = false); + static G2Element FromByteVector(const std::vector &bytevec, bool legacy_encoding = false); + static G2Element FromNative(const blst_p2 &element); + static G2Element FromAffine(const blst_p2_affine &element); + static G2Element FromMessage( + const std::vector &message, + const uint8_t *dst, + size_t dst_len, bool legacy_encoding = false); + static G2Element FromMessage( + Bytes message, + const uint8_t *dst, + size_t dst_len, bool legacy_encoding = false); static G2Element Generator(); bool IsValid() const; void CheckValid() const; - void ToNative(g2_t output) const; + void ToNative(blst_p2 *output) const; + void ToAffine(blst_p2_affine *output) const; G2Element Negate() const; GTElement Pair(const G1Element &a) const; std::vector Serialize(bool fLegacy = false) const; @@ -109,22 +106,25 @@ class G2Element { friend bool operator==(G2Element const &a, G2Element const &b); friend bool operator!=(G2Element const &a, G2Element const &b); friend std::ostream &operator<<(std::ostream &os, const G2Element &s); - friend G2Element& operator+=(G2Element& a, const G2Element& b); + friend G2Element &operator+=(G2Element &a, const G2Element &b); friend G2Element operator+(const G2Element &a, const G2Element &b); - friend G2Element operator*(const G2Element &a, const bn_t &k); - friend G2Element operator*(const bn_t &k, const G2Element &a); + friend G2Element operator*(const G2Element &a, const blst_scalar &k); + friend G2Element operator*(const blst_scalar &k, const G2Element &a); private: - g2_t q; + blst_p2 q; }; class GTElement { public: - static const size_t SIZE = 384; + static const size_t SIZE = sizeof(blst_fp12); + static GTElement FromBytes(Bytes bytes); static GTElement FromBytesUnchecked(Bytes bytes); static GTElement FromByteVector(const std::vector &bytevec); - static GTElement FromNative(const gt_t *element); + static GTElement FromNative(const blst_fp12 *element); + static GTElement FromAffine(const blst_p1_affine &element); + static GTElement FromAffine(const blst_p2_affine &element); static GTElement Unity(); // unity void Serialize(uint8_t *buffer) const; @@ -135,10 +135,9 @@ class GTElement { friend bool operator!=(GTElement const &a, GTElement const &b); friend std::ostream &operator<<(std::ostream &os, const GTElement &s); friend GTElement operator*(GTElement &a, GTElement &b); - GTElement &operator=(const GTElement &rhs); private: - gt_t r; + blst_fp12 r; GTElement() {} }; diff --git a/src/dashbls/include/dashbls/extendedprivatekey.hpp b/src/dashbls/include/dashbls/extendedprivatekey.hpp index aefdbf057257..575256ab9425 100644 --- a/src/dashbls/include/dashbls/extendedprivatekey.hpp +++ b/src/dashbls/include/dashbls/extendedprivatekey.hpp @@ -15,21 +15,13 @@ #ifndef SRC_EXTENDEDPRIVATEKEY_HPP_ #define SRC_EXTENDEDPRIVATEKEY_HPP_ -#include "relic_conf.h" - #include -#if defined GMP && ARITH == GMP -#include -#endif - #include "chaincode.hpp" #include "elements.hpp" #include "extendedpublickey.hpp" #include "privatekey.hpp" -#include "relic.h" -#include "relic_test.h" namespace bls { /* diff --git a/src/dashbls/include/dashbls/extendedpublickey.hpp b/src/dashbls/include/dashbls/extendedpublickey.hpp index b44d5c636a3c..c1fbdf7bf0dd 100644 --- a/src/dashbls/include/dashbls/extendedpublickey.hpp +++ b/src/dashbls/include/dashbls/extendedpublickey.hpp @@ -15,20 +15,12 @@ #ifndef SRC_EXTENDEDPUBLICKEY_HPP_ #define SRC_EXTENDEDPUBLICKEY_HPP_ -#include "relic_conf.h" - #include -#if defined GMP && ARITH == GMP -#include -#endif - #include "chaincode.hpp" #include "elements.hpp" -#include "relic.h" -#include "relic_test.h" namespace bls { diff --git a/src/dashbls/include/dashbls/hdkeys.hpp b/src/dashbls/include/dashbls/hdkeys.hpp index 629ec5e3d142..1cadd7423b9c 100644 --- a/src/dashbls/include/dashbls/hdkeys.hpp +++ b/src/dashbls/include/dashbls/hdkeys.hpp @@ -15,16 +15,11 @@ #ifndef SRC_BLSHDKEYS_HPP_ #define SRC_BLSHDKEYS_HPP_ -#include "relic_conf.h" #include -#if defined GMP && ARITH == GMP -#include -#endif - -#include "util.hpp" -#include "privatekey.hpp" #include "hkdf.hpp" +#include "privatekey.hpp" +#include "util.hpp" namespace bls { @@ -32,14 +27,14 @@ class HDKeys { /** * Implements HD keys as specified in EIP2333. **/ - public: +public: static const uint8_t HASH_LEN = 32; static PrivateKey KeyGen(const std::vector& seed) { return KeyGen(Bytes(seed)); } - + static PrivateKey KeyGen(const Bytes& seed) { // KeyGen @@ -56,65 +51,44 @@ class HDKeys { throw std::invalid_argument("Seed size must be at least 32 bytes"); } - // "BLS-SIG-KEYGEN-SALT-" in ascii - const uint8_t saltHkdf[20] = {66, 76, 83, 45, 83, 73, 71, 45, 75, 69, - 89, 71, 69, 78, 45, 83, 65, 76, 84, 45}; + blst_scalar* skBn = Util::SecAlloc(1); + blst_keygen_v3(skBn, seed.begin(), seed.size(), info, infoLen); + uint8_t* skBytes = Util::SecAlloc(32); + blst_bendian_from_scalar(skBytes, skBn); - uint8_t *prk = Util::SecAlloc(32); - uint8_t *ikmHkdf = Util::SecAlloc(seed.size() + 1); - memcpy(ikmHkdf, seed.begin(), seed.size()); - ikmHkdf[seed.size()] = 0; - - const uint8_t L = 48; // `ceil((3 * ceil(log2(r))) / 16)`, where `r` is the - // order of the BLS 12-381 curve - - uint8_t *okmHkdf = Util::SecAlloc(L); - - uint8_t keyInfoHkdf[infoLen + 2]; - memcpy(keyInfoHkdf, info, infoLen); - keyInfoHkdf[infoLen] = 0; // Two bytes for L, 0 and 48 - keyInfoHkdf[infoLen + 1] = L; - - HKDF256::ExtractExpand( - okmHkdf, - L, - ikmHkdf, - seed.size() + 1, - saltHkdf, - 20, - keyInfoHkdf, - infoLen + 2); - - bn_t order; - bn_new(order); - g1_get_ord(order); - - // Make sure private key is less than the curve order - bn_t *skBn = Util::SecAlloc(1); - bn_new(*skBn); - bn_read_bin(*skBn, okmHkdf, L); - bn_mod_basic(*skBn, *skBn, order); - - uint8_t *skBytes = Util::SecAlloc(32); - bn_write_bin(skBytes, 32, *skBn); PrivateKey k = PrivateKey::FromBytes(Bytes(skBytes, 32)); - Util::SecFree(prk); - Util::SecFree(ikmHkdf); Util::SecFree(skBn); - Util::SecFree(okmHkdf); Util::SecFree(skBytes); return k; } - static void IKMToLamportSk(uint8_t* outputLamportSk, const uint8_t* ikm, size_t ikmLen, const uint8_t* salt, size_t saltLen) { + static void IKMToLamportSk( + uint8_t* outputLamportSk, + const uint8_t* ikm, + size_t ikmLen, + const uint8_t* salt, + size_t saltLen) + { // Expands the ikm to 255*HASH_LEN bytes for the lamport sk const uint8_t info[1] = {0}; - HKDF256::ExtractExpand(outputLamportSk, HASH_LEN * 255, ikm, ikmLen, salt, saltLen, info, 0); + HKDF256::ExtractExpand( + outputLamportSk, + HASH_LEN * 255, + ikm, + ikmLen, + salt, + saltLen, + info, + 0); } - static void ParentSkToLamportPK(uint8_t* outputLamportPk, const PrivateKey& parentSk, uint32_t index) { + static void ParentSkToLamportPK( + uint8_t* outputLamportPk, + const PrivateKey& parentSk, + uint32_t index) + { uint8_t* salt = Util::SecAlloc(4); uint8_t* ikm = Util::SecAlloc(HASH_LEN); uint8_t* notIkm = Util::SecAlloc(HASH_LEN); @@ -134,11 +108,15 @@ class HDKeys { uint8_t* lamportPk = Util::SecAlloc(HASH_LEN * 255 * 2); for (size_t i = 0; i < 255; i++) { - Util::Hash256(lamportPk + i * HASH_LEN, lamport0 + i * HASH_LEN, HASH_LEN); + Util::Hash256( + lamportPk + i * HASH_LEN, lamport0 + i * HASH_LEN, HASH_LEN); } - for (size_t i=0; i < 255; i++) { - Util::Hash256(lamportPk + 255 * HASH_LEN + i * HASH_LEN, lamport1 + i * HASH_LEN, HASH_LEN); + for (size_t i = 0; i < 255; i++) { + Util::Hash256( + lamportPk + 255 * HASH_LEN + i * HASH_LEN, + lamport1 + i * HASH_LEN, + HASH_LEN); } Util::Hash256(outputLamportPk, lamportPk, HASH_LEN * 255 * 2); @@ -150,7 +128,8 @@ class HDKeys { Util::SecFree(lamportPk); } - static PrivateKey DeriveChildSk(const PrivateKey& parentSk, uint32_t index) { + static PrivateKey DeriveChildSk(const PrivateKey& parentSk, uint32_t index) + { uint8_t* lamportPk = Util::SecAlloc(HASH_LEN); HDKeys::ParentSkToLamportPK(lamportPk, parentSk, index); std::vector lamportPkVector(lamportPk, lamportPk + HASH_LEN); @@ -159,21 +138,29 @@ class HDKeys { return child; } - static PrivateKey DeriveChildSkUnhardened(const PrivateKey& parentSk, uint32_t index) { + static PrivateKey DeriveChildSkUnhardened( + const PrivateKey& parentSk, + uint32_t index) + { uint8_t* buf = Util::SecAlloc(G1Element::SIZE + 4); uint8_t* digest = Util::SecAlloc(HASH_LEN); - memcpy(buf, parentSk.GetG1Element().Serialize().data(), G1Element::SIZE); + memcpy( + buf, parentSk.GetG1Element().Serialize().data(), G1Element::SIZE); Util::IntToFourBytes(buf + G1Element::SIZE, index); Util::Hash256(digest, buf, G1Element::SIZE + 4); - PrivateKey ret = PrivateKey::Aggregate({parentSk, PrivateKey::FromBytes(Bytes(digest, HASH_LEN), true)}); + PrivateKey ret = PrivateKey::Aggregate( + {parentSk, PrivateKey::FromBytes(Bytes(digest, HASH_LEN), true)}); Util::SecFree(buf); Util::SecFree(digest); return ret; } - static G1Element DeriveChildG1Unhardened(const G1Element& pk, uint32_t index) { + static G1Element DeriveChildG1Unhardened( + const G1Element& pk, + uint32_t index) + { uint8_t* buf = Util::SecAlloc(G1Element::SIZE + 4); uint8_t* digest = Util::SecAlloc(HASH_LEN); memcpy(buf, pk.Serialize().data(), G1Element::SIZE); @@ -181,35 +168,33 @@ class HDKeys { Util::IntToFourBytes(buf + G1Element::SIZE, index); Util::Hash256(digest, buf, G1Element::SIZE + 4); - bn_t nonce, ord; - bn_new(nonce); - bn_zero(nonce); - bn_read_bin(nonce, digest, HASH_LEN); - bn_new(ord); - g1_get_ord(ord); - bn_mod_basic(nonce, nonce, ord); + blst_scalar nonce; + // The digest is big-endian; upstream chia loaded it as little-endian, + // which only worked because operator* reversed the bytes again. + blst_scalar_from_bendian(&nonce, digest); Util::SecFree(buf); Util::SecFree(digest); G1Element gen = G1Element::Generator(); - return pk + gen * nonce; + + return pk + (gen * nonce); } - static G2Element DeriveChildG2Unhardened(const G2Element& pk, uint32_t index) { + static G2Element DeriveChildG2Unhardened( + const G2Element& pk, + uint32_t index) + { uint8_t* buf = Util::SecAlloc(G2Element::SIZE + 4); uint8_t* digest = Util::SecAlloc(HASH_LEN); memcpy(buf, pk.Serialize().data(), G2Element::SIZE); Util::IntToFourBytes(buf + G2Element::SIZE, index); Util::Hash256(digest, buf, G2Element::SIZE + 4); - bn_t nonce, ord; - bn_new(nonce); - bn_zero(nonce); - bn_read_bin(nonce, digest, HASH_LEN); - bn_new(ord); - g1_get_ord(ord); - bn_mod_basic(nonce, nonce, ord); + blst_scalar nonce; + // The digest is big-endian; upstream chia loaded it as little-endian, + // which only worked because operator* reversed the bytes again. + blst_scalar_from_bendian(&nonce, digest); Util::SecFree(buf); Util::SecFree(digest); @@ -218,5 +203,5 @@ class HDKeys { return pk + gen * nonce; } }; -} // end namespace bls +} // end namespace bls #endif // SRC_BLSHDKEYS_HPP_ diff --git a/src/dashbls/include/dashbls/hkdf.hpp b/src/dashbls/include/dashbls/hkdf.hpp index a7ddc863ebab..e338966dc784 100644 --- a/src/dashbls/include/dashbls/hkdf.hpp +++ b/src/dashbls/include/dashbls/hkdf.hpp @@ -15,13 +15,7 @@ #ifndef SRC_BLSHKDF_HPP_ #define SRC_BLSHKDF_HPP_ -#include "relic_conf.h" #include - -#if defined GMP && ARITH == GMP -#include -#endif - #include #include "util.hpp" @@ -40,12 +34,11 @@ class HKDF256 { // assert(ikm_len == 32); // Used for EIP2333 key derivation // Hash256 used as the hash function (sha256) // PRK Output is 32 bytes (HashLen) - md_hmac(prk_output, ikm, ikm_len, salt, saltLen); + Util::md_hmac(prk_output, ikm, ikm_len, salt, saltLen); } static void Expand(uint8_t* okm, size_t L, const uint8_t* prk, const uint8_t* info, const size_t infoLen) { assert(L <= 255 * HASH_LEN); // L <= 255 * HashLen - assert(infoLen >= 0); size_t N = (L + HASH_LEN - 1) / HASH_LEN; // Round up size_t bytesWritten = 0; @@ -59,12 +52,12 @@ class HKDF256 { if (i == 1) { memcpy(hmacInput1, info, infoLen); hmacInput1[infoLen] = i; - md_hmac(T, hmacInput1, infoLen + 1, prk, HASH_LEN); + Util::md_hmac(T, hmacInput1, infoLen + 1, prk, HASH_LEN); } else { memcpy(hmacInput, T, HASH_LEN); memcpy(hmacInput + HASH_LEN, info, infoLen); hmacInput[HASH_LEN + infoLen] = i; - md_hmac(T, hmacInput, HASH_LEN + infoLen + 1, prk, HASH_LEN); + Util::md_hmac(T, hmacInput, HASH_LEN + infoLen + 1, prk, HASH_LEN); } size_t to_write = L - bytesWritten; if (to_write > HASH_LEN) { diff --git a/src/dashbls/include/dashbls/legacy.hpp b/src/dashbls/include/dashbls/legacy.hpp index b3e1ee1345f1..30621760694b 100644 --- a/src/dashbls/include/dashbls/legacy.hpp +++ b/src/dashbls/include/dashbls/legacy.hpp @@ -5,27 +5,24 @@ #ifndef SRC_LEGACY_HPP_ #define SRC_LEGACY_HPP_ -#include - -#include "relic_conf.h" - -#if defined GMP && ARITH == GMP -#include -#endif - extern "C" { -#include "relic.h" +#include "blst.h" } +#include + +namespace bls { /** * Maps a byte array to a point in an elliptic curve over a quadratic extension. * - * Called ep2_map() in old relic version, _legacy prefix is to avoid duplicated symbols + * Called ep2_map() in old relic version. Now reimplemented on blst and must stay + * bit-for-bit compatible: pre-v19 (legacy scheme) consensus depends on it. * - * @param[out] p - the result. - * @param[in] msg - the byte array to map. - * @param[in] len - the array length in bytes. + * @param[out] p - the result. + * @param[in] msg - the byte array to map (must be 32 bytes). + * @param[in] len - the array length in bytes (must be 32). */ -void ep2_map_legacy(ep2_t p, const uint8_t *msg, int len); +void ep2_map_legacy(blst_p2 *p, const uint8_t *msg, size_t len); +} // namespace bls #endif // #define SRC_LEGACY_HPP_ diff --git a/src/dashbls/include/dashbls/privatekey.hpp b/src/dashbls/include/dashbls/privatekey.hpp index d02a7d292c12..a85051da59b5 100644 --- a/src/dashbls/include/dashbls/privatekey.hpp +++ b/src/dashbls/include/dashbls/privatekey.hpp @@ -15,12 +15,6 @@ #ifndef SRC_BLSPRIVATEKEY_HPP_ #define SRC_BLSPRIVATEKEY_HPP_ -#include "relic_conf.h" - -#if defined GMP && ARITH == GMP -#include -#endif - #include "elements.hpp" namespace bls { @@ -34,9 +28,6 @@ class PrivateKey { // Construct a private key from a BIP32 based seed. static PrivateKey FromSeedBIP32(const Bytes& seed); - // Construct a random private key. - static PrivateKey RandomPrivateKey(); - // Construct a private key from a bytearray. static PrivateKey FromBytes(const Bytes& bytes, bool modOrder = false); @@ -76,13 +67,13 @@ class PrivateKey { friend G2Element operator*(const G2Element &a, const PrivateKey &k); friend G2Element operator*(const PrivateKey &k, const G2Element &a); - friend PrivateKey operator*(const PrivateKey& a, const bn_t& k); - friend PrivateKey operator*(const bn_t& k, const PrivateKey& a); + friend PrivateKey operator*(const PrivateKey& a, const blst_scalar& k); + friend PrivateKey operator*(const blst_scalar& k, const PrivateKey& a); // Serialize the key into bytes void Serialize(uint8_t *buffer) const; - std::vector Serialize(bool fLegacy = false) const; - std::array SerializeToArray(bool fLegacy = false) const; + std::vector Serialize() const; + std::array SerializeToArray() const; G2Element SignG2( const uint8_t *msg, @@ -105,7 +96,7 @@ class PrivateKey { void InvalidateCaches(); // The actual byte data - bn_st* keydata{nullptr}; + blst_scalar* keydata{nullptr}; mutable bool fG1CacheValid{false}; mutable G1Element g1Cache; diff --git a/src/dashbls/include/dashbls/schemes.hpp b/src/dashbls/include/dashbls/schemes.hpp index 1aee61dd346d..a7dbdf2b2ce3 100644 --- a/src/dashbls/include/dashbls/schemes.hpp +++ b/src/dashbls/include/dashbls/schemes.hpp @@ -1,14 +1,14 @@ // Copyright 2020 Chia Network Inc // Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in coiance with the License. +// you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or iied. +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. @@ -19,12 +19,6 @@ #include #include -#include "relic_conf.h" - -#if defined GMP && ARITH == GMP -#include -#endif - #include "elements.hpp" #include "privatekey.hpp" @@ -36,7 +30,6 @@ namespace bls { class Bytes; class CoreMPL { - public: CoreMPL() = delete; CoreMPL(const std::string& strId) : strCiphersuiteId(strId) {} @@ -47,31 +40,42 @@ class CoreMPL { virtual PrivateKey KeyGen(const Bytes& seed); // Generates a public key from a secret key - virtual vector SkToPk(const PrivateKey &seckey); + virtual vector SkToPk(const PrivateKey& seckey); - virtual G1Element SkToG1(const PrivateKey &seckey); + virtual G1Element SkToG1(const PrivateKey& seckey); - virtual G2Element Sign(const PrivateKey &seckey, const vector &message); + virtual G2Element Sign( + const PrivateKey& seckey, + const vector& message); virtual G2Element Sign(const PrivateKey& seckey, const Bytes& message); - virtual bool Verify(const vector &pubkey, - const vector &message, - const vector &signature); + virtual bool Verify( + const vector& pubkey, + const vector& message, + const vector& signature); - virtual bool Verify(const Bytes& pubkey, const Bytes& message, const Bytes& signature); + virtual bool Verify( + const Bytes& pubkey, + const Bytes& message, + const Bytes& signature); - virtual bool Verify(const G1Element &pubkey, - const vector &message, - const G2Element &signature); + virtual bool Verify( + const G1Element& pubkey, + const vector& message, + const G2Element& signature); - virtual bool Verify(const G1Element& pubkey, const Bytes& message, const G2Element& signature); + virtual bool Verify( + const G1Element& pubkey, + const Bytes& message, + const G2Element& signature); - virtual std::array Aggregate(const vector> &signatures); + virtual std::array Aggregate( + const vector>& signatures); virtual std::array Aggregate(const vector& signatures); - virtual G2Element Aggregate(const vector &signatures); + virtual G2Element Aggregate(const vector& signatures); - virtual G1Element Aggregate(const vector &publicKeys); + virtual G1Element Aggregate(const vector& publicKeys); virtual G2Element AggregateSecure(const std::vector& vecPublicKeys, const std::vector& vecSignatures, @@ -81,21 +85,25 @@ class CoreMPL { const G2Element& signature, const Bytes& message); - virtual bool AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature); + virtual bool AggregateVerify( + const vector>& pubkeys, + const vector>& messages, + const vector& signature); - virtual bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const Bytes& signature); + virtual bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const Bytes& signature); - virtual bool AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature); + virtual bool AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature); - virtual bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const G2Element& signature); + virtual bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature); PrivateKey DeriveChildSk(const PrivateKey& sk, uint32_t index); PrivateKey DeriveChildSkUnhardened(const PrivateKey& sk, uint32_t index); @@ -103,7 +111,8 @@ class CoreMPL { protected: const std::string& strCiphersuiteId; - bool NativeVerify(g1_t *pubKeys, g2_t *mappedHashes, size_t length); + static bool NativeVerify(const std::vector& g1s, + const std::vector& g2s); G2Element AggregateSecure(std::vector const &vecPublicKeys, std::vector const &vecSignatures, const Bytes& message, @@ -118,106 +127,127 @@ class BasicSchemeMPL final : public CoreMPL { public: static const std::string CIPHERSUITE_ID; BasicSchemeMPL() : CoreMPL(BasicSchemeMPL::CIPHERSUITE_ID) {} - bool AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature) override; - - bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const Bytes& signature) override; - - bool AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature) override; - - bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const G2Element& signature) override; + bool AggregateVerify( + const vector>& pubkeys, + const vector>& messages, + const vector& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const Bytes& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature) override; }; class AugSchemeMPL final : public CoreMPL { - public: static const std::string CIPHERSUITE_ID; AugSchemeMPL() : CoreMPL(AugSchemeMPL::CIPHERSUITE_ID) {} - G2Element Sign(const PrivateKey &seckey, const vector &message) override; + G2Element Sign(const PrivateKey& seckey, const vector& message) + override; G2Element Sign(const PrivateKey& seckey, const Bytes& message) override; // Used for prepending different augMessage - G2Element Sign(const PrivateKey &seckey, - const vector &message, - const G1Element &prepend_pk); + G2Element Sign( + const PrivateKey& seckey, + const vector& message, + const G1Element& prepend_pk); // Used for prepending different augMessage - G2Element Sign(const PrivateKey& seckey, - const Bytes& message, - const G1Element& prepend_pk); - - bool Verify(const vector &pubkey, - const vector &message, - const vector &signature) override; - - bool Verify(const Bytes& pubkey, - const Bytes& message, - const Bytes& signature) override; - - bool Verify(const G1Element &pubkey, - const vector &message, - const G2Element &signature) override; - - bool Verify(const G1Element& pubkey, - const Bytes& message, - const G2Element& signature) override; + G2Element Sign( + const PrivateKey& seckey, + const Bytes& message, + const G1Element& prepend_pk); + + bool Verify( + const vector& pubkey, + const vector& message, + const vector& signature) override; + + bool Verify( + const Bytes& pubkey, + const Bytes& message, + const Bytes& signature) override; + + bool Verify( + const G1Element& pubkey, + const vector& message, + const G2Element& signature) override; + + bool Verify( + const G1Element& pubkey, + const Bytes& message, + const G2Element& signature) override; + + bool AggregateVerify( + const vector>& pubkeys, + const vector>& messages, + const vector& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const Bytes& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature) override; - bool AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature) override; - - bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const Bytes& signature) override; - - bool AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature) override; - - bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const G2Element& signature) override; + bool VerifySecure(const std::vector& vecPublicKeys, + const G2Element& signature, + const Bytes& message) override; }; class PopSchemeMPL final : public CoreMPL { - public: static const std::string CIPHERSUITE_ID; static const std::string POP_CIPHERSUITE_ID; PopSchemeMPL() : CoreMPL(PopSchemeMPL::CIPHERSUITE_ID) {} - G2Element PopProve(const PrivateKey &seckey); + G2Element PopProve(const PrivateKey& seckey); - bool PopVerify(const G1Element &pubkey, const G2Element &signature_proof); + bool PopVerify(const G1Element& pubkey, const G2Element& signature_proof); - bool PopVerify(const vector &pubkey, const vector &proof); + bool PopVerify(const vector& pubkey, const vector& proof); bool PopVerify(const Bytes& pubkey, const Bytes& proof); - bool FastAggregateVerify(const vector &pubkeys, - const vector &message, - const G2Element &signature); - - bool FastAggregateVerify(const vector& pubkeys, - const Bytes& message, - const G2Element& signature); - - bool FastAggregateVerify(const vector> &pubkeys, - const vector &message, - const vector &signature); - - bool FastAggregateVerify(const vector& pubkeys, - const Bytes& message, - const Bytes& signature); + bool FastAggregateVerify( + const vector& pubkeys, + const vector& message, + const G2Element& signature); + + bool FastAggregateVerify( + const vector& pubkeys, + const Bytes& message, + const G2Element& signature); + + bool FastAggregateVerify( + const vector>& pubkeys, + const vector& message, + const vector& signature); + + bool FastAggregateVerify( + const vector& pubkeys, + const Bytes& message, + const Bytes& signature); }; /** @@ -228,23 +258,23 @@ class LegacySchemeMPL final : public CoreMPL { public: LegacySchemeMPL() : CoreMPL(std::string{}) {} - virtual vector SkToPk(const PrivateKey &seckey) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + virtual vector SkToPk(const PrivateKey &) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } - G2Element Sign(const PrivateKey &seckey, const vector &message) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + G2Element Sign(const PrivateKey &, const vector &) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } G2Element Sign(const PrivateKey &seckey, const Bytes& message) final; - bool Verify(const vector& pubkey, - const vector& message, - const vector& signature) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + bool Verify(const vector&, + const vector&, + const vector&) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } - bool Verify(const G1Element& pubkey, - const vector& message, - const G2Element& signature) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + bool Verify(const G1Element&, + const vector&, + const G2Element&) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } - bool Verify(const Bytes& pubkey, const Bytes& message, const Bytes& signature) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + bool Verify(const Bytes&, const Bytes&, const Bytes&) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } bool Verify(const G1Element &pubkey, const Bytes& message, const G2Element &signature) final; - std::array Aggregate(const vector> &signatures) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + std::array Aggregate(const vector> &) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } G2Element AggregateSecure(const std::vector& vecPublicKeys, const std::vector& vecSignatures, @@ -254,17 +284,17 @@ class LegacySchemeMPL final : public CoreMPL { const G2Element& signature, const Bytes& message) final; - bool AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + bool AggregateVerify(const vector> &, + const vector> &, + const vector &) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } - bool AggregateVerify(const vector &pubkeys, - const vector &messages, - const Bytes &signature) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + bool AggregateVerify(const vector &, + const vector &, + const Bytes &) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } - bool AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + bool AggregateVerify(const vector &, + const vector> &, + const G2Element &) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } bool AggregateVerify(const vector &pubkeys, const vector &messages, diff --git a/src/dashbls/include/dashbls/test-utils.hpp b/src/dashbls/include/dashbls/test-utils.hpp index 154079ff4a99..237940c87c1c 100644 --- a/src/dashbls/include/dashbls/test-utils.hpp +++ b/src/dashbls/include/dashbls/test-utils.hpp @@ -47,10 +47,10 @@ void endStopwatch(string testName, std::vector getRandomSeed() { uint8_t buf[32]; - bn_t r; - bn_new(r); - bn_rand(r, RLC_POS, 256); - bn_write_bin(buf, 32, r); + + for (int i = 0; i < 32; i++) + buf[i] = rand (); + std::vector ret(buf, buf + 32); return ret; } diff --git a/src/dashbls/include/dashbls/util.hpp b/src/dashbls/include/dashbls/util.hpp index 37fd8547a983..02ec7b3877a7 100644 --- a/src/dashbls/include/dashbls/util.hpp +++ b/src/dashbls/include/dashbls/util.hpp @@ -19,9 +19,14 @@ #include #include #include +#include #include #include +extern "C" { +#include "blst.h" +} + namespace bls { class BLS; @@ -60,8 +65,41 @@ class Util { public: static void Hash256(uint8_t* output, const uint8_t* message, size_t messageLen) { - md_map_sh256(output, message, messageLen); + blst_sha256(output, message, messageLen); + } + +static void md_hmac(uint8_t *mac, const uint8_t *in, size_t in_len, const uint8_t *key, + size_t key_len) { + constexpr size_t block_size = 64; + constexpr size_t md_len = 32; + // The pads and the padded key are derived from the key, so they live in + // the same secure memory as the private keys (see SecAlloc). + uint8_t *buf = SecAlloc(block_size + md_len + block_size + in_len + block_size); + if (buf == NULL) + throw std::runtime_error("out of memory"); + uint8_t *opad = buf; // block_size + md_len + uint8_t *ipad = opad + block_size + md_len; // block_size + in_len + uint8_t *_key = ipad + block_size + in_len; // block_size + + if (key_len > block_size) { + Hash256(_key, key, key_len); + key_len = md_len; + } else { + memcpy(_key, key, key_len); } + memset(_key + key_len, 0, block_size - key_len); + key = _key; + + for (size_t i = 0; i < block_size; i++) { + opad[i] = 0x5C ^ key[i]; + ipad[i] = 0x36 ^ key[i]; + } + memcpy(ipad + block_size, in, in_len); + Hash256(opad + block_size, ipad, block_size + in_len); + Hash256(mac, opad, block_size + md_len); + + SecFree(buf); +} static std::string HexStr(const uint8_t* data, size_t len) { std::stringstream s; @@ -80,8 +118,8 @@ class Util { } /* - * Securely allocates a portion of memory, using libsodium. This prevents - * paging to disk, and zeroes out the memory when it's freed. + * Securely allocates a portion of memory. This prevents paging to disk, + * and zeroes out the memory when it's freed. */ template static T* SecAlloc(size_t numTs) { diff --git a/src/dashbls/js-bindings/CMakeLists.txt b/src/dashbls/js-bindings/CMakeLists.txt index 5790f3a11619..86660a01a011 100644 --- a/src/dashbls/js-bindings/CMakeLists.txt +++ b/src/dashbls/js-bindings/CMakeLists.txt @@ -5,8 +5,6 @@ include_directories( ${INCLUDE_DIRECTORIES} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../include - ${CMAKE_CURRENT_SOURCE_DIR}/../depends/relic/include - ${CMAKE_CURRENT_BINARY_DIR}/../depends/relic/include ${CMAKE_CURRENT_SOURCE_DIR}/../depends/catch2/include ) diff --git a/src/dashbls/js-bindings/blsjs.d.ts b/src/dashbls/js-bindings/blsjs.d.ts index 95cb05962ad1..556a2a8edaaf 100644 --- a/src/dashbls/js-bindings/blsjs.d.ts +++ b/src/dashbls/js-bindings/blsjs.d.ts @@ -48,7 +48,6 @@ export declare class G1Element { deepcopy(): G1Element; getFingerprint(): number; add(el: G1Element): G1Element; - mul(bn: Bignum): G1Element; equalTo(el: G1Element): boolean; delete(): void; } @@ -63,7 +62,6 @@ export declare class G2Element { negate(): G2Element; deepcopy(): G2Element; add(el: G2Element): G2Element; - mul(bn: Bignum): G2Element; equalTo(el: G2Element): boolean; delete(): void; } @@ -82,12 +80,6 @@ export declare class PrivateKey { delete(): void; } -export declare class Bignum { - static fromString(s: string, radix: number): Bignum; - toString(radix: number): string; - delete(): void; -} - export declare class Util { static hash256(msg: Uint8Array): Uint8Array; static hexStr(msg: Uint8Array): string; @@ -100,7 +92,6 @@ export interface ModuleInstance { G1Element: typeof G1Element; G2Element: typeof G2Element; PrivateKey: typeof PrivateKey; - Bignum: typeof Bignum; Util: typeof Util; } diff --git a/src/dashbls/js-bindings/helpers.cpp b/src/dashbls/js-bindings/helpers.cpp index e58f5e4909f2..41a92a0a2e41 100644 --- a/src/dashbls/js-bindings/helpers.cpp +++ b/src/dashbls/js-bindings/helpers.cpp @@ -26,12 +26,6 @@ namespace helpers { return buffer; } - val toUint8Array(bn_t bn) { - std::vector vec = toVector(bn); - val buffer = toUint8Array(vec); - return buffer; - } - std::vector toVector(uint8_t *pointer, size_t data_size) { std::vector data; data.reserve(data_size); @@ -48,13 +42,6 @@ namespace helpers { return vec; } - std::vector toVector(bn_t bn) { - uint8_t buf[bn_size_bin(bn)]; - bn_write_bin(buf, bn_size_bin(bn), bn); - std::vector vec = helpers::toVector(buf, bn_size_bin(bn)); - return vec; - } - std::vector> jsBuffersArrayToVector(val buffersArray) { auto l = buffersArray["length"].as(); std::vector> vec; @@ -64,20 +51,6 @@ namespace helpers { return vec; } - std::vector jsBuffersArrayToBnVector(val buffersArray) { - auto l = buffersArray["length"].as(); - std::vector vec; - for (unsigned i = 0; i < l; ++i) { - bn_t data; - bn_new(data); - std::vector bnVec = toVector(buffersArray[i]); - bn_read_bin(data, bnVec.data(), static_cast(bnVec.size())); - bn_t *point = &data; - vec.push_back(point); - } - return vec; - } - val byteArraysVectorToJsBuffersArray(std::vector arraysVector, size_t element_size) { auto vecSize = arraysVector.size(); std::vector valVector; diff --git a/src/dashbls/js-bindings/helpers.h b/src/dashbls/js-bindings/helpers.h index 031df07043dc..faf2976e3e31 100644 --- a/src/dashbls/js-bindings/helpers.h +++ b/src/dashbls/js-bindings/helpers.h @@ -18,9 +18,6 @@ #include #include #include -extern "C" { -#include -} #include using namespace emscripten; @@ -31,14 +28,10 @@ namespace helpers { val toUint8Array(std::vector vec); - val toUint8Array(bn_t bn); - std::vector toVector(uint8_t *pointer, size_t data_size); std::vector toVector(val jsBuffer); - std::vector toVector(bn_t bn); - template inline std::vector toVectorFromJSArray(val jsArray) { auto l = jsArray["length"].as(); @@ -62,8 +55,6 @@ namespace helpers { std::vector> jsBuffersArrayToVector(val buffersArray); - std::vector jsBuffersArrayToBnVector(val buffersArray); - val byteArraysVectorToJsBuffersArray(std::vector arraysVector, size_t element_size); } // namespace helpers diff --git a/src/dashbls/js-bindings/jsbindings.cpp b/src/dashbls/js-bindings/jsbindings.cpp index 81daa4abc74e..6e9d45f1160b 100644 --- a/src/dashbls/js-bindings/jsbindings.cpp +++ b/src/dashbls/js-bindings/jsbindings.cpp @@ -70,7 +70,6 @@ EMSCRIPTEN_BINDINGS(blsjs) { .function("deepcopy", &G1ElementWrapper::Deepcopy) .function("getFingerprint", &G1ElementWrapper::GetFingerprint) .function("add", &G1ElementWrapper::Add) - .function("mul", &G1ElementWrapper::Mul) .function("equalTo", &G1ElementWrapper::EqualTo); class_("G2Element") @@ -84,7 +83,6 @@ EMSCRIPTEN_BINDINGS(blsjs) { .function("negate", &G2ElementWrapper::Negate) .function("deepcopy", &G2ElementWrapper::Deepcopy) .function("add", &G2ElementWrapper::Add) - .function("mul", &G2ElementWrapper::Mul) .function("equalTo", &G2ElementWrapper::EqualTo); class_("PrivateKey") @@ -99,10 +97,6 @@ EMSCRIPTEN_BINDINGS(blsjs) { .function("mulG2", &PrivateKeyWrapper::MulG2) .function("equalTo", &PrivateKeyWrapper::EqualTo); - class_("Bignum") - .class_function("fromString", &BignumWrapper::FromString) - .function("toString", &BignumWrapper::ToString); - class_("Util") .class_function("hash256", &UtilWrapper::Hash256) .class_function("hexStr", &UtilWrapper::HexStr); diff --git a/src/dashbls/js-bindings/tests/test.js b/src/dashbls/js-bindings/tests/test.js index 34671d6546b7..7c1455932f4f 100644 --- a/src/dashbls/js-bindings/tests/test.js +++ b/src/dashbls/js-bindings/tests/test.js @@ -22,7 +22,6 @@ blsjs().then((blsjs) => { const modules = [ 'AugSchemeMPL', 'BasicSchemeMPL', - "Bignum", 'G1Element', 'G2Element', 'PopSchemeMPL', @@ -42,7 +41,6 @@ blsjs().then((blsjs) => { const { AugSchemeMPL, BasicSchemeMPL, - Bignum, G1Element, G2Element, PopSchemeMPL, @@ -380,17 +378,11 @@ blsjs().then((blsjs) => { assert(AugSchemeMPL.aggregateVerify([], [], new G2Element())); } - function testBignum() { - const mersenne = Bignum.fromString('162259276829213363391578010288127', 10); - assert(mersenne.toString(16).toLowerCase() == '7ffffffffffffffffffffffffff'); - } - testSchemes(); testVectorsInvalid(); testVectorsValid(); testReadme(); testAggregateVerifyZeroItems(); - testBignum(); }).then(function() { console.log("\nAll tests passed."); }); diff --git a/src/dashbls/js-bindings/wrappers/BignumWrapper.cpp b/src/dashbls/js-bindings/wrappers/BignumWrapper.cpp deleted file mode 100644 index 26fea069a0ff..000000000000 --- a/src/dashbls/js-bindings/wrappers/BignumWrapper.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2020 Chia Network Inc - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 - -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include "BignumWrapper.h" - -namespace js_wrappers { -Bignum::Bignum() { - bn_make(&content, 1); -} - -Bignum::~Bignum() { - bn_clean(&content); -} - -Bignum::Bignum(const Bignum &other) { - bn_copy(&content, &other.content); -} - -bn_st *Bignum::operator &() { return &content; } - -BignumWrapper::BignumWrapper(const Bignum &bn) : JSWrapper(bn) {} - -BignumWrapper BignumWrapper::FromString(const std::string &s, int radix) { - Bignum result; - bn_read_str(&result, s.c_str(), s.size(), radix); - return BignumWrapper(result); -} - -std::string BignumWrapper::ToString(int radix) { - auto wrapper = GetWrappedInstance(); - int strsize = bn_size_str(&wrapper, radix); - std::vector strholder(strsize); - bn_write_str(&strholder[0], strsize, &wrapper, radix); - return std::string(&strholder[0], strsize - 1); -} -} // namespace js_wrappers diff --git a/src/dashbls/js-bindings/wrappers/BignumWrapper.h b/src/dashbls/js-bindings/wrappers/BignumWrapper.h deleted file mode 100644 index 337d52702506..000000000000 --- a/src/dashbls/js-bindings/wrappers/BignumWrapper.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Chia Network Inc - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 - -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef JS_BINDINGS_WRAPPERS_BIGNUMWRAPPER_H_ -#define JS_BINDINGS_WRAPPERS_BIGNUMWRAPPER_H_ - -#include -#include "JSWrapper.h" - -namespace js_wrappers { -class Bignum { -public: - Bignum(); - ~Bignum(); - Bignum(const Bignum &other); - - bn_st *operator &(); - -private: - bn_st content; -}; - -class BignumWrapper : public JSWrapper { -public: - explicit BignumWrapper(const Bignum &bn); - static BignumWrapper FromString(const std::string &s, int radix); - std::string ToString(int radix); -}; -} // namespace js_wrappers - -#endif // JS_BINDINGS_WRAPPERS_SIGNATUREWRAPPER_H_ diff --git a/src/dashbls/js-bindings/wrappers/G1ElementWrapper.cpp b/src/dashbls/js-bindings/wrappers/G1ElementWrapper.cpp index 0d630514886b..f623a5062173 100644 --- a/src/dashbls/js-bindings/wrappers/G1ElementWrapper.cpp +++ b/src/dashbls/js-bindings/wrappers/G1ElementWrapper.cpp @@ -44,16 +44,6 @@ G1ElementWrapper G1ElementWrapper::Add(const G1ElementWrapper &other) { return G1ElementWrapper(GetWrappedInstance() + other.GetWrappedInstance()); } -G1ElementWrapper G1ElementWrapper::Mul(const BignumWrapper &other) { - bn_t factor; - // Since the type of bn_t is bn_st[0], we can do this dance to make a temporary - // copy of the struct itself to hand to G1ElementWrapper's multiply. The - // type was clearly intended to by by-value in argument lists (degrade to ptr) - // but value semantics in C++ complicates matters. - factor[0] = *(&other.GetWrappedInstance()); - return G1ElementWrapper(GetWrappedInstance() * factor); -} - bool G1ElementWrapper::EqualTo(const G1ElementWrapper &others) { return GetWrappedInstance() == others.GetWrappedInstance(); } diff --git a/src/dashbls/js-bindings/wrappers/G1ElementWrapper.h b/src/dashbls/js-bindings/wrappers/G1ElementWrapper.h index 1b5a0f8282a7..e7185c5237a9 100644 --- a/src/dashbls/js-bindings/wrappers/G1ElementWrapper.h +++ b/src/dashbls/js-bindings/wrappers/G1ElementWrapper.h @@ -17,7 +17,6 @@ #include #include "JSWrapper.h" -#include "BignumWrapper.h" namespace js_wrappers { class G1ElementWrapper : public JSWrapper { @@ -38,8 +37,6 @@ class G1ElementWrapper : public JSWrapper { G1ElementWrapper Add(const G1ElementWrapper &other); - G1ElementWrapper Mul(const BignumWrapper &other); - bool EqualTo(const G1ElementWrapper &others); G1ElementWrapper Negate(); diff --git a/src/dashbls/js-bindings/wrappers/G2ElementWrapper.cpp b/src/dashbls/js-bindings/wrappers/G2ElementWrapper.cpp index 980a7dd8e706..de4a208f5b96 100644 --- a/src/dashbls/js-bindings/wrappers/G2ElementWrapper.cpp +++ b/src/dashbls/js-bindings/wrappers/G2ElementWrapper.cpp @@ -67,16 +67,6 @@ G2ElementWrapper G2ElementWrapper::Add(const G2ElementWrapper& other) { return G2ElementWrapper(GetWrappedInstance() + other.GetWrappedInstance()); } -G2ElementWrapper G2ElementWrapper::Mul(const BignumWrapper& other) { - bn_t factor; - // Since the type of bn_t is bn_st[0], we can do this dance to make a - // temporary copy of the struct itself to hand to G2ElementWrapper's - // multiply. The type was clearly intended to by by-value in argument lists - // (degrade to ptr) but value semantics in C++ complicates matters. - factor[0] = *(&other.GetWrappedInstance()); - return G2ElementWrapper(GetWrappedInstance() * factor); -} - bool G2ElementWrapper::EqualTo(const G2ElementWrapper& others) { return GetWrappedInstance() == others.GetWrappedInstance(); } diff --git a/src/dashbls/js-bindings/wrappers/G2ElementWrapper.h b/src/dashbls/js-bindings/wrappers/G2ElementWrapper.h index 46f23f6ca826..829affd2ab79 100644 --- a/src/dashbls/js-bindings/wrappers/G2ElementWrapper.h +++ b/src/dashbls/js-bindings/wrappers/G2ElementWrapper.h @@ -17,7 +17,6 @@ #include #include "JSWrapper.h" -#include "BignumWrapper.h" namespace js_wrappers { class G2ElementWrapper : public JSWrapper { @@ -46,8 +45,6 @@ class G2ElementWrapper : public JSWrapper { G2ElementWrapper Add(const G2ElementWrapper &other); - G2ElementWrapper Mul(const BignumWrapper &other); - bool EqualTo(const G2ElementWrapper &others); }; } // namespace js_wrappers diff --git a/src/dashbls/pyproject.toml b/src/dashbls/pyproject.toml index c9b5e5526393..a427ccb8e03e 100644 --- a/src/dashbls/pyproject.toml +++ b/src/dashbls/pyproject.toml @@ -47,13 +47,9 @@ test-requires = [ ] [tool.cibuildwheel.linux] -before-all = "dnf -y install gmp-devel" manylinux-aarch64-image = "manylinux_2_28" manylinux-x86_64-image = "manylinux_2_28" -[tool.cibuildwheel.macos] -environment = { CMAKE_ARGS = "-DARITH=easy" } - [tool.pytest.ini_options] testpaths = ["binds/python"] addopts = "--benchmark-skip" diff --git a/src/dashbls/rust-bindings/bls-dash-sys/build.rs b/src/dashbls/rust-bindings/bls-dash-sys/build.rs index 0570baaa89b0..c514df3125a6 100644 --- a/src/dashbls/rust-bindings/bls-dash-sys/build.rs +++ b/src/dashbls/rust-bindings/bls-dash-sys/build.rs @@ -138,13 +138,9 @@ fn main() { .collect(); include_paths.extend([ - bls_dash_build_path.join("depends/relic-src/include"), - bls_dash_build_path.join("depends/relic/include"), bls_dash_build_path.join("src"), root_path.join("include/dashbls"), - bls_dash_build_path.join("depends/relic/include"), bls_dash_build_path.join("depends/mimalloc/include"), - root_path.join("depends/relic/include"), root_path.join("depends/mimalloc/include"), bls_dash_src_path.clone(), ]); @@ -186,21 +182,6 @@ fn main() { cc.compile("bls-dash-sys"); - // // Link dependencies - // println!( - // "cargo:rustc-link-search={}", - // bls_dash_build_path.join("_deps/sodium-build").display() - // ); - - // println!("cargo:rustc-link-lib=static=sodium"); - - println!( - "cargo:rustc-link-search={}", - root_path.join("build/depends/relic/lib").display() - ); - - println!("cargo:rustc-link-lib=static=relic_s"); - let mimalloc_dir = root_path.join("build/depends/mimalloc"); println!("cargo:rustc-link-search={}", mimalloc_dir.display()); let mimalloc_lib = if mimalloc_dir.join("libmimalloc-secure-debug.a").exists() { @@ -217,26 +198,6 @@ fn main() { println!("cargo:rustc-link-lib=static=dashbls"); - // Link GMP if exists - let gmp_libraries_file_path = bls_dash_build_path.join("gmp_libraries.txt"); - - if gmp_libraries_file_path.exists() { - let gmp_libraries_path = PathBuf::from( - fs::read_to_string(gmp_libraries_file_path) - .expect("should read gmp includes from file"), - ); - - let gmp_libraries_parent_path = gmp_libraries_path - .parent() - .expect("can't get gmp libraries parent dir"); - - println!( - "cargo:rustc-link-search={}", - gmp_libraries_parent_path.display() - ); - - println!("cargo:rustc-link-lib=static=gmp"); - } println!("cargo:warning=########## bls_dash_build_path:{}", bls_dash_build_path.display()); // Generate rust code for c binding to src/lib.rs @@ -312,7 +273,6 @@ fn main() { // } // println!("cargo:rustc-link-search={}", target_path.display()); // println!("cargo:rustc-link-lib=static=gmp"); -// println!("cargo:rustc-link-lib=static=sodium"); // println!("cargo:rustc-link-lib=static=relic_s"); // println!("cargo:rustc-link-search={}", bls_dash_build_path.join("src").display()); // println!("cargo:rustc-link-lib=static=bls"); @@ -404,12 +364,8 @@ fn main() { .collect(); include_paths.extend([ - bls_dash_build_path.join(format!("relic-{}-{}/depends/relic-src/include", platform, arch)), - bls_dash_build_path.join(format!("relic-{}-{}/depends/relic/include", platform, arch)), - bls_dash_build_path.join("contrib/relic/src"), root_path.join("src"), root_path.join("include/dashbls"), - root_path.join("depends/relic/include"), root_path.join("depends/mimalloc/include"), root_path.join("depends/catch2/include"), bls_dash_src_path.clone(), @@ -430,16 +386,10 @@ fn main() { .flag("-Wno-delete-non-abstract-non-virtual-dtor") .flag("-std=c++14"); - cc.compile("dashbls"); + cc.compile("bls-dash-sys"); println!("cargo:rustc-link-search={}", target_path.display()); - println!("cargo:rustc-link-lib=static=gmp"); - //println!("cargo:rustc-link-lib=c++"); - //println!("cargo:rustc-link-lib=c"); - //println!("cargo:rustc-link-lib=static=sodium"); - println!("cargo:rustc-link-lib=static=relic_s"); - println!("cargo:rustc-link-lib=static=bls"); - println!("cargo:rustc-link-search={}", bls_dash_src_path.display()); + println!("cargo:rustc-link-lib=static=mimalloc-secure"); println!("cargo:rustc-link-lib=static=dashbls"); println!("cargo:rerun-if-changed={}", bls_dash_src_path.display()); } diff --git a/src/dashbls/rust-bindings/bls-dash-sys/c-bindings/schemes.cpp b/src/dashbls/rust-bindings/bls-dash-sys/c-bindings/schemes.cpp index bc2e632c8027..96c0d2fa4432 100644 --- a/src/dashbls/rust-bindings/bls-dash-sys/c-bindings/schemes.cpp +++ b/src/dashbls/rust-bindings/bls-dash-sys/c-bindings/schemes.cpp @@ -324,8 +324,13 @@ G2Element LegacySchemeMPLSign( { bls::LegacySchemeMPL* schemePtr = (bls::LegacySchemeMPL*)scheme; const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk; - return new bls::G2Element( - schemePtr->Sign(*skPtr, bls::Bytes((uint8_t*)msg, msgLen))); + try { + return new bls::G2Element( + schemePtr->Sign(*skPtr, bls::Bytes((uint8_t*)msg, msgLen))); + } catch (const std::exception& ex) { + gErrMsg = ex.what(); + return nullptr; + } } bool LegacySchemeMPLVerify( diff --git a/src/dashbls/rust-bindings/bls-signatures/src/schemes.rs b/src/dashbls/rust-bindings/bls-signatures/src/schemes.rs index 3019bc0b4aa6..1755bc3549e6 100644 --- a/src/dashbls/rust-bindings/bls-signatures/src/schemes.rs +++ b/src/dashbls/rust-bindings/bls-signatures/src/schemes.rs @@ -1,9 +1,9 @@ -use std::ffi::c_void; +use std::ffi::{c_void, CStr}; use bls_dash_sys::{ AugSchemeMPLAggregateVerify, AugSchemeMPLFree, AugSchemeMPLSign, AugSchemeMPLVerify, BasicSchemeMPLAggregateVerify, BasicSchemeMPLFree, CoreMPLAggregatePubKeys, - CoreMPLAggregateSigs, CoreMPLSign, CoreMPLVerify, CoreMPLVerifySecure, + CoreMPLAggregateSigs, CoreMPLSign, CoreMPLVerify, CoreMPLVerifySecure, GetLastErrorMsg, LegacySchemeMPLAggregateVerify, LegacySchemeMPLSign, LegacySchemeMPLVerify, LegacySchemeMPLVerifySecure, NewAugSchemeMPL, NewBasicSchemeMPL, NewLegacySchemeMPL, }; @@ -198,16 +198,23 @@ impl Scheme for LegacySchemeMPL { } fn sign(&self, private_key: &PrivateKey, message: &[u8]) -> G2Element { - G2Element { - c_element: unsafe { - LegacySchemeMPLSign( - self.scheme, - private_key.as_mut_ptr(), - message.as_ptr() as *const _, - message.len(), - ) - }, + // The legacy scheme signs 32-byte message hashes; the C++ side throws + // for anything else, and a C++ exception must not cross the FFI. + assert_eq!(message.len(), 32, "the legacy scheme signs a 32-byte message hash"); + let c_element = unsafe { + LegacySchemeMPLSign( + self.scheme, + private_key.as_mut_ptr(), + message.as_ptr() as *const _, + message.len(), + ) + }; + // The C shim returns null when the C++ side threw. + if c_element.is_null() { + let msg = unsafe { CStr::from_ptr(GetLastErrorMsg()) }; + panic!("LegacySchemeMPLSign failed: {}", msg.to_string_lossy()); } + G2Element { c_element } } fn verify(&self, public_key: &G1Element, message: &[u8], signature: &G2Element) -> bool { @@ -383,10 +390,11 @@ mod tests { .g1_element() .expect("unable to get public key"); - let message_1 = b"ayya"; - let message_2 = b"ayyb"; - let message_3 = b"ayyc"; - let message_4 = b"ayyd"; + // 32-byte messages: the legacy scheme only signs message hashes + let message_1 = &[0x11u8; 32]; + let message_2 = &[0x22u8; 32]; + let message_3 = &[0x33u8; 32]; + let message_4 = &[0x44u8; 32]; let signature_1 = scheme.sign(&private_key_1, message_1); let signature_2 = scheme.sign(&private_key_2, message_2); @@ -431,4 +439,42 @@ mod tests { fn verify_aggregate_legacy() { verify_aggregate(LegacySchemeMPL::new()); } + + fn legacy_key_and_signature() -> (LegacySchemeMPL, G1Element, G2Element) { + let scheme = LegacySchemeMPL::new(); + let private_key = PrivateKey::key_gen(&scheme, b"seedweedseedweedseedweedseedweed") + .expect("unable to generate private key"); + let public_key = private_key.g1_element().expect("unable to get public key"); + let signature = scheme.sign(&private_key, &[0x11u8; 32]); + (scheme, public_key, signature) + } + + #[test] + #[should_panic(expected = "32-byte message hash")] + fn legacy_sign_rejects_short_message() { + let scheme = LegacySchemeMPL::new(); + let private_key = PrivateKey::key_gen(&scheme, b"seedweedseedweedseedweedseedweed") + .expect("unable to generate private key"); + scheme.sign(&private_key, &[0x11u8; 31]); + } + + #[test] + #[should_panic(expected = "32-byte message hash")] + fn legacy_sign_rejects_long_message() { + let scheme = LegacySchemeMPL::new(); + let private_key = PrivateKey::key_gen(&scheme, b"seedweedseedweedseedweedseedweed") + .expect("unable to generate private key"); + scheme.sign(&private_key, &[0x11u8; 33]); + } + + #[test] + fn legacy_verify_rejects_wrong_message_length() { + let (scheme, public_key, signature) = legacy_key_and_signature(); + assert!(scheme.verify(&public_key, &[0x11u8; 32], &signature)); + for message in [&[0x11u8; 31][..], &[0x11u8; 33][..]] { + assert!(!scheme.verify(&public_key, message, &signature)); + assert!(!scheme.verify_secure([&public_key], message, &signature)); + assert!(!scheme.aggregate_verify([&public_key], [message], &signature)); + } + } } diff --git a/src/dashbls/setup.py b/src/dashbls/setup.py index cb8f9b6b8a56..6b748cfe5bdc 100644 --- a/src/dashbls/setup.py +++ b/src/dashbls/setup.py @@ -73,7 +73,6 @@ def build_extension(self, ext: CMakeExtension) -> None: "-DBUILD_BLS_BENCHMARKS=OFF", "-DBUILD_BLS_TESTS=OFF", "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=" + extdir, - "-DMULTI=", "-DPYBIND11_FINDPYTHON=ON", "-DPython_EXECUTABLE=" + sys.executable, "-DVERSION_INFO=" + self.distribution.get_version(), diff --git a/src/dashbls/src/CMakeLists.txt b/src/dashbls/src/CMakeLists.txt index 5802843a61ed..02eb9ae8f917 100644 --- a/src/dashbls/src/CMakeLists.txt +++ b/src/dashbls/src/CMakeLists.txt @@ -1,41 +1,63 @@ -file(GLOB HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/dashbls/*.hpp) +file(GLOB HEADERS ${PROJECT_SOURCE_DIR}/include/dashbls/*.hpp) source_group("SrcHeaders" FILES ${HEADERS}) -add_library(dashbls +list(APPEND bls_sources ${HEADERS} - ${CMAKE_CURRENT_SOURCE_DIR}/privatekey.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/bls.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/chaincode.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/elements.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/extendedprivatekey.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/extendedpublickey.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/legacy.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/schemes.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/threshold.cpp) - -target_include_directories(dashbls - PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR} - $<$:${GMP_INCLUDES}> - ${CMAKE_CURRENT_SOURCE_DIR}/../include/dashbls - ${CMAKE_CURRENT_SOURCE_DIR}/../depends/mimalloc/include - ${CMAKE_CURRENT_SOURCE_DIR}/../depends/relic/include - ${CMAKE_CURRENT_BINARY_DIR}/../depends/relic/include + privatekey.cpp + bls.cpp + chaincode.cpp + elements.cpp + extendedprivatekey.cpp + extendedpublickey.cpp + legacy.cpp + schemes.cpp + threshold.cpp + ${blst_SOURCE_DIR}/src/server.c ) -target_compile_definitions(dashbls - PRIVATE - BLSALLOC_MIMALLOC=1 -) +if(MSVC) + list(APPEND bls_sources + ${blst_SOURCE_DIR}/build/win64/add_mod_256-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/add_mod_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/add_mod_384x384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/ct_inverse_mod_256-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/ct_is_square_mod_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/ctq_inverse_mod_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/ctx_inverse_mod_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/div3w-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/mulq_mont_256-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/mulq_mont_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/mulx_mont_256-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/mulx_mont_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/sha256-x86_64.asm + ) +else() + list(APPEND bls_sources + ${blst_SOURCE_DIR}/build/assembly.S + ) + set_source_files_properties(${blst_SOURCE_DIR}/src/server.c PROPERTIES COMPILE_OPTIONS -fno-builtin) + add_compile_options(-fPIC) + add_compile_options(-Wall) + add_compile_options(-Wextra) + if((CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") AND (NOT EMSCRIPTEN)) + add_compile_options(-mno-avx) + endif() +endif() +add_library(dashbls ${bls_sources}) +target_include_directories(dashbls PUBLIC ${blst_SOURCE_DIR}/bindings ${PROJECT_SOURCE_DIR}/include/dashbls/) +target_compile_definitions(dashbls PRIVATE __BLST_PORTABLE__ BLSALLOC_MIMALLOC=1) +if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64|AMD64|aarch64|arm64|ARM64") + # blst ships assembly for x86_64 and aarch64 only; other 64-bit targets + # (riscv64, powerpc64, ...) build its portable C code instead. + target_compile_definitions(dashbls PRIVATE __BLST_NO_ASM__) +endif() target_link_libraries(dashbls PUBLIC - relic_s mimalloc-static ) -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../depends/relic/include/ DESTINATION include/dashbls) -install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../depends/relic/include/ DESTINATION include/dashbls) +install(FILES ${blst_SOURCE_DIR}/bindings/blst.h ${blst_SOURCE_DIR}/bindings/blst_aux.h DESTINATION include/dashbls) install(FILES ${HEADERS} DESTINATION include/dashbls) install(FILES $ DESTINATION lib) @@ -43,9 +65,13 @@ if(BUILD_BLS_TESTS) include(${CMAKE_CURRENT_SOURCE_DIR}/../depends/catch2/CMakeLists.txt) add_executable(runtest test.cpp) + if(EMSCRIPTEN) + target_link_options(runtest PRIVATE "-sEXPORTED_FUNCTIONS=_malloc") + endif() target_link_libraries(runtest - PRIVATE dashbls - PRIVATE catch2) + PRIVATE + dashbls + catch2) if(EMSCRIPTEN) target_link_options(runtest PRIVATE "SHELL:-s MALLOC=emmalloc") @@ -66,3 +92,19 @@ if(BUILD_BLS_BENCHMARKS) endif() endif() endif() + +if(BUILD_BLS_TESTS) + # runtest compares the library against test-vectors/reference.txt; + # vectorgen regenerates that file from whichever library it is built against. + target_compile_definitions(runtest PRIVATE + DASHBLS_REFERENCE_VECTORS="${CMAKE_CURRENT_SOURCE_DIR}/../test-vectors/reference.txt") + + add_executable(vectorgen ${CMAKE_CURRENT_SOURCE_DIR}/../tools/vectorgen.cpp) + target_include_directories(vectorgen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(vectorgen PRIVATE dashbls) + + if(EMSCRIPTEN) + # mimalloc's Emscripten backend is built on emmalloc + target_link_options(vectorgen PRIVATE "SHELL:-s MALLOC=emmalloc") + endif() +endif() diff --git a/src/dashbls/src/bls.cpp b/src/dashbls/src/bls.cpp index e0af3a388216..19cce171f82e 100644 --- a/src/dashbls/src/bls.cpp +++ b/src/dashbls/src/bls.cpp @@ -18,10 +18,6 @@ #include "mimalloc.h" #endif -#if BLSALLOC_SODIUM -#include "sodium.h" -#endif - namespace bls { const size_t BLS::MESSAGE_HASH_LEN; @@ -31,41 +27,14 @@ bool BLSInitResult = BLS::Init(); Util::SecureAllocCallback Util::secureAllocCallback; Util::SecureFreeCallback Util::secureFreeCallback; -static void relic_core_initializer(void* ptr) -{ - core_init(); - if (err_get_code() != RLC_OK) { - throw std::runtime_error("core_init() failed"); - } - - const int r = ep_param_set_any_pairf(); - if (r != RLC_OK) { - throw std::runtime_error("ep_param_set_any_pairf() failed"); - } -} - bool BLS::Init() { - if (ALLOC != AUTO) { - throw std::runtime_error("Must have ALLOC == AUTO"); - } #if BLSALLOC_MIMALLOC SetSecureAllocator(mi_malloc, mi_free); -#elif BLSALLOC_SODIUM - if (sodium_init() < 0) { - throw std::runtime_error("libsodium init failed"); - } - SetSecureAllocator(sodium_malloc, sodium_free); #else SetSecureAllocator(malloc, free); #endif -#if MULTI != RELIC_NONE - core_set_thread_initializer(relic_core_initializer, nullptr); -#else - relic_core_initializer(nullptr); -#endif - return true; } @@ -77,18 +46,4 @@ void BLS::SetSecureAllocator( Util::secureFreeCallback = freeCb; } - -void BLS::CheckRelicErrors(bool should_throw) -{ - if (!core_get()) { - throw std::runtime_error("Library not initialized properly. Call BLS::Init()"); - } - if (core_get()->code != RLC_OK) { - core_get()->code = RLC_OK; - if (should_throw) { - throw std::invalid_argument("Relic library error"); - } - } -} - } // end namespace bls diff --git a/src/dashbls/src/bn_helpers.hpp b/src/dashbls/src/bn_helpers.hpp deleted file mode 100644 index 05175437ebee..000000000000 --- a/src/dashbls/src/bn_helpers.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2026 The Dash Core developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef SRC_BN_HELPERS_HPP_ -#define SRC_BN_HELPERS_HPP_ - -#include "relic_conf.h" - -extern "C" { -#include "relic.h" -} - -#include - -namespace bls { - -// RAII wrapper for dynamically allocated bn_t arrays. -// Ensures bn_free + delete[] runs even when exceptions are thrown. -// Tracks initialization count so partial construction cleans up correctly. -struct BnArrayGuard { - bn_t* data; - size_t count; - size_t initialized{0}; - - explicit BnArrayGuard(size_t n) : data(new bn_t[n]), count(n) { - for (size_t i = 0; i < count; i++) { - bn_new(data[i]); - initialized++; - } - } - - ~BnArrayGuard() { - for (size_t i = 0; i < initialized; i++) { - bn_free(data[i]); - } - delete[] data; - } - - bn_t& operator[](size_t i) { return data[i]; } - const bn_t& operator[](size_t i) const { return data[i]; } - - BnArrayGuard(const BnArrayGuard&) = delete; - BnArrayGuard& operator=(const BnArrayGuard&) = delete; -}; - -// RAII wrapper for a single bn_t value. -struct BnGuard { - bn_t val; - - BnGuard() { bn_new(val); } - ~BnGuard() { bn_free(val); } - - operator bn_t&() { return val; } - - BnGuard(const BnGuard&) = delete; - BnGuard& operator=(const BnGuard&) = delete; -}; - -} // namespace bls - -#endif // SRC_BN_HELPERS_HPP_ diff --git a/src/dashbls/src/chaincode.cpp b/src/dashbls/src/chaincode.cpp index efacdc95ae29..e5a7204703f9 100644 --- a/src/dashbls/src/chaincode.cpp +++ b/src/dashbls/src/chaincode.cpp @@ -14,6 +14,8 @@ #include "bls.hpp" +#include + namespace bls { ChainCode ChainCode::FromBytes(const Bytes& bytes) { @@ -21,21 +23,15 @@ ChainCode ChainCode::FromBytes(const Bytes& bytes) { throw std::invalid_argument("ChainCode::FromBytes: Invalid size"); } ChainCode c = ChainCode(); - bn_new(c.chainCode); - bn_read_bin(c.chainCode, bytes.begin(), ChainCode::SIZE); + memcpy(c.chainCode.data(), bytes.begin(), ChainCode::SIZE); return c; } -ChainCode::ChainCode(const ChainCode &cc) { - uint8_t bytes[ChainCode::SIZE]; - cc.Serialize(bytes); - bn_new(chainCode); - bn_read_bin(chainCode, bytes, ChainCode::SIZE); -} +ChainCode::ChainCode(const ChainCode &cc) : chainCode(cc.chainCode) {} // Comparator implementation. bool operator==(ChainCode const &a, ChainCode const &b) { - return bn_cmp(a.chainCode, b.chainCode) == RLC_EQ; + return a.chainCode == b.chainCode; } bool operator!=(ChainCode const &a, ChainCode const &b) { @@ -49,7 +45,7 @@ std::ostream &operator<<(std::ostream &os, ChainCode const &s) { } void ChainCode::Serialize(uint8_t *buffer) const { - bn_write_bin(buffer, ChainCode::SIZE, chainCode); + memcpy(buffer, chainCode.data(), SIZE); } std::vector ChainCode::Serialize() const { diff --git a/src/dashbls/src/elements.cpp b/src/dashbls/src/elements.cpp index b0c747af823c..3f77b4d54ddf 100644 --- a/src/dashbls/src/elements.cpp +++ b/src/dashbls/src/elements.cpp @@ -12,16 +12,194 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include #include "bls.hpp" #include "legacy.hpp" +namespace { +// The legacy codec reproduces the byte-level behavior of the relic-based +// implementation exactly, including its handling of malformed input. relic +// was built without CHECK, so its internal errors did not throw: an +// out-of-range field element left the coordinate at zero, and a failed +// square root left y holding its pre-existing raw contents (0, or a raw +// limb 1 when the sign bit had been stored). All of it is consensus-visible +// through re-serialization and is pinned by test-vectors/reference.txt. + +// BLS12-381 base field prime p, big-endian. +static const uint8_t P_BE[48] = { + 0x1a, 0x01, 0x11, 0xea, 0x39, 0x7f, 0xe6, 0x9a, 0x4b, 0x1b, 0xa7, 0xb6, + 0x43, 0x4b, 0xac, 0xd7, 0x64, 0x77, 0x4b, 0x84, 0xf3, 0x85, 0x12, 0xbf, + 0x67, 0x30, 0xd2, 0xa0, 0xf6, 0xb0, 0xf6, 0x24, 0x1e, 0xab, 0xff, 0xfe, + 0xb1, 0x53, 0xff, 0xff, 0xb9, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xab}; + +// (p - 1) / 2, big-endian. The legacy sign convention is y > (p-1)/2 +// ("larger" root), matching relic's ep_pck/ep2_pck for pairing-friendly +// curves. +static const uint8_t HALF_P_BE[48] = { + 0x0d, 0x00, 0x88, 0xf5, 0x1c, 0xbf, 0xf3, 0x4d, 0x25, 0x8d, 0xd3, 0xdb, + 0x21, 0xa5, 0xd6, 0x6b, 0xb2, 0x3b, 0xa5, 0xc2, 0x79, 0xc2, 0x89, 0x5f, + 0xb3, 0x98, 0x69, 0x50, 0x7b, 0x58, 0x7b, 0x12, 0x0f, 0x55, 0xff, 0xff, + 0x58, 0xa9, 0xff, 0xff, 0xdc, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xd5, 0x55}; + +// (2^384)^-1 mod p, big-endian. When relic (built without CHECK) failed to +// find a square root during legacy point decompression with the sign bit +// set, the y coordinate was left holding a raw limb value of 1, which reads +// back from Montgomery form as this constant. Preserved bit-for-bit for +// compatibility with historical consensus data. +static const uint8_t MONT_R_INV_BE[48] = { + 0x14, 0xfe, 0xc7, 0x01, 0xe8, 0xfb, 0x0c, 0xe9, 0xed, 0x5e, 0x64, 0x27, + 0x3c, 0x4f, 0x53, 0x8b, 0x17, 0x97, 0xab, 0x14, 0x58, 0xa8, 0x8d, 0xe9, + 0x34, 0x3e, 0xa9, 0x79, 0x14, 0x95, 0x6d, 0xc8, 0x7f, 0xe1, 0x12, 0x74, + 0xd8, 0x98, 0xfa, 0xfb, 0xf4, 0xd3, 0x82, 0x59, 0x38, 0x0b, 0x48, 0x20}; + +inline void FpFromBE48(blst_fp& out, const uint8_t* be) +{ + blst_fp_from_bendian(&out, be); +} + +// Compares a big-endian 48-byte value against a constant. Returns the +// memcmp sign. +inline int CmpBE48(const uint8_t* a, const uint8_t* b) +{ + return memcmp(a, b, 48); +} + +inline void FpZero(blst_fp& out) { memset(&out, 0x00, sizeof(blst_fp)); } + +inline void FpOneConst(blst_fp& out) +{ + uint8_t be[48] = {0}; + be[47] = 1; + blst_fp_from_bendian(&out, be); +} + +// relic's ep2_upk sign rule (decompression side, with the IETF tie-break): +// sign = c1 > (p-1)/2, but when c1 == 0 the sign of c0 is used instead. +// Note the serialization side (ep2_pck) uses c1 only, with no tie-break. +inline bool Fp2SignUpk(const blst_fp2& y) +{ + uint8_t be[48]; + blst_bendian_from_fp(be, &y.fp[1]); + bool c1Zero = true; + for (int i = 0; i < 48; i++) + if (be[i] != 0) { c1Zero = false; break; } + if (!c1Zero) return CmpBE48(be, HALF_P_BE) > 0; + blst_bendian_from_fp(be, &y.fp[0]); + return CmpBE48(be, HALF_P_BE) > 0; +} + +// The "larger root" test used by both the legacy codec (relic's +// ep_pck/ep2_pck convention) and the legacy hash-to-curve: y > (p-1)/2 on +// the canonical representation. +inline bool FpSignGtHalf(const blst_fp& a) +{ + uint8_t be[48]; + blst_bendian_from_fp(be, &a); + return CmpBE48(be, HALF_P_BE) > 0; +} +} // anon namespace + namespace bls { +static void LegacyDecodeG1( + blst_p1_affine& a, + const uint8_t* bytes, + const bool signBit) +{ + uint8_t xbytes[G1Element::SIZE]; + memcpy(xbytes, bytes, G1Element::SIZE); + // the relic-based G1 codec erased the top three bits of the first byte + // unconditionally, before the sign bit was even examined (unlike G2, + // which only clears the sign bit) + xbytes[0] &= 0x1f; + + if (CmpBE48(xbytes, P_BE) >= 0) { + // relic's fp_read_bin error path: coordinate left untouched (zero) + FpZero(a.x); + } else { + FpFromBE48(a.x, xbytes); + } + + // rhs = x^3 + 4 + blst_fp rhs; + blst_fp_sqr(&rhs, &a.x); + blst_fp_mul(&rhs, &rhs, &a.x); + blst_fp four; + uint8_t fourBytes[48] = {0}; + fourBytes[47] = 4; + FpFromBE48(four, fourBytes); + blst_fp_add(&rhs, &rhs, &four); + + if (blst_fp_sqrt(&a.y, &rhs)) { + if (FpSignGtHalf(a.y) != signBit) { + blst_fp_cneg(&a.y, &a.y, true); + } + } else { + // relic's ep_upk failure: y keeps the raw sign-bit marker + if (signBit) { + FpFromBE48(a.y, MONT_R_INV_BE); + } else { + FpZero(a.y); + } + } +} + +static void LegacyDecodeG2( + blst_p2_affine& a, + const uint8_t* bytes, + const bool signBit) +{ + uint8_t c0[48], c1[48]; + memcpy(c0, bytes, 48); + memcpy(c1, bytes + 48, 48); + if (signBit) { + c0[0] &= 0x7f; + } + + if (CmpBE48(c0, P_BE) >= 0) { + FpZero(a.x.fp[0]); + } else { + FpFromBE48(a.x.fp[0], c0); + } + if (CmpBE48(c1, P_BE) >= 0) { + FpZero(a.x.fp[1]); + } else { + FpFromBE48(a.x.fp[1], c1); + } + + // rhs = x^3 + (4, 4) + blst_fp2 rhs; + blst_fp2_sqr(&rhs, &a.x); + blst_fp2_mul(&rhs, &rhs, &a.x); + blst_fp four; + uint8_t fourBytes[48] = {0}; + fourBytes[47] = 4; + FpFromBE48(four, fourBytes); + blst_fp2 b2; + b2.fp[0] = four; + b2.fp[1] = four; + blst_fp2_add(&rhs, &rhs, &b2); + + if (blst_fp2_sqrt(&a.y, &rhs)) { + if (Fp2SignUpk(a.y) != signBit) { + blst_fp2_cneg(&a.y, &a.y, true); + } + } else { + if (signBit) { + FpFromBE48(a.y.fp[0], MONT_R_INV_BE); + } else { + FpZero(a.y.fp[0]); + } + FpZero(a.y.fp[1]); + } +} const size_t G1Element::SIZE; -G1Element G1Element::FromBytes(Bytes const bytes, bool fLegacy) { +G1Element G1Element::FromBytes(Bytes const bytes, bool fLegacy) +{ G1Element ele = G1Element::FromBytesUnchecked(bytes, fLegacy); if (!fLegacy) { ele.CheckValid(); @@ -35,55 +213,46 @@ G1Element G1Element::FromBytesUnchecked(Bytes const bytes, bool fLegacy) throw std::invalid_argument("G1Element::FromBytes: Invalid size"); } - G1Element ele; - - // convert bytes to relic form - uint8_t buffer[G1Element::SIZE + 1]; - std::memcpy(buffer + 1, bytes.begin(), G1Element::SIZE); - buffer[0] = 0x00; - buffer[1] &= 0x1f; // erase 3 msbs from given input - + // check if the element is canonical + const uint8_t* raw_bytes = bytes.begin(); + bool fZerosOnly = (raw_bytes[0] & 0x1f) == 0 && + Util::HasOnlyZeros(Bytes(raw_bytes + 1, bytes.size() - 1)); if ((bytes[0] & 0xc0) == 0xc0) { // representing infinity - buffer[0] = 0x00; - buffer[1] &= 0x1f; // erase 3 msbs from given input - - bool fZerosOnly = Util::HasOnlyZeros(Bytes(buffer, G1Element::SIZE + 1)); // enforce that infinity must be 0xc0000..00 if (bytes[0] != 0xc0 || !fZerosOnly) { - throw std::invalid_argument("Given G1 infinity element must be canonical"); + throw std::invalid_argument( + "Given G1 infinity element must be canonical"); } + return G1Element(); // return infinity element (point all zero) + } + if (fLegacy) { + G1Element ele; + blst_p1_affine a; + LegacyDecodeG1(a, bytes.begin(), (bytes[0] & 0x80) != 0); + // Build the Jacobian point by hand: blst_p1_from_affine maps the + // all-zero affine pair to infinity, but relic kept degenerate + // decodes (e.g. x = 0, y = 0) as ordinary z=1 points, which is + // consensus-visible through re-serialization. + ele.p.x = a.x; + ele.p.y = a.y; + FpOneConst(ele.p.z); return ele; - } else { - if (fLegacy) { - if (bytes[0] & 0x80) { - buffer[0] = 0x03; // Insert extra byte for Y=1 - buffer[1] &= 0x7f; // Remove initial Y bit - } else { - buffer[0] = 0x02; // Insert extra byte for Y=0 - } - } else { - buffer[0] = 0x00; - buffer[1] &= 0x1f; // erase 3 msbs from given input - - bool fZerosOnly = Util::HasOnlyZeros(Bytes(buffer, G1Element::SIZE + 1)); - if ((bytes[0] & 0xc0) != 0x80) { - throw std::invalid_argument( - "Given G1 non-infinity element must start with 0b10"); - } - - if (fZerosOnly) { - throw std::invalid_argument("G1 non-infinity element can't have only zeros"); - } - if (bytes[0] & 0x20) { // sign bit - buffer[0] = 0x03; - } else { - buffer[0] = 0x02; - } - } } - g1_read_bin(ele.p, buffer, G1Element::SIZE + 1); - BLS::CheckRelicErrors(!fLegacy); - return ele; + if ((bytes[0] & 0xc0) != 0x80) { + throw std::invalid_argument( + "Given G1 non-infinity element must start with 0b10"); + } + if (fZerosOnly) { + throw std::invalid_argument( + "G1 non-infinity element can't have only zeros"); + } + + blst_p1_affine a; + BLST_ERROR err = blst_p1_uncompress(&a, bytes.begin()); + if (err != BLST_SUCCESS) + throw std::invalid_argument("G1Element::FromBytes: Invalid bytes"); + + return G1Element::FromAffine(a); } G1Element G1Element::FromByteVector(const std::vector& bytevec, bool fLegacy) @@ -91,35 +260,46 @@ G1Element G1Element::FromByteVector(const std::vector& bytevec, bool fL return G1Element::FromBytes(Bytes(bytevec), fLegacy); } -G1Element G1Element::FromNative(const g1_t element) +G1Element G1Element::FromNative(const blst_p1& element) { G1Element ele; - g1_copy(ele.p, element); + memcpy(&(ele.p), &element, sizeof(blst_p1)); return ele; } -G1Element G1Element::Copy() { +G1Element G1Element::FromAffine(const blst_p1_affine& element) +{ G1Element ele; - g1_copy(ele.p, this->p); - + blst_p1_from_affine(&(ele.p), &element); return ele; } - -G1Element G1Element::FromMessage(const std::vector& message, - const uint8_t* dst, - int dst_len) +G1Element G1Element::FromMessage( + const std::vector& message, + const uint8_t* dst, + size_t dst_len) { return FromMessage(Bytes(message), dst, dst_len); } -G1Element G1Element::FromMessage(Bytes const message, - const uint8_t* dst, - int dst_len) +G1Element G1Element::FromMessage( + Bytes const message, + const uint8_t* dst, + size_t dst_len) { G1Element ans; - ep_map_dst(ans.p, message.begin(), (int)message.size(), dst, dst_len); - BLS::CheckRelicErrors(); + const byte* aug = nullptr; + size_t aug_len = 0; + + blst_hash_to_g1( + &(ans.p), + message.begin(), + message.size(), + dst, + dst_len, + aug, + aug_len); + assert(ans.IsValid()); return ans; } @@ -127,35 +307,46 @@ G1Element G1Element::FromMessage(Bytes const message, G1Element G1Element::Generator() { G1Element ele; - g1_get_gen(ele.p); - BLS::CheckRelicErrors(); + ele.p = *(blst_p1_generator()); return ele; } -bool G1Element::IsValid() const { - // Infinity no longer valid in Relic - // https://github.com/relic-toolkit/relic/commit/f3be2babb955cf9f82743e0ae5ef265d3da6c02b - if (g1_is_infty((g1_st*)p) == 1) +bool G1Element::IsValid() const +{ + // Infinity was considered a valid G1Element in older Relic versions + // on which this library was previously based. + // For historical compatibililty this behavior is maintained. + + if (blst_p1_is_inf(&p)) return true; - return g1_is_valid((g1_st*)p); + // blst_p1_in_g1 assumes a point on the curve; relic's g1_is_valid + // checked both + return blst_p1_on_curve(&p) && blst_p1_in_g1(&p); } -void G1Element::CheckValid() const { +void G1Element::CheckValid() const +{ if (!IsValid()) throw std::invalid_argument("G1 element is invalid"); - BLS::CheckRelicErrors(); } -void G1Element::ToNative(g1_t output) const { - g1_copy(output, p); +void G1Element::ToNative(blst_p1* output) const +{ + memcpy(output, &p, sizeof(blst_p1)); } +void G1Element::ToAffine(blst_p1_affine* output) const +{ + blst_p1_to_affine(output, &p); +} + +G1Element G1Element::Copy() { return *this; } + G1Element G1Element::Negate() const { - G1Element ans; - g1_neg(ans.p, p); - BLS::CheckRelicErrors(); + G1Element ans = G1Element::FromNative(p); + blst_p1_cneg(&(ans.p), true); return ans; } @@ -165,84 +356,83 @@ uint32_t G1Element::GetFingerprint(const bool fLegacy) const { uint8_t buffer[G1Element::SIZE]; uint8_t hash[32]; - memcpy(buffer, Serialize(fLegacy).data(), G1Element::SIZE); + memcpy(buffer, SerializeToArray(fLegacy).data(), G1Element::SIZE); Util::Hash256(hash, buffer, G1Element::SIZE); return Util::FourBytesToInt(hash); } -std::vector G1Element::Serialize(const bool fLegacy) const { - const auto arr = G1Element::SerializeToArray(fLegacy); +std::vector G1Element::Serialize(const bool fLegacy) const +{ + const auto arr = SerializeToArray(fLegacy); return std::vector{arr.begin(), arr.end()}; } -std::array G1Element::SerializeToArray(const bool fLegacy) const { - uint8_t buffer[G1Element::SIZE + 1]; - g1_write_bin(buffer, G1Element::SIZE + 1, p, 1); - +std::array G1Element::SerializeToArray(const bool fLegacy) const +{ std::array result{}; - if (buffer[0] == 0x00) { // infinity - result[0] = 0xc0; + if (!fLegacy) { + blst_p1_compress(result.data(), &p); return result; } - if (buffer[0] == 0x03) { // sign bit set - buffer[1] |= fLegacy ? 0x80 : 0x20; + if (blst_p1_is_inf(&p)) { + result[0] = 0xc0; + return result; } - if (!fLegacy) { - buffer[1] |= 0x80; // indicate compression + blst_p1_affine a; + blst_p1_to_affine(&a, &p); + blst_bendian_from_fp(result.data(), &a.x); + if (FpSignGtHalf(a.y)) { + result[0] |= 0x80; } - - std::copy_n(buffer + 1, G1Element::SIZE, result.begin()); return result; } -bool operator==(const G1Element & a, const G1Element &b) +bool operator==(const G1Element& a, const G1Element& b) { - return g1_cmp(a.p, b.p) == RLC_EQ; + return blst_p1_is_equal(&(a.p), &(b.p)); } -bool operator!=(const G1Element & a, const G1Element & b) { return !(a == b); } +bool operator!=(const G1Element& a, const G1Element& b) { return !(a == b); } -std::ostream& operator<<(std::ostream& os, const G1Element &ele) +std::ostream& operator<<(std::ostream& os, const G1Element& ele) { return os << Util::HexStr(ele.Serialize()); } G1Element& operator+=(G1Element& a, const G1Element& b) { - g1_add(a.p, a.p, b.p); - BLS::CheckRelicErrors(); + blst_p1_add_or_double(&(a.p), &(a.p), &(b.p)); return a; } G1Element operator+(const G1Element& a, const G1Element& b) { G1Element ans; - g1_add(ans.p, a.p, b.p); - BLS::CheckRelicErrors(); + blst_p1_add_or_double(&(ans.p), &(a.p), &(b.p)); return ans; } -G1Element operator*(const G1Element& a, const bn_t& k) +G1Element operator*(const G1Element& a, const blst_scalar& k) { G1Element ans; - g1_mul(ans.p, (g1_st*)a.p, (bn_st*)k); - BLS::CheckRelicErrors(); + byte* bte = Util::SecAlloc(32); + blst_lendian_from_scalar(bte, &k); + blst_p1_mult(&(ans.p), &(a.p), bte, 256); + Util::SecFree(bte); + return ans; } -G1Element operator*(const bn_t& k, const G1Element& a) { return a * k; } - - +G1Element operator*(const blst_scalar& k, const G1Element& a) { return a * k; } // G2Element definitions below - - const size_t G2Element::SIZE; -G2Element G2Element::FromBytes(Bytes const bytes, const bool fLegacy) { +G2Element G2Element::FromBytes(Bytes const bytes, const bool fLegacy) +{ G2Element ele = G2Element::FromBytesUnchecked(bytes, fLegacy); if (!fLegacy) { ele.CheckValid(); @@ -256,59 +446,59 @@ G2Element G2Element::FromBytesUnchecked(Bytes const bytes, const bool fLegacy) throw std::invalid_argument("G2Element::FromBytes: Invalid size"); } - G2Element ele; - uint8_t buffer[G2Element::SIZE + 1]; - if (fLegacy) { - std::memcpy(buffer + 1, bytes.begin(), G2Element::SIZE); - buffer[0] = 0x00; - } else { - std::memcpy(buffer + 1, bytes.begin() + G2Element::SIZE / 2, G2Element::SIZE / 2); - std::memcpy(buffer + 1 + G2Element::SIZE / 2, bytes.begin(), G2Element::SIZE / 2); - buffer[0] = 0x00; - buffer[49] &= 0x1f; // erase 3 msbs from input - if ((bytes[48] & 0xe0) != 0x00) { + // The relic implementation computed its zeros-only check over a + // buffer that still contained the first byte unmasked, so for the + // legacy G2 codec any input with the two top bits set - canonical + // infinity included - was rejected as non-canonical. + if ((bytes[0] & 0xc0) == 0xc0) { throw std::invalid_argument( - "Given G2 element must always have 48th byte start with 0b000"); + "Given G2 infinity element must be canonical"); } + G2Element ele; + blst_p2_affine a; + LegacyDecodeG2(a, bytes.begin(), (bytes[0] & 0x80) != 0); + // See the G1 legacy path: keep degenerate all-zero decodes as + // ordinary z=1 points instead of mapping them to infinity. + ele.q.x = a.x; + ele.q.y = a.y; + FpOneConst(ele.q.z.fp[0]); + FpZero(ele.q.z.fp[1]); + return ele; + } + + if ((bytes[48] & 0xe0) != 0x00) { + throw std::invalid_argument( + "Given G2 element must always have 48th byte start with 0b000"); } - bool fZerosOnly = Util::HasOnlyZeros(Bytes(buffer, G2Element::SIZE + 1)); - if (((bytes[0] & 0xc0) == 0xc0)) { // infinity + + bool fZerosOnly = (bytes[0] & 0x1f) == 0 && + Util::HasOnlyZeros(Bytes(bytes.begin() + 1, bytes.size() - 1)); + if ((bytes[0] & 0xc0) == 0xc0) { // infinity // enforce that infinity must be 0xc0000..00 if (bytes[0] != 0xc0 || !fZerosOnly) { throw std::invalid_argument( "Given G2 infinity element must be canonical"); } - return ele; + return G2Element(); } - if (fLegacy) { - if (bytes[0] & 0x80) { - buffer[0] = 0x03; // Insert extra byte for Y=1 - buffer[1] &= 0x7f; // Remove initial Y bit - } else { - buffer[0] = 0x02; // Insert extra byte for Y=0 - } - } else { - if (((bytes[0] & 0xc0) != 0x80)) { - throw std::invalid_argument( - "G2 non-inf element must have 0th byte start with 0b10"); - } - - if (fZerosOnly) { - throw std::invalid_argument("G2 non-infinity element can't have only zeros"); - } + if ((bytes[0] & 0xc0) != 0x80) { + throw std::invalid_argument( + "G2 non-inf element must have 0th byte start with 0b10"); + } - if (bytes[0] & 0x20) { - buffer[0] = 0x03; - } else { - buffer[0] = 0x02; - } + if (fZerosOnly) { + throw std::invalid_argument( + "G2 non-infinity element can't have only zeros"); } - g2_read_bin(ele.q, buffer, G2Element::SIZE + 1); - BLS::CheckRelicErrors(!fLegacy); - return ele; + blst_p2_affine a; + BLST_ERROR err = blst_p2_uncompress(&a, bytes.begin()); + if (err != BLST_SUCCESS) + throw std::invalid_argument("G2Element::FromBytes: Invalid bytes"); + + return G2Element::FromAffine(a); } G2Element G2Element::FromByteVector(const std::vector& bytevec, bool fLegacy) @@ -316,33 +506,51 @@ G2Element G2Element::FromByteVector(const std::vector& bytevec, bool fL return G2Element::FromBytes(Bytes(bytevec), fLegacy); } -G2Element G2Element::FromNative(const g2_t element) +G2Element G2Element::FromNative(const blst_p2& element) { G2Element ele; - g2_copy(ele.q, (g2_st*)element); + memcpy(&(ele.q), &element, sizeof(blst_p2)); return ele; } -G2Element G2Element::FromMessage(const std::vector& message, - const uint8_t* dst, - int dst_len, - const bool fLegacy) +G2Element G2Element::FromAffine(const blst_p2_affine& element) +{ + G2Element ele; + blst_p2_from_affine(&(ele.q), &element); + return ele; +} + +G2Element G2Element::FromMessage( + const std::vector& message, + const uint8_t* dst, + size_t dst_len, + const bool fLegacy) { return FromMessage(Bytes(message), dst, dst_len, fLegacy); } -G2Element G2Element::FromMessage(Bytes const message, - const uint8_t* dst, - int dst_len, - const bool fLegacy) +G2Element G2Element::FromMessage( + Bytes const message, + const uint8_t* dst, + size_t dst_len, + const bool fLegacy) { G2Element ans; if (fLegacy) { - ep2_map_legacy(ans.q, message.begin(), BLS::MESSAGE_HASH_LEN); + ep2_map_legacy(&(ans.q), message.begin(), message.size()); } else { - ep2_map_dst(ans.q, message.begin(), (int)message.size(), dst, dst_len); + const byte* aug = nullptr; + size_t aug_len = 0; + + blst_hash_to_g2( + &(ans.q), + message.begin(), + message.size(), + dst, + dst_len, + aug, + aug_len); } - BLS::CheckRelicErrors(); assert(ans.IsValid()); return ans; } @@ -350,139 +558,134 @@ G2Element G2Element::FromMessage(Bytes const message, G2Element G2Element::Generator() { G2Element ele; - g2_get_gen(ele.q); - BLS::CheckRelicErrors(); + ele.q = (*blst_p2_generator()); return ele; } -bool G2Element::IsValid() const { - // Infinity no longer valid in Relic - // https://github.com/relic-toolkit/relic/commit/f3be2babb955cf9f82743e0ae5ef265d3da6c02b - if (g2_is_infty((g2_st*)q) == 1) +bool G2Element::IsValid() const +{ + // Infinity was considered a valid G2Element in older Relic versions + // on which this library was previously based. + // For historical compatibililty this behavior is maintained. + + if (blst_p2_is_inf(&q)) return true; - return g2_is_valid((g2_st*)q); + return blst_p2_on_curve(&q) && blst_p2_in_g2(&q); } -void G2Element::CheckValid() const { +void G2Element::CheckValid() const +{ if (!IsValid()) throw std::invalid_argument("G2 element is invalid"); - BLS::CheckRelicErrors(); } -void G2Element::ToNative(g2_t output) const { - g2_copy(output, (g2_st*)q); +void G2Element::ToNative(blst_p2* output) const +{ + memcpy(output, (blst_p2*)&q, sizeof(blst_p2)); } -G2Element G2Element::Copy() { - G2Element ele; - g2_copy(ele.q, this->q); - - return ele; +void G2Element::ToAffine(blst_p2_affine* output) const +{ + blst_p2_to_affine(output, &q); } +G2Element G2Element::Copy() { return *this; } G2Element G2Element::Negate() const { - G2Element ans; - g2_neg(ans.q, (g2_st*)q); - BLS::CheckRelicErrors(); + G2Element ans = G2Element::FromNative(q); + blst_p2_cneg(&(ans.q), true); return ans; } GTElement G2Element::Pair(const G1Element& a) const { return a & (*this); } -std::vector G2Element::Serialize(const bool fLegacy) const { +std::vector G2Element::Serialize(const bool fLegacy) const +{ const auto arr = G2Element::SerializeToArray(fLegacy); return std::vector{arr.begin(), arr.end()}; } -std::array G2Element::SerializeToArray(const bool fLegacy) const { - uint8_t buffer[G2Element::SIZE + 1]; - g2_write_bin(buffer, G2Element::SIZE + 1, (g2_st*)q, 1); - +std::array G2Element::SerializeToArray(const bool fLegacy) const +{ std::array result{}; - - if (buffer[0] == 0x00) { // infinity - result.fill(0); - result[0] = 0xc0; + if (!fLegacy) { + blst_p2_compress(result.data(), &q); return result; } - if (fLegacy) { - if (buffer[0] == 0x03) { // sign bit set - buffer[1] |= 0x80; - } - } else { - // remove leading 3 bits - buffer[1] &= 0x1f; - buffer[49] &= 0x1f; - if (buffer[0] == 0x03) { - buffer[49] |= 0xa0; // swapped later to 0 - } else { - buffer[49] |= 0x80; - } + if (blst_p2_is_inf(&q)) { + result[0] = 0xc0; + return result; } - if (fLegacy) { - std::memcpy(result.data(), buffer + 1, G2Element::SIZE); - } else { - // Swap buffer, relic uses the opposite ordering for Fq2 elements - std::memcpy(result.data(), buffer + 1 + G2Element::SIZE / 2, G2Element::SIZE / 2); - std::memcpy(result.data() + G2Element::SIZE / 2, buffer + 1, G2Element::SIZE / 2); + blst_p2_affine a; + blst_p2_to_affine(&a, &q); + // legacy layout: x.c0 || x.c1 (the modern IETF layout is the swap) + blst_bendian_from_fp(result.data(), &a.x.fp[0]); + blst_bendian_from_fp(result.data() + 48, &a.x.fp[1]); + // legacy sign: c1 > (p-1)/2, no tie-break (relic's ep2_pck) + if (FpSignGtHalf(a.y.fp[1])) { + result[0] |= 0x80; } - return result; } bool operator==(G2Element const& a, G2Element const& b) { - return g2_cmp((g2_st*)a.q, (g2_st*)b.q) == RLC_EQ; + return blst_p2_is_equal(&(a.q), &(b.q)); } bool operator!=(G2Element const& a, G2Element const& b) { return !(a == b); } -std::ostream& operator<<(std::ostream& os, const G2Element & s) +std::ostream& operator<<(std::ostream& os, const G2Element& s) { return os << Util::HexStr(s.Serialize()); } G2Element& operator+=(G2Element& a, const G2Element& b) { - g2_add(a.q, a.q, (g2_st*)b.q); - BLS::CheckRelicErrors(); + blst_p2_add_or_double(&(a.q), &(a.q), &(b.q)); return a; } G2Element operator+(const G2Element& a, const G2Element& b) { G2Element ans; - g2_add(ans.q, (g2_st*)a.q, (g2_st*)b.q); - BLS::CheckRelicErrors(); + blst_p2_add_or_double(&(ans.q), &(a.q), &(b.q)); return ans; } -G2Element operator*(const G2Element& a, const bn_t& k) +G2Element operator*(const G2Element& a, const blst_scalar& k) { G2Element ans; - g2_mul(ans.q, (g2_st*)a.q, (bn_st*)k); - BLS::CheckRelicErrors(); + byte* bte = Util::SecAlloc(32); + blst_lendian_from_scalar(bte, &k); + blst_p2_mult(&(ans.q), &(a.q), bte, 256); + Util::SecFree(bte); + return ans; } -G2Element operator*(const bn_t& k, const G2Element& a) { return a * k; } - - +G2Element operator*(const blst_scalar& k, const G2Element& a) { return a * k; } // GTElement const size_t GTElement::SIZE; +/* + * Currently deserliazation is not available - these are currently + * broken and just return the zero element + */ GTElement GTElement::FromBytes(Bytes const bytes) { GTElement ele = GTElement::FromBytesUnchecked(bytes); - if (gt_is_valid(*(gt_t*)&ele) == 0) - throw std::invalid_argument("GTElement is invalid"); + // + // this doesn't seem to be the proper check as it doesn't work as expeced + // + // if (!blst_fp12_in_group(&(ele.r))) + // throw std::invalid_argument("GTElement is invalid"); return ele; } @@ -492,8 +695,7 @@ GTElement GTElement::FromBytesUnchecked(Bytes const bytes) throw std::invalid_argument("GTElement::FromBytes: Invalid size"); } GTElement ele = GTElement(); - gt_read_bin(ele.r, bytes.begin(), GTElement::SIZE); - BLS::CheckRelicErrors(); + memcpy(&(ele.r), bytes.begin(), SIZE); return ele; } @@ -502,23 +704,35 @@ GTElement GTElement::FromByteVector(const std::vector& bytevec) return GTElement::FromBytes(Bytes(bytevec)); } -GTElement GTElement::FromNative(const gt_t* element) +GTElement GTElement::FromNative(const blst_fp12* element) { GTElement ele = GTElement(); - gt_copy(ele.r, *(gt_t*)element); + ele.r = *element; return ele; } -GTElement GTElement::Unity() { +GTElement GTElement::FromAffine(const blst_p1_affine& affine) +{ GTElement ele = GTElement(); - gt_set_unity(ele.r); + blst_aggregated_in_g1(&ele.r, &affine); return ele; } +GTElement GTElement::FromAffine(const blst_p2_affine& affine) +{ + GTElement ele = GTElement(); + blst_aggregated_in_g2(&ele.r, &affine); + return ele; +} + +GTElement GTElement::Unity() +{ + return GTElement::FromNative(blst_fp12_one()); +} bool operator==(GTElement const& a, GTElement const& b) { - return gt_cmp(*(gt_t*)(a.r), *(gt_t*)(b.r)) == RLC_EQ; + return blst_fp12_is_equal(&(a.r), &(b.r)); } bool operator!=(GTElement const& a, GTElement const& b) { return !(a == b); } @@ -530,31 +744,31 @@ std::ostream& operator<<(std::ostream& os, GTElement const& ele) GTElement operator&(const G1Element& a, const G2Element& b) { - G1Element nonConstA(a); - gt_t ans; - gt_new(ans); - g2_t tmp; - g2_null(tmp); - g2_new(tmp); - b.ToNative(tmp); - pp_map_oatep_k12(ans, nonConstA.p, tmp); + blst_fp12 ans; + + blst_p1_affine aff1; + blst_p2_affine aff2; + a.ToAffine(&aff1); + b.ToAffine(&aff2); + + blst_miller_loop(&ans, &aff2, &aff1); + blst_final_exp(&ans, &ans); + GTElement ret = GTElement::FromNative(&ans); - gt_free(ans); - g2_free(tmp); + return ret; } GTElement operator*(GTElement& a, GTElement& b) { GTElement ans; - fp12_mul(ans.r, a.r, b.r); - BLS::CheckRelicErrors(); + blst_fp12_mul(&(ans.r), &(a.r), &(b.r)); return ans; } void GTElement::Serialize(uint8_t* buffer) const { - gt_write_bin(buffer, GTElement::SIZE, *(gt_t*)&r, 1); + memcpy(buffer, &r, GTElement::SIZE); } std::vector GTElement::Serialize() const diff --git a/src/dashbls/src/extendedprivatekey.cpp b/src/dashbls/src/extendedprivatekey.cpp index d5fe746ee690..237aa0515892 100644 --- a/src/dashbls/src/extendedprivatekey.cpp +++ b/src/dashbls/src/extendedprivatekey.cpp @@ -31,27 +31,16 @@ ExtendedPrivateKey ExtendedPrivateKey::FromSeed(const Bytes& bytes) { // Hash the seed into 64 bytes, half will be sk, half will be cc hashInput[bytes.size()] = 0; - md_hmac(ILeft, hashInput, bytes.size() + 1, prefix, sizeof(prefix)); + Util::md_hmac(ILeft, hashInput, bytes.size() + 1, prefix, sizeof(prefix)); hashInput[bytes.size()] = 1; - md_hmac(IRight, hashInput, bytes.size() + 1, prefix, sizeof(prefix)); + Util::md_hmac(IRight, hashInput, bytes.size() + 1, prefix, sizeof(prefix)); // Make sure private key is less than the curve order - bn_t* skBn = Util::SecAlloc(1); - bn_t order; - bn_new(order); - g1_get_ord(order); - - bn_new(*skBn); - bn_read_bin(*skBn, ILeft, PrivateKey::PRIVATE_KEY_SIZE); - bn_mod_basic(*skBn, *skBn, order); - bn_write_bin(ILeft, PrivateKey::PRIVATE_KEY_SIZE, *skBn); - ExtendedPrivateKey esk(ExtendedPublicKey::REVISION, 0, 0, 0, ChainCode::FromBytes(Bytes(IRight, ChainCode::SIZE)), - PrivateKey::FromBytes(Bytes(ILeft, PrivateKey::PRIVATE_KEY_SIZE))); + PrivateKey::FromBytes(Bytes(ILeft, PrivateKey::PRIVATE_KEY_SIZE), true)); - Util::SecFree(skBn); Util::SecFree(ILeft); Util::SecFree(hashInput); return esk; @@ -101,13 +90,13 @@ ExtendedPrivateKey ExtendedPrivateKey::PrivateChild(uint32_t i, const bool fLega } hmacInput[inputLen - 1] = 0; - md_hmac(ILeft, hmacInput, inputLen, + Util::md_hmac(ILeft, hmacInput, inputLen, hmacKey, ChainCode::SIZE); // Change 1 byte to generate a different sequence for chaincode hmacInput[inputLen - 1] = 1; - md_hmac(IRight, hmacInput, inputLen, + Util::md_hmac(IRight, hmacInput, inputLen, hmacKey, ChainCode::SIZE); PrivateKey newSk = PrivateKey::FromBytes(Bytes(ILeft, PrivateKey::PRIVATE_KEY_SIZE), true); diff --git a/src/dashbls/src/extendedpublickey.cpp b/src/dashbls/src/extendedpublickey.cpp index a484dea64621..ad1015a68c9b 100644 --- a/src/dashbls/src/extendedpublickey.cpp +++ b/src/dashbls/src/extendedpublickey.cpp @@ -59,13 +59,13 @@ ExtendedPublicKey ExtendedPublicKey::PublicChild(uint32_t i, const bool fLegacy) hmacInput[inputLen - 1] = 0; Util::IntToFourBytes(hmacInput + G1Element::SIZE, i); - md_hmac(ILeft, hmacInput, inputLen, + Util::md_hmac(ILeft, hmacInput, inputLen, hmacKey, ChainCode::SIZE); // Change 1 byte to generate a different sequence for chaincode hmacInput[inputLen - 1] = 1; - md_hmac(IRight, hmacInput, inputLen, + Util::md_hmac(IRight, hmacInput, inputLen, hmacKey, ChainCode::SIZE); PrivateKey leftSk = PrivateKey::FromBytes(Bytes(ILeft, PrivateKey::PRIVATE_KEY_SIZE), true); diff --git a/src/dashbls/src/legacy.cpp b/src/dashbls/src/legacy.cpp index 44780528d6ba..a7d5832b9886 100644 --- a/src/dashbls/src/legacy.cpp +++ b/src/dashbls/src/legacy.cpp @@ -3,142 +3,69 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "legacy.hpp" - -#include - -#define B12_P381_S3 "BE32CE5FBEED9CA374D38C0ED41EEFD5BB675277CDF12D11BC2FB026C41400045C03FFFFFFFDFFFD" -#define B12_P381_S32 "5F19672FDF76CE51BA69C6076A0F77EADDB3A93BE6F89688DE17D813620A00022E01FFFFFFFEFFFE" - -/** - * Returns the (sqrt(-3) - 1) / 2 mod q in the curve, where q is the prime. - * - * @param[out] h - the returned cofactor. - */ -static void ep2_curve_get_s32(bn_t s32In) { - static std::once_flag is_initialized; - static bn_t s32; - std::call_once(is_initialized, [] { - bn_new(s32); - bn_read_str(s32, B12_P381_S32, sizeof(B12_P381_S32), 16); - }); - bn_copy(s32In, s32); +#include +#include +#include + +namespace { + +// sqrt(-3) mod p, big-endian, zero-padded to 48 bytes. Value taken from the +// relic implementation's B12_P381_S3 constant; validated by +// s3^2 == -3 (mod p). +const uint8_t S3_BE[48] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x32, 0xce, 0x5f, + 0xbe, 0xed, 0x9c, 0xa3, 0x74, 0xd3, 0x8c, 0x0e, 0xd4, 0x1e, 0xef, 0xd5, + 0xbb, 0x67, 0x52, 0x77, 0xcd, 0xf1, 0x2d, 0x11, 0xbc, 0x2f, 0xb0, 0x26, + 0xc4, 0x14, 0x00, 0x04, 0x5c, 0x03, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xfd}; + +// (sqrt(-3) - 1) / 2 mod p (relic's B12_P381_S32). +const uint8_t S32_BE[48] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x19, 0x67, 0x2f, + 0xdf, 0x76, 0xce, 0x51, 0xba, 0x69, 0xc6, 0x07, 0x6a, 0x0f, 0x77, 0xea, + 0xdd, 0xb3, 0xa9, 0x3b, 0xe6, 0xf8, 0x96, 0x88, 0xde, 0x17, 0xd8, 0x13, + 0x62, 0x0a, 0x00, 0x02, 0x2e, 0x01, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfe}; + +// Effective cofactor h_eff for BLS12-381 G2 (RFC 9380 section 8.8.2), +// big-endian, 80 bytes / 636 bits. Scalar multiplication by h_eff is +// equivalent to the psi-endomorphism-based cofactor clearing the relic +// implementation performed (verified empirically point-by-point). +const uint8_t H_EFF_BE[80] = { + 0x0b, 0xc6, 0x9f, 0x08, 0xf2, 0xee, 0x75, 0xb3, 0x58, 0x4c, 0x6a, 0x0e, + 0xa9, 0x1b, 0x35, 0x28, 0x88, 0xe2, 0xa8, 0xe9, 0x14, 0x5a, 0xd7, 0x68, + 0x99, 0x86, 0xff, 0x03, 0x15, 0x08, 0xff, 0xe1, 0x32, 0x9c, 0x2f, 0x17, + 0x87, 0x31, 0xdb, 0x95, 0x6d, 0x82, 0xbf, 0x01, 0x5d, 0x12, 0x12, 0xb0, + 0x2e, 0xc0, 0xec, 0x69, 0xd7, 0x47, 0x7c, 0x1a, 0xe9, 0x54, 0xcb, 0xc0, + 0x66, 0x89, 0xf6, 0xa3, 0x59, 0x89, 0x4c, 0x0a, 0xde, 0xbb, 0xf6, 0xb4, + 0xe8, 0x02, 0x00, 0x05, 0xaa, 0xa9, 0x55, 0x51}; + +void FpOne(blst_fp& out) +{ + uint8_t be[48] = {0}; + be[47] = 1; + blst_fp_from_bendian(&out, be); } -/** - * Returns the sqrt(-3) mod q in the curve, where q is the prime. - * - * @param[out] h - the returned cofactor. - */ -static void ep2_curve_get_s3(bn_t s3In) { - static std::once_flag is_initialized; - static bn_t s3; - std::call_once(is_initialized, [] { - bn_new(s3); - bn_read_str(s3, B12_P381_S3, sizeof(B12_P381_S3), 16); - }); - bn_copy(s3In, s3); +void FpFour(blst_fp& out) +{ + uint8_t be[48] = {0}; + be[47] = 4; + blst_fp_from_bendian(&out, be); } -/** - * Returns the 'b' coefficient of the currently configured elliptic curve. - * - * @param[out] b - the 'b' coefficient of the elliptic curve. - */ -static void ep2_curve_get_b(fp2_t b) { - ctx_t *ctx = core_get(); - fp_copy(b[0], ctx->ep2_b[0]); - fp_copy(b[1], ctx->ep2_b[1]); -} +inline void FpZero(blst_fp& out) { memset(&out, 0x00, sizeof(blst_fp)); } -/** - * Returns the variable used to parameterize the given prime modulus. - * - * @param[out] x - the integer parameter. - */ -static void fp_param_get_var(bn_t x) { - bn_t a; - - bn_null(a); - - RLC_TRY { - bn_new(a); - /* x = -(2^63 + 2^62 + 2^60 + 2^57 + 2^48 + 2^16). */ - bn_set_2b(x, 63); - bn_set_2b(a, 62); - bn_add(x, x, a); - bn_set_2b(a, 60); - bn_add(x, x, a); - bn_set_2b(a, 57); - bn_add(x, x, a); - bn_set_2b(a, 48); - bn_add(x, x, a); - bn_set_2b(a, 16); - bn_add(x, x, a); - bn_neg(x, x); - } - RLC_CATCH_ANY { - RLC_THROW(ERR_CAUGHT); - } - RLC_FINALLY { - bn_free(a); - } +bool FpIsZero(const blst_fp& a) +{ + uint8_t be[48]; + blst_bendian_from_fp(be, &a); + for (int i = 0; i < 48; i++) + if (be[i] != 0) return false; + return true; } -/** - * Multiplies a point by the cofactor in a Barreto-Lynn-Soctt. - * - * @param[out] r - the result. - * @param[in] p - the point to multiply. - */ -static void ep2_mul_cof_b12(ep2_t r, ep2_t p) { - bn_t x; - ep2_t t0, t1, t2, t3; - - ep2_null(t0); - ep2_null(t1); - ep2_null(t2); - ep2_null(t3); - bn_null(x); - - RLC_TRY { - ep2_new(t0); - ep2_new(t1); - ep2_new(t2); - ep2_new(t3); - bn_new(x); - - fp_param_get_var(x); - - /* Compute t0 = xP. */ - ep2_mul_basic(t0, p, x); - /* Compute t1 = [x^2]P. */ - ep2_mul_basic(t1, t0, x); - - /* t2 = (x^2 - x - 1)P = x^2P - x*P - P. */ - ep2_sub(t2, t1, t0); - ep2_sub(t2, t2, p); - /* t3 = \psi(x - 1)P. */ - ep2_sub(t3, t0, p); - ep2_norm(t3, t3); - ep2_frb(t3, t3, 1); - ep2_add(t2, t2, t3); - /* t3 = \psi^2(2P). */ - ep2_dbl(t3, p); - ep2_norm(t3, t3); - ep2_frb(t3, t3, 2); - ep2_add(t2, t2, t3); - ep2_norm(r, t2); - } - RLC_CATCH_ANY { - RLC_THROW(ERR_CAUGHT); - } - RLC_FINALLY { - ep2_free(t0); - ep2_free(t1); - ep2_free(t2); - ep2_free(t3); - bn_free(x); - } +bool Fp2IsZero(const blst_fp2& a) +{ + return FpIsZero(a.fp[0]) && FpIsZero(a.fp[1]); } /** @@ -146,288 +73,191 @@ static void ep2_mul_cof_b12(ep2_t r, ep2_t p) { * The algorithm is Shallue–van de Woestijne encoding from * Section 3 of "Indifferentiable Hashing to Barreto–Naehrig Curves" * from Fouque-Tibouchi: + * @param[out] p - the encoded point. + * @param[in] t - the field element to encode. + * Returns false when the result is the point at infinity (t == 0). */ -static void ep2_sw_encode(ep2_t p, fp2_t t) { - if (fp2_is_zero(t)) { +bool ep2_sw_encode(blst_p2_affine& p, const blst_fp2& t) +{ + if (Fp2IsZero(t)) { // Maps t=0 to the point at infinity. - ep2_set_infty(p); - return; + return false; } - fp2_t nt; // Negative t - fp2_t w; - fp2_t b; - bn_t s_n3; - bn_t s_n3m1o2; - fp2_t x1; - fp2_t x2; - fp2_t x3; - fp2_t rhs; - - fp2_new(nt); - fp2_new(w); - fp2_new(b); - bn_new(s_n3); - bn_new(s_n3m1o2); - fp2_new(x1); - fp2_new(x2); - fp2_new(x3); - fp2_new(rhs); - - // nt = -t - fp2_neg(nt, t); - - uint8_t buf0[RLC_FP_BYTES]; // t[1] - uint8_t buf1[RLC_FP_BYTES]; // -t[1] - fp_write_bin(buf0, RLC_FP_BYTES, t[1]); - fp_write_bin(buf1, RLC_FP_BYTES, nt[1]); - - // Compare bytes since fp_cmp compares montgomery representation - int parity = memcmp(buf0, buf1, RLC_FP_BYTES) > 0; + + // parity of t: compare the canonical bytes of t.c1 against those of + // (-t).c1 + blst_fp2 nt = t; + blst_fp2_cneg(&nt, &nt, true); + uint8_t buf0[48], buf1[48]; + blst_bendian_from_fp(buf0, &t.fp[1]); + blst_bendian_from_fp(buf1, &nt.fp[1]); + const bool parity = memcmp(buf0, buf1, 48) > 0; + + blst_fp one, four; + FpOne(one); + FpFour(four); + blst_fp2 b; + b.fp[0] = four; + b.fp[1] = four; // w = t^2 + b + 1 - fp2_mul(w, t, t); - ep2_curve_get_b(b); - fp2_add(w, w, b); - fp_add_dig(w[0], w[0], 1); + blst_fp2 w; + blst_fp2_sqr(&w, &t); + blst_fp2_add(&w, &w, &b); + blst_fp_add(&w.fp[0], &w.fp[0], &one); - if (fp2_is_zero(w)) { - ep2_curve_get_gen(p); + if (Fp2IsZero(w)) { + p = *blst_p2_affine_generator(); if (parity) { - ep2_neg(p, p); + blst_fp2_cneg(&p.y, &p.y, true); } - fp2_free(nt); - fp2_free(w); - fp2_free(b); - bn_free(s_n3); - bn_free(s_n3m1o2); - fp2_free(x1); - fp2_free(x2); - fp2_free(x3); - fp2_free(rhs); - return; + return true; } - // sqrt(-3) - ep2_curve_get_s3(s_n3); - fp2_t s_n3p; - fp2_null(s_n3p); - fp2_new(s_n3p); - fp2_t s_n3m1o2p; - fp2_null(s_n3m1o2p); - fp2_new(s_n3m1o2p); + blst_fp2 s3p, s32p; + blst_fp_from_bendian(&s3p.fp[0], S3_BE); + FpZero(s3p.fp[1]); + blst_fp_from_bendian(&s32p.fp[0], S32_BE); + FpZero(s32p.fp[1]); - fp2_zero(s_n3p); - fp2_zero(s_n3m1o2p); - fp_prime_conv(s_n3p[0], s_n3); + // w = sqrt(-3) * t / (t^2 + b + 1) + blst_fp2_inverse(&w, &w); + blst_fp2_mul(&w, &w, &s3p); + blst_fp2_mul(&w, &w, &t); - // (sqrt(-3) - 1) / 2 - ep2_curve_get_s32(s_n3m1o2); - fp_prime_conv(s_n3m1o2p[0], s_n3m1o2); - - fp2_inv(w, w); - fp2_mul(w, w, s_n3p); - fp2_mul(w, w, t); - - // x1 = -wt + sqrt(-3) - fp2_neg(x1, w); - fp2_mul(x1, x1, t); - fp2_add(x1, x1, s_n3m1o2p); + // x1 = -wt + (sqrt(-3) - 1) / 2 + blst_fp2 x1; + x1 = w; + blst_fp2_cneg(&x1, &x1, true); + blst_fp2_mul(&x1, &x1, &t); + blst_fp2_add(&x1, &x1, &s32p); // x2 = -x1 - 1 - fp2_neg(x2, x1); - fp_sub_dig(x2[0], x2[0], 1); + blst_fp2 x2 = x1; + blst_fp2_cneg(&x2, &x2, true); + blst_fp_sub(&x2.fp[0], &x2.fp[0], &one); // x3 = 1/w^2 + 1 - fp2_mul(x3, w, w); - fp2_inv(x3, x3); - fp_add_dig(x3[0], x3[0], 1); - - fp2_zero(p->y); - fp2_set_dig(p->z, 1); - - // if x1 has no y, try x2. if x2 has no y, try x3 - fp2_copy(p->x, x1); - - ep2_rhs(rhs, p); - int Xx1 = fp2_srt(p->y, rhs) ? 1 : -1; - fp2_copy(p->x, x2); - ep2_rhs(rhs, p); - int Xx2 = fp2_srt(p->y, rhs) ? 1 : -1; + blst_fp2 x3; + blst_fp2_sqr(&x3, &w); + blst_fp2_inverse(&x3, &x3); + blst_fp_add(&x3.fp[0], &x3.fp[0], &one); + + const auto rhs = [&b](blst_fp2& out, const blst_fp2& x) { + blst_fp2_sqr(&out, &x); + blst_fp2_mul(&out, &out, &x); + blst_fp2_add(&out, &out, &b); + }; + + blst_fp2 r, y; + rhs(r, x1); + const int Xx1 = blst_fp2_sqrt(&y, &r) ? 1 : -1; + rhs(r, x2); + const int Xx2 = blst_fp2_sqrt(&y, &r) ? 1 : -1; // This formula computes which index to use, in constant time // without conditional branches. It's taken from the paper. 3 is // added, because the % operator in c can be negative. - int index = ((((Xx1 - 1) * Xx2) % 3) + 3) % 3; - - if (index == 0) { - fp2_copy(p->x, x1); - ep2_rhs(rhs, p); - fp2_srt(p->y, rhs); - } else if (index == 1) { - fp2_copy(p->x, x2); - ep2_rhs(rhs, p); - fp2_srt(p->y, rhs); - } else if (index == 2) { - fp2_copy(p->x, x3); - ep2_rhs(rhs, p); - fp2_srt(p->y, rhs); - } - - p->coord = 1; - - // Check for lexicografically greater than the negation - fp2_t ny; - fp2_null(ny); - fp2_new(ny); - fp2_neg(ny, p->y); - fp_write_bin(buf0, RLC_FP_BYTES, p->y[1]); - fp_write_bin(buf1, RLC_FP_BYTES, ny[1]); - - // Compare bytes since fp_cmp compares montgomery representation - if ((memcmp(buf0, buf1, RLC_FP_BYTES) > 0) != parity) { - ep2_neg(p, p); + const int index = ((((Xx1 - 1) * Xx2) % 3) + 3) % 3; + + p.x = (index == 0) ? x1 : (index == 1) ? x2 : x3; + rhs(r, p.x); + const bool haveRoot = blst_fp2_sqrt(&p.y, &r); + (void)haveRoot; + assert(haveRoot); // guaranteed by the SW construction + + // Normalize the sign of y against the parity of t + blst_fp2 ny = p.y; + blst_fp2_cneg(&ny, &ny, true); + blst_bendian_from_fp(buf0, &p.y.fp[1]); + blst_bendian_from_fp(buf1, &ny.fp[1]); + if ((memcmp(buf0, buf1, 48) > 0) != parity) { + p.y = ny; } + return true; +} - fp2_free(nt); - fp2_free(w); - fp2_free(b); - bn_free(s_n3); - bn_free(s_n3m1o2); - fp2_free(x1); - fp2_free(x2); - fp2_free(x3); - fp2_free(rhs); - - fp2_free(s_n3p); - fp2_free(s_n3m1o2p); - fp2_free(ny); +// Reduce a 64-byte big-endian value mod p into an fp element, matching +// relic's bn_read_bin + fp_prime_conv: split as hi*2^256 + lo with both +// halves < 2^256 < p. +void FpFromBE64Wide(blst_fp& out, const uint8_t* be64) +{ + uint8_t padded[48] = {0}; + blst_fp hi, lo, c256; + + memcpy(padded + 16, be64, 32); + blst_fp_from_bendian(&hi, padded); + memcpy(padded + 16, be64 + 32, 32); + blst_fp_from_bendian(&lo, padded); + + // 2^256 mod p == 2^256 (p is 381 bits) + memset(padded, 0, 48); + padded[15] = 0x01; + blst_fp_from_bendian(&c256, padded); + + blst_fp_mul(&out, &hi, &c256); + blst_fp_add(&out, &out, &lo); } +} // anon namespace + +namespace bls { +void ep2_map_legacy(blst_p2* p, const uint8_t* msg, size_t len) +{ + if (len != 32) { + throw std::invalid_argument( + "ep2_map_legacy requires a 32-byte message hash"); + } -void ep2_map_legacy(ep2_t p, const uint8_t *msg, int len) { - bn_t t00; - bn_t t01; - bn_t t10; - bn_t t11; - fp_t t00p; - fp_t t01p; - fp_t t10p; - fp_t t11p; - fp2_t t0p; - fp2_t t1p; - ep2_t p0; - ep2_t p1; - - bn_null(t00); - bn_null(t01); - bn_null(t10); - bn_null(t11); - fp_null(t00p); - fp_null(t01p); - fp_null(t10p); - fp_null(t11p); - fp2_null(t0p); - fp2_null(t1p); - ep2_null(p1); - ep2_null(p0); - - RLC_TRY { - uint8_t input[RLC_MD_LEN + 8]; - if (len != RLC_MD_LEN) { - RLC_THROW(ERR_CAUGHT); - } - memcpy(input, msg, len); - // b"G2_0_c0" - input[RLC_MD_LEN + 0] = 0x47; // G - input[RLC_MD_LEN + 1] = 0x32; // 2 - input[RLC_MD_LEN + 2] = 0x5f; // _ - input[RLC_MD_LEN + 3] = 0x30; // 0 - input[RLC_MD_LEN + 4] = 0x5f; // _ - input[RLC_MD_LEN + 5] = 0x63; // c - input[RLC_MD_LEN + 6] = 0x30; // 0 - - bn_new(t00); - bn_new(t01); - bn_new(t10); - bn_new(t11); - fp_new(t00p); - fp_new(t01p); - fp_new(t10p); - fp_new(t11p); - fp2_new(t0p); - fp2_new(t1p); - ep2_new(p1); - ep2_new(p0); - - uint8_t t00Bytes[RLC_MD_LEN * 2]; - uint8_t t01Bytes[RLC_MD_LEN * 2]; - uint8_t t10Bytes[RLC_MD_LEN * 2]; - uint8_t t11Bytes[RLC_MD_LEN * 2]; - - // b"G2_0_c0" - input[RLC_MD_LEN + 7] = 0x00; // 0 - md_map(t00Bytes, input, RLC_MD_LEN + 8); - input[RLC_MD_LEN + 7] = 1; // 1 - md_map(t00Bytes + RLC_MD_LEN, input, RLC_MD_LEN + 8); - - // b"G2_0_c1" - input[RLC_MD_LEN + 6] = 0x31; // b"1" - input[RLC_MD_LEN + 7] = 0; // 0 - - md_map(t01Bytes, input, RLC_MD_LEN + 8); - input[RLC_MD_LEN + 7] = 1; // 1 - md_map(t01Bytes + RLC_MD_LEN, input, RLC_MD_LEN + 8); - - // b"G2_1_c0" - input[RLC_MD_LEN + 3] = 0x31; // b"1" - input[RLC_MD_LEN + 6] = 0x30; // b"0" - input[RLC_MD_LEN + 7] = 0; // 0 - md_map(t10Bytes, input, RLC_MD_LEN + 8); - input[RLC_MD_LEN + 7] = 1; // 1 - md_map(t10Bytes + RLC_MD_LEN, input, RLC_MD_LEN + 8); - - // b"G2_1_c1" - input[RLC_MD_LEN + 6] = 0x31; // b"1" - input[RLC_MD_LEN + 7] = 0; // 0 - md_map(t11Bytes, input, RLC_MD_LEN + 8); - input[RLC_MD_LEN + 7] = 1; // 1 - md_map(t11Bytes + RLC_MD_LEN, input, RLC_MD_LEN + 8); - - bn_read_bin(t00, t00Bytes, RLC_MD_LEN * 2); - bn_read_bin(t01, t01Bytes, RLC_MD_LEN * 2); - bn_read_bin(t10, t10Bytes, RLC_MD_LEN * 2); - bn_read_bin(t11, t11Bytes, RLC_MD_LEN * 2); - - fp_prime_conv(t00p, t00); - fp_prime_conv(t01p, t01); - fp_prime_conv(t10p, t10); - fp_prime_conv(t11p, t11); - - fp_copy(t0p[0], t00p); - fp_copy(t0p[1], t01p); - fp_copy(t1p[0], t10p); - fp_copy(t1p[1], t11p); - - ep2_sw_encode(p0, t0p); - ep2_sw_encode(p1, t1p); - ep2_add(p0, p0, p1); - /* Now, multiply by cofactor to get the correct group. */ - ep2_mul_cof_b12(p, p0); + uint8_t input[32 + 8]; + memcpy(input, msg, 32); + + uint8_t t00Bytes[64], t01Bytes[64], t10Bytes[64], t11Bytes[64]; + + const auto draw = [&input](uint8_t* out, char i, char j) { + // tag: "G2__c" followed by a counter byte + input[32 + 0] = 0x47; // G + input[32 + 1] = 0x32; // 2 + input[32 + 2] = 0x5f; // _ + input[32 + 3] = (uint8_t)i; + input[32 + 4] = 0x5f; // _ + input[32 + 5] = 0x63; // c + input[32 + 6] = (uint8_t)j; + input[32 + 7] = 0; + blst_sha256(out, input, 32 + 8); + input[32 + 7] = 1; + blst_sha256(out + 32, input, 32 + 8); + }; + + draw(t00Bytes, '0', '0'); + draw(t01Bytes, '0', '1'); + draw(t10Bytes, '1', '0'); + draw(t11Bytes, '1', '1'); + + blst_fp2 t0, t1; + FpFromBE64Wide(t0.fp[0], t00Bytes); + FpFromBE64Wide(t0.fp[1], t01Bytes); + FpFromBE64Wide(t1.fp[0], t10Bytes); + FpFromBE64Wide(t1.fp[1], t11Bytes); + + blst_p2_affine a0, a1; + const bool has0 = ep2_sw_encode(a0, t0); + const bool has1 = ep2_sw_encode(a1, t1); + + blst_p2 sum; + memset(&sum, 0x00, sizeof(blst_p2)); // infinity + if (has0) { + blst_p2_from_affine(&sum, &a0); } - RLC_CATCH_ANY { - RLC_THROW(ERR_CAUGHT); + if (has1) { + blst_p2_add_or_double_affine(&sum, &sum, &a1); } - RLC_FINALLY { - fp2_free(t0p); - fp2_free(t1p); - fp_free(t00p); - fp_free(t01p); - fp_free(t10p); - fp_free(t11p); - bn_free(t00); - bn_free(t01); - bn_free(t10); - bn_free(t11); - ep2_free(p0); - ep2_free(p1); + + // Clear the cofactor by multiplying with h_eff (equivalent to the + // psi-based clearing the relic implementation used). + uint8_t heffLE[sizeof(H_EFF_BE)]; + for (size_t i = 0; i < sizeof(H_EFF_BE); i++) { + heffLE[i] = H_EFF_BE[sizeof(H_EFF_BE) - 1 - i]; } + blst_p2_mult(p, &sum, heffLE, 636); } +} // namespace bls diff --git a/src/dashbls/src/privatekey.cpp b/src/dashbls/src/privatekey.cpp index d07246d8575e..51eb8acd9653 100644 --- a/src/dashbls/src/privatekey.cpp +++ b/src/dashbls/src/privatekey.cpp @@ -12,6 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + +#include + #include "bls.hpp" #include "legacy.hpp" @@ -28,81 +32,65 @@ PrivateKey PrivateKey::FromSeedBIP32(const Bytes& seed) { PrivateKey::PRIVATE_KEY_SIZE); // Hash the seed into sk - md_hmac(hash, seed.begin(), (int)seed.size(), hmacKey, sizeof(hmacKey)); - - bn_t order; - bn_new(order); - g1_get_ord(order); + Util::md_hmac(hash, seed.begin(), seed.size(), hmacKey, sizeof(hmacKey)); // Make sure private key is less than the curve order - bn_t* skBn = Util::SecAlloc(1); - bn_new(*skBn); - bn_read_bin(*skBn, hash, PrivateKey::PRIVATE_KEY_SIZE); - bn_mod_basic(*skBn, *skBn, order); - PrivateKey k; - bn_copy(k.keydata, *skBn); + blst_scalar_from_be_bytes(k.keydata, hash, PrivateKey::PRIVATE_KEY_SIZE); - Util::SecFree(skBn); Util::SecFree(hash); return k; } +// BLS12-381 group order r, big-endian. +// Taken from depends/blst/src/consts.c: BLS12_381_r = { 0xffffffff00000001, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48 } +// (little-endian limbs of the same number, with the comment z^4 - z^2 + 1, group order). + +static const uint8_t ORDER_BE[32] = { + 0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48, 0x33, 0x39, 0xd8, 0x08, + 0x09, 0xa1, 0xd8, 0x05, 0x53, 0xbd, 0xa4, 0x02, 0xff, 0xfe, 0x5b, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01}; + // Construct a private key from a bytearray. -PrivateKey PrivateKey::FromBytes(const Bytes& bytes, bool modOrder) +PrivateKey PrivateKey::FromBytes(const Bytes &bytes, bool modOrder) { if (bytes.size() != PRIVATE_KEY_SIZE) { throw std::invalid_argument("PrivateKey::FromBytes: Invalid size"); } PrivateKey k; - bn_read_bin(k.keydata, bytes.begin(), PrivateKey::PRIVATE_KEY_SIZE); - bn_t ord; - bn_new(ord); - g1_get_ord(ord); - if (modOrder) { - bn_mod_basic(k.keydata, k.keydata, ord); - } else { - if (bn_cmp(k.keydata, ord) > 0) { + if (modOrder) + // this allows any bytes to be input and does proper mod order + blst_scalar_from_be_bytes(k.keydata, bytes.begin(), bytes.size()); + else { + // Values strictly greater than the group order are rejected; the + // order itself is accepted, matching the relic-based + // implementation's bn_cmp(keydata, order) > 0 check. + if (memcmp(bytes.begin(), ORDER_BE, PRIVATE_KEY_SIZE) > 0) { throw std::invalid_argument( "PrivateKey byte data must be less than the group order"); } + blst_scalar_from_bendian(k.keydata, bytes.begin()); } return k; } // Construct a private key from a bytearray. -PrivateKey PrivateKey::FromByteVector(const std::vector bytes, bool modOrder) +PrivateKey PrivateKey::FromByteVector( + const std::vector bytes, + bool modOrder) { return PrivateKey::FromBytes(Bytes(bytes), modOrder); } -// Construct a private key from a bytearray. -PrivateKey PrivateKey::RandomPrivateKey() -{ - bn_t *r = Util::SecAlloc(1); - bn_new(*r); - bn_rand(*r, RLC_POS, 256); - PrivateKey k; - bn_copy(k.keydata, *r); - bn_t ord; - bn_new(ord); - g1_get_ord(ord); - bn_mod_basic(k.keydata, k.keydata, ord); - Util::SecFree(r); - return k; -} - -PrivateKey::PrivateKey() { - AllocateKeyData(); -}; +PrivateKey::PrivateKey() { AllocateKeyData(); }; // Construct a private key from another private key. PrivateKey::PrivateKey(const PrivateKey &privateKey) { privateKey.CheckKeyData(); AllocateKeyData(); - bn_copy(keydata, privateKey.keydata); + memcpy(keydata, privateKey.keydata, sizeof(blst_scalar)); } PrivateKey::PrivateKey(PrivateKey &&k) @@ -111,14 +99,11 @@ PrivateKey::PrivateKey(PrivateKey &&k) k.InvalidateCaches(); } -PrivateKey::~PrivateKey() -{ - DeallocateKeyData(); -} +PrivateKey::~PrivateKey() { DeallocateKeyData(); } void PrivateKey::DeallocateKeyData() { - if(keydata != nullptr) { + if (keydata != nullptr) { Util::SecFree(keydata); keydata = nullptr; } @@ -131,16 +116,16 @@ void PrivateKey::InvalidateCaches() fG2CacheValid = false; } -PrivateKey& PrivateKey::operator=(const PrivateKey& other) +PrivateKey &PrivateKey::operator=(const PrivateKey &other) { CheckKeyData(); other.CheckKeyData(); InvalidateCaches(); - bn_copy(keydata, other.keydata); + memcpy(keydata, other.keydata, sizeof(blst_scalar)); return *this; } -PrivateKey& PrivateKey::operator=(PrivateKey&& other) +PrivateKey &PrivateKey::operator=(PrivateKey &&other) { DeallocateKeyData(); keydata = std::exchange(other.keydata, nullptr); @@ -148,28 +133,28 @@ PrivateKey& PrivateKey::operator=(PrivateKey&& other) return *this; } -const G1Element& PrivateKey::GetG1Element() const +const G1Element &PrivateKey::GetG1Element() const { if (!fG1CacheValid) { CheckKeyData(); - g1_st *p = Util::SecAlloc(1); - g1_mul_gen(p, keydata); + blst_p1 *p = Util::SecAlloc(1); + blst_sk_to_pk_in_g1(p, keydata); - g1Cache = G1Element::FromNative(p); + g1Cache = G1Element::FromNative(*p); Util::SecFree(p); fG1CacheValid = true; } return g1Cache; } -const G2Element& PrivateKey::GetG2Element() const +const G2Element &PrivateKey::GetG2Element() const { if (!fG2CacheValid) { CheckKeyData(); - g2_st *q = Util::SecAlloc(1); - g2_mul_gen(q, keydata); + blst_p2 *q = Util::SecAlloc(1); + blst_sk_to_pk_in_g2(q, keydata); - g2Cache = G2Element::FromNative(q); + g2Cache = G2Element::FromNative(*q); Util::SecFree(q); fG2CacheValid = true; } @@ -184,11 +169,15 @@ bool PrivateKey::HasKeyData() const G1Element operator*(const G1Element &a, const PrivateKey &k) { k.CheckKeyData(); - g1_st* ans = Util::SecAlloc(1); + + blst_p1 *ans = Util::SecAlloc(1); a.ToNative(ans); - g1_mul(ans, ans, k.keydata); - G1Element ret = G1Element::FromNative(ans); + byte *bte = Util::SecAlloc(32); + blst_lendian_from_scalar(bte, k.keydata); + blst_p1_mult(ans, ans, bte, 256); + G1Element ret = G1Element::FromNative(*ans); Util::SecFree(ans); + Util::SecFree(bte); return ret; } @@ -197,40 +186,40 @@ G1Element operator*(const PrivateKey &k, const G1Element &a) { return a * k; } G2Element operator*(const G2Element &a, const PrivateKey &k) { k.CheckKeyData(); - g2_st* ans = Util::SecAlloc(1); + blst_p2 *ans = Util::SecAlloc(1); a.ToNative(ans); - g2_mul(ans, ans, k.keydata); - G2Element ret = G2Element::FromNative(ans); + byte *bte = Util::SecAlloc(32); + blst_lendian_from_scalar(bte, k.keydata); + blst_p2_mult(ans, ans, bte, 256); + G2Element ret = G2Element::FromNative(*ans); Util::SecFree(ans); + Util::SecFree(bte); return ret; } G2Element operator*(const PrivateKey &k, const G2Element &a) { return a * k; } -PrivateKey operator*(const PrivateKey& k, const bn_t& a) +PrivateKey operator*(const PrivateKey& k, const blst_scalar& a) { k.CheckKeyData(); - bn_t order; - bn_new(order); - g2_get_ord(order); - PrivateKey ret; - bn_mul_comba(ret.keydata, k.keydata, a); - bn_mod_basic(ret.keydata, ret.keydata, order); + blst_sk_mul_n_check(ret.keydata, k.keydata, &a); return ret; } -PrivateKey operator*(const bn_t& a, const PrivateKey& k) { return a * k; } +PrivateKey operator*(const blst_scalar& a, const PrivateKey& k) { return k * a; } -G2Element PrivateKey::GetG2Power(const G2Element& element) const +G2Element PrivateKey::GetG2Power(const G2Element &element) const { CheckKeyData(); - g2_st* q = Util::SecAlloc(1); + blst_p2 *q = Util::SecAlloc(1); element.ToNative(q); - g2_mul(q, q, keydata); - - const G2Element ret = G2Element::FromNative(q); + byte *bte = Util::SecAlloc(32); + blst_lendian_from_scalar(bte, keydata); + blst_p2_mult(q, q, bte, 255); + const G2Element ret = G2Element::FromNative(*q); Util::SecFree(q); + Util::SecFree(bte); return ret; } @@ -240,30 +229,29 @@ PrivateKey PrivateKey::Aggregate(std::vector const &privateKeys) throw std::length_error("Number of private keys must be at least 1"); } - bn_t order; - bn_new(order); - g1_get_ord(order); - PrivateKey ret; assert(ret.IsZero()); for (size_t i = 0; i < privateKeys.size(); i++) { privateKeys[i].CheckKeyData(); - bn_add(ret.keydata, ret.keydata, privateKeys[i].keydata); - bn_mod_basic(ret.keydata, ret.keydata, order); + blst_sk_add_n_check(ret.keydata, ret.keydata, privateKeys[i].keydata); } return ret; } -bool PrivateKey::IsZero() const { +bool PrivateKey::IsZero() const +{ CheckKeyData(); - return bn_is_zero(keydata); + blst_scalar zro; + memset(&zro, 0x00, sizeof(blst_scalar)); + + return memcmp(keydata, &zro, sizeof(blst_scalar)) == 0; } bool operator==(const PrivateKey &a, const PrivateKey &b) { a.CheckKeyData(); b.CheckKeyData(); - return bn_cmp(a.keydata, b.keydata) == RLC_EQ; + return memcmp(a.keydata, b.keydata, sizeof(blst_scalar)) == 0; } bool operator!=(const PrivateKey &a, const PrivateKey &b) { return !(a == b); } @@ -274,17 +262,21 @@ void PrivateKey::Serialize(uint8_t *buffer) const throw std::runtime_error("PrivateKey::Serialize buffer invalid"); } CheckKeyData(); - bn_write_bin(buffer, PrivateKey::PRIVATE_KEY_SIZE, keydata); + // blst_bendian_from_scalar converts through a temporary limb vector and + // securely wipes it, which costs more than the serialization itself; + // the scalar's native bytes are little-endian, so copy and reverse. + blst_lendian_from_scalar(buffer, keydata); + std::reverse(buffer, buffer + PRIVATE_KEY_SIZE); } -std::vector PrivateKey::Serialize(const bool fLegacy) const +std::vector PrivateKey::Serialize() const { std::vector data(PRIVATE_KEY_SIZE); Serialize(data.data()); return data; } -std::array PrivateKey::SerializeToArray(bool fLegacy) const +std::array PrivateKey::SerializeToArray() const { std::array data{}; Serialize(data.data()); @@ -299,35 +291,34 @@ G2Element PrivateKey::SignG2( const bool fLegacy) const { CheckKeyData(); + if (fLegacy && len != BLS::MESSAGE_HASH_LEN) { + throw std::invalid_argument("legacy signing requires a 32-byte message hash"); + } - g2_t pt; - g2_null(pt); - g2_new(pt); - + blst_p2 *pt = Util::SecAlloc(1); if (fLegacy) { - ep2_map_legacy(pt, msg, BLS::MESSAGE_HASH_LEN); + ep2_map_legacy(pt, msg, len); } else { - ep2_map_dst(pt, msg, len, dst, dst_len); + blst_hash_to_g2(pt, msg, len, dst, dst_len, nullptr, 0); } - - g2_mul(pt, pt, keydata); - G2Element ret = G2Element::FromNative(pt); - g2_free(pt); + blst_sign_pk_in_g1(pt, pt, keydata); + G2Element ret = G2Element::FromNative(*pt); + Util::SecFree(pt); return ret; } void PrivateKey::AllocateKeyData() { assert(!keydata); - keydata = Util::SecAlloc(1); - keydata->alloc = RLC_BN_SIZE; - bn_zero(keydata); + keydata = Util::SecAlloc(1); + memset(keydata, 0x00, sizeof(blst_scalar)); } void PrivateKey::CheckKeyData() const { if (keydata == nullptr) { - throw std::runtime_error("PrivateKey::CheckKeyData keydata not initialized"); + throw std::runtime_error( + "PrivateKey::CheckKeyData keydata not initialized"); } } diff --git a/src/dashbls/src/schemes.cpp b/src/dashbls/src/schemes.cpp index af33f1f50eee..506ea9eee729 100644 --- a/src/dashbls/src/schemes.cpp +++ b/src/dashbls/src/schemes.cpp @@ -12,6 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "schemes.hpp" + +#include + #include #include #include @@ -19,9 +23,7 @@ #include "bls.hpp" #include "elements.hpp" -#include "schemes.hpp" #include "hdkeys.hpp" -#include "bn_helpers.hpp" using std::string; using std::vector; @@ -29,11 +31,8 @@ using std::vector; namespace bls { template -static void HashPubKeys(bn_t* computedTs, size_t nPubKeys, GetBytesFn getBytes) +static void HashPubKeys(blst_scalar* computedTs, size_t nPubKeys, GetBytesFn getBytes) { - BnGuard order; - g2_get_ord(order.val); - std::vector vecBuffer(nPubKeys * G1Element::SIZE); for (size_t i = 0; i < nPubKeys; i++) { @@ -53,18 +52,19 @@ static void HashPubKeys(bn_t* computedTs, size_t nPubKeys, GetBytesFn getBytes) std::memcpy(buffer + 4, pkHash, 32); Util::Hash256(hash, buffer, 4 + 32); - bn_read_bin(computedTs[i], hash, 32); - bn_mod_basic(computedTs[i], computedTs[i], order.val); + // reduces the hash mod the group order, like the former + // bn_read_bin + bn_mod + blst_scalar_from_be_bytes(&computedTs[i], hash, 32); } } -enum InvariantResult { BAD=false, GOOD=true, CONTINUE }; +enum InvariantResult { BAD = false, GOOD = true, CONTINUE }; // Enforce argument invariants for Agg Sig Verification InvariantResult VerifyAggregateSignatureArguments( const size_t nPubKeys, const size_t nMessages, - const G2Element &signature) + const G2Element& signature) { if (nPubKeys == 0) { return (nMessages == 0 && signature == G2Element() ? GOOD : BAD); @@ -78,79 +78,99 @@ InvariantResult VerifyAggregateSignatureArguments( /* These are all for the min-pubkey-size variant. TODO : analogs for min-signature-size */ -const std::string BasicSchemeMPL::CIPHERSUITE_ID = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_"; -const std::string AugSchemeMPL::CIPHERSUITE_ID = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_"; -const std::string PopSchemeMPL::CIPHERSUITE_ID = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; -const std::string PopSchemeMPL::POP_CIPHERSUITE_ID = "BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; +const std::string BasicSchemeMPL::CIPHERSUITE_ID = + "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_"; +const std::string AugSchemeMPL::CIPHERSUITE_ID = + "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_"; +const std::string PopSchemeMPL::CIPHERSUITE_ID = + "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; +const std::string PopSchemeMPL::POP_CIPHERSUITE_ID = + "BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; -PrivateKey CoreMPL::KeyGen(const vector& seed) { +PrivateKey CoreMPL::KeyGen(const vector& seed) +{ return HDKeys::KeyGen(seed); } -PrivateKey CoreMPL::KeyGen(const Bytes& seed) { - return HDKeys::KeyGen(seed); -} +PrivateKey CoreMPL::KeyGen(const Bytes& seed) { return HDKeys::KeyGen(seed); } -vector CoreMPL::SkToPk(const PrivateKey &seckey) +vector CoreMPL::SkToPk(const PrivateKey& seckey) { return seckey.GetG1Element().Serialize(); } -G1Element CoreMPL::SkToG1(const PrivateKey &seckey) +G1Element CoreMPL::SkToG1(const PrivateKey& seckey) { return seckey.GetG1Element(); } -G2Element CoreMPL::Sign(const PrivateKey &seckey, const vector &message) +G2Element CoreMPL::Sign( + const PrivateKey& seckey, + const vector& message) { return CoreMPL::Sign(seckey, Bytes(message)); } G2Element CoreMPL::Sign(const PrivateKey& seckey, const Bytes& message) { - return seckey.SignG2(message.begin(), message.size(), (const uint8_t*)strCiphersuiteId.c_str(), strCiphersuiteId.length()); + return seckey.SignG2( + message.begin(), + message.size(), + (const uint8_t*)strCiphersuiteId.c_str(), + strCiphersuiteId.length()); } -bool CoreMPL::Verify(const vector &pubkey, - const vector &message, // unhashed - const vector &signature) +bool CoreMPL::Verify( + const vector& pubkey, + const vector& message, // unhashed + const vector& signature) { - return CoreMPL::Verify(G1Element::FromBytes(Bytes(pubkey)), - Bytes(message), - G2Element::FromBytes(Bytes(signature))); + return CoreMPL::Verify(Bytes(pubkey), Bytes(message), Bytes(signature)); } -bool CoreMPL::Verify(const Bytes& pubkey, const Bytes& message, const Bytes& signature) +bool CoreMPL::Verify( + const Bytes& pubkey, + const Bytes& message, + const Bytes& signature) { - return CoreMPL::Verify(G1Element::FromBytes(pubkey), message, G2Element::FromBytes(signature)); + G1Element pubkeyElement; + G2Element signatureElement; + try { + pubkeyElement = G1Element::FromBytes(pubkey); + signatureElement = G2Element::FromBytes(signature); + } catch (...) { + return false; + } + return CoreMPL::Verify(pubkeyElement, message, signatureElement); } -bool CoreMPL::Verify(const G1Element &pubkey, - const vector &message, // unhashed - const G2Element &signature) +bool CoreMPL::Verify( + const G1Element& pubkey, + const vector& message, // unhashed + const G2Element& signature) { return CoreMPL::Verify(pubkey, Bytes(message), signature); } -bool CoreMPL::Verify(const G1Element& pubkey, const Bytes& message, const G2Element& signature) +bool CoreMPL::Verify( + const G1Element& pubkey, + const Bytes& message, + const G2Element& signature) { + // Keep the relic-era semantics rather than blst_core_verify: elements are + // gated by IsValid() and the check is the product of pairings. const G2Element hashedPoint = G2Element::FromMessage(message, (const uint8_t*)strCiphersuiteId.c_str(), strCiphersuiteId.length()); - std::array g1s; - std::array g2s; - - G1Element::Generator().Negate().ToNative(g1s[0]); - if (!pubkey.IsValid()) { + if (!pubkey.IsValid() || pubkey == G1Element()) { return false; } - if (!signature.IsValid()) { + if (!signature.IsValid() || signature == G2Element()) { return false; } - pubkey.ToNative(g1s[1]); - signature.ToNative(g2s[0]); - hashedPoint.ToNative(g2s[1]); - return CoreMPL::NativeVerify(g1s.data(), g2s.data(), 2); + const std::vector g1s{G1Element::Generator().Negate(), pubkey}; + const std::vector g2s{signature, hashedPoint}; + return CoreMPL::NativeVerify(g1s, g2s); } std::array CoreMPL::Aggregate(const vector> &signatures) @@ -173,7 +193,7 @@ std::array CoreMPL::Aggregate(const vector& sig return CoreMPL::Aggregate(elements).SerializeToArray(); } -G2Element CoreMPL::Aggregate(const vector &signatures) +G2Element CoreMPL::Aggregate(const vector& signatures) { G2Element aggregated; for (const G2Element& signature : signatures) { @@ -182,7 +202,7 @@ G2Element CoreMPL::Aggregate(const vector &signatures) return aggregated; } -G1Element CoreMPL::Aggregate(const vector &publicKeys) +G1Element CoreMPL::Aggregate(const vector& publicKeys) { G1Element aggregated; for (const G1Element& publicKey : publicKeys) { @@ -193,13 +213,13 @@ G1Element CoreMPL::Aggregate(const vector &publicKeys) G2Element CoreMPL::AggregateSecure(std::vector const &vecPublicKeys, std::vector const &vecSignatures, - const Bytes& message, + const Bytes& /*message*/, const bool fLegacy) { if (vecSignatures.size() != vecPublicKeys.size()) { throw std::invalid_argument("LegacySchemeMPL::AggregateSigs sigs.size() != pubKeys.size()"); } - BnArrayGuard computedTs(vecPublicKeys.size()); + std::vector computedTs(vecPublicKeys.size()); std::vector, const G2Element*>> vecSorted(vecPublicKeys.size()); for (size_t i = 0; i < vecPublicKeys.size(); i++) { vecSorted[i] = std::make_pair(vecPublicKeys[i].SerializeToArray(fLegacy), &vecSignatures[i]); @@ -208,7 +228,7 @@ G2Element CoreMPL::AggregateSecure(std::vector const &vecPublicKeys, return std::memcmp(a.first.data(), b.first.data(), G1Element::SIZE) < 0; }); - HashPubKeys(computedTs.data, vecSorted.size(), + HashPubKeys(computedTs.data(), vecSorted.size(), [&](size_t i) { return vecSorted[i].first.data(); }); // Raise all signatures to power of the corresponding t's and aggregate the results into aggSig @@ -232,7 +252,16 @@ bool CoreMPL::VerifySecure(const std::vector& vecPublicKeys, const G2Element& signature, const Bytes& message, const bool fLegacy) { - BnArrayGuard computedTs(vecPublicKeys.size()); + for (const auto& pk : vecPublicKeys) { + if (!pk.IsValid() || pk == G1Element()) { + return false; + } + } + if (!signature.IsValid() || signature == G2Element()) { + return false; + } + + std::vector computedTs(vecPublicKeys.size()); std::vector> vecSorted(vecPublicKeys.size()); for (size_t i = 0; i < vecPublicKeys.size(); i++) { vecSorted[i] = vecPublicKeys[i].SerializeToArray(fLegacy); @@ -241,7 +270,7 @@ bool CoreMPL::VerifySecure(const std::vector& vecPublicKeys, return std::memcmp(a.data(), b.data(), G1Element::SIZE) < 0; }); - HashPubKeys(computedTs.data, vecSorted.size(), + HashPubKeys(computedTs.data(), vecSorted.size(), [&](size_t i) { return vecSorted[i].data(); }); G1Element publicKey; @@ -259,132 +288,178 @@ bool CoreMPL::VerifySecure(const std::vector& vecPublicKeys, return CoreMPL::VerifySecure(vecPublicKeys, signature, message, false); } -bool CoreMPL::AggregateVerify(const vector> &pubkeys, - const vector> &messages, // unhashed - const vector &signature) +bool CoreMPL::AggregateVerify( + const vector>& pubkeys, + const vector>& messages, // unhashed + const vector& signature) { const std::vector vecPubKeyBytes(pubkeys.begin(), pubkeys.end()); const std::vector vecMessagesBytes(messages.begin(), messages.end()); - return CoreMPL::AggregateVerify(vecPubKeyBytes, vecMessagesBytes, Bytes(signature)); + return CoreMPL::AggregateVerify( + vecPubKeyBytes, vecMessagesBytes, Bytes(signature)); } -bool CoreMPL::AggregateVerify(const vector& pubkeys, - const vector& messages, // unhashed - const Bytes& signature) +bool CoreMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, // unhashed + const Bytes& signature) { const size_t nPubKeys = pubkeys.size(); - const G2Element signatureElement = G2Element::FromBytes(signature); - const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signatureElement); + G2Element signatureElement; + try { + signatureElement = G2Element::FromBytes(signature); + } catch (...) { + return false; + } + const auto arg_check = VerifyAggregateSignatureArguments( + nPubKeys, messages.size(), signatureElement); if (arg_check != CONTINUE) { return arg_check; } vector pubkeyElements; pubkeyElements.reserve(nPubKeys); - for (size_t i = 0; i < nPubKeys; ++i) { - pubkeyElements.push_back(G1Element::FromBytes(pubkeys[i])); + try { + for (size_t i = 0; i < nPubKeys; ++i) { + pubkeyElements.push_back(G1Element::FromBytes(pubkeys[i])); + } + } catch (...) { + return false; } return CoreMPL::AggregateVerify(pubkeyElements, messages, signatureElement); } -bool CoreMPL::AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature) +bool CoreMPL::AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature) { - return CoreMPL::AggregateVerify(pubkeys, std::vector(messages.begin(), messages.end()), signature); + return CoreMPL::AggregateVerify( + pubkeys, + std::vector(messages.begin(), messages.end()), + signature); } -bool CoreMPL::AggregateVerify(const vector& pubkeys, - const vector &messages, - const G2Element& signature) +bool CoreMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature) { const size_t nPubKeys = pubkeys.size(); - const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); + const auto arg_check = + VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); if (arg_check != CONTINUE) { return arg_check; } - std::vector vecG1(nPubKeys + 1); - std::vector vecG2(nPubKeys + 1); - G1Element::Generator().Negate().ToNative(&vecG1[0]); - if (!signature.IsValid()) { + if (!signature.IsValid() || signature == G2Element()) { return false; } - signature.ToNative(&vecG2[0]); + std::vector vecG1; + std::vector vecG2; + vecG1.reserve(nPubKeys + 1); + vecG2.reserve(nPubKeys + 1); + vecG1.push_back(G1Element::Generator().Negate()); + vecG2.push_back(signature); for (size_t i = 0; i < nPubKeys; ++i) { - if (!pubkeys[i].IsValid()) { + if (!pubkeys[i].IsValid() || pubkeys[i] == G1Element()) { return false; } - pubkeys[i].ToNative(&vecG1[i + 1]); - G2Element::FromMessage(messages[i], (const uint8_t*)strCiphersuiteId.c_str(), strCiphersuiteId.length()).ToNative(&vecG2[i + 1]); + vecG1.push_back(pubkeys[i]); + vecG2.push_back(G2Element::FromMessage(messages[i], (const uint8_t*)strCiphersuiteId.c_str(), strCiphersuiteId.length())); } - return CoreMPL::NativeVerify((g1_t*)vecG1.data(), (g2_t*)vecG2.data(), nPubKeys + 1); + return CoreMPL::NativeVerify(vecG1, vecG2); } -bool CoreMPL::NativeVerify(g1_t *pubkeys, g2_t *mappedHashes, size_t length) +bool CoreMPL::NativeVerify(const std::vector& g1s, + const std::vector& g2s) { - gt_t target, candidate, tmpPairing; - fp12_zero(target); - fp_set_dig(target[0][0][0], 1); - fp12_zero(candidate); - fp_set_dig(candidate[0][0][0], 1); - - // prod e(pubkey[i], hash[i]) * e(-g1, aggSig) - // Performs pubKeys.size() pairings, 250 at a time - - for (size_t i = 0; i < length; i += 250) { - size_t numPairings = std::min((length - i), (size_t)250); - pc_map_sim(tmpPairing, pubkeys + i, mappedHashes + i, numPairings); - fp12_mul(candidate, candidate, tmpPairing); - } - - // 1 =? prod e(pubkey[i], hash[i]) * e(-g1, aggSig) - if (gt_cmp(target, candidate) != RLC_EQ || core_get()->code != RLC_OK) { - core_get()->code = RLC_OK; + // 1 =? prod e(g1s[i], g2s[i]) + // A pairing with the point at infinity on either side contributes the + // identity, matching relic's pc_map_sim. + if (g1s.size() != g2s.size()) { return false; } - BLS::CheckRelicErrors(); - return true; + std::vector ps; + std::vector qs; + ps.reserve(g1s.size()); + qs.reserve(g2s.size()); + for (size_t i = 0; i < g1s.size(); ++i) { + blst_p1 p; + blst_p2 q; + g1s[i].ToNative(&p); + g2s[i].ToNative(&q); + // Infinity is decided on the projective points: blst's affine form + // cannot tell (0, 0) apart from infinity. + if (blst_p1_is_inf(&p) || blst_p2_is_inf(&q)) { + continue; + } + blst_p1_to_affine(&ps.emplace_back(), &p); + blst_p2_to_affine(&qs.emplace_back(), &q); + } + + blst_fp12 candidate = *blst_fp12_one(); + if (!ps.empty()) { + // One shared Miller loop for all pairs, like relic's pc_map_sim. + std::vector pPtrs(ps.size()); + std::vector qPtrs(qs.size()); + for (size_t i = 0; i < ps.size(); ++i) { + pPtrs[i] = &ps[i]; + qPtrs[i] = &qs[i]; + } + blst_miller_loop_n(&candidate, qPtrs.data(), pPtrs.data(), ps.size()); + } + + blst_final_exp(&candidate, &candidate); + return blst_fp12_is_one(&candidate); } -PrivateKey CoreMPL::DeriveChildSk(const PrivateKey& sk, uint32_t index) { +PrivateKey CoreMPL::DeriveChildSk(const PrivateKey& sk, uint32_t index) +{ return HDKeys::DeriveChildSk(sk, index); } -PrivateKey CoreMPL::DeriveChildSkUnhardened(const PrivateKey& sk, uint32_t index) { +PrivateKey CoreMPL::DeriveChildSkUnhardened( + const PrivateKey& sk, + uint32_t index) +{ return HDKeys::DeriveChildSkUnhardened(sk, index); } -G1Element CoreMPL::DeriveChildPkUnhardened(const G1Element& pk, uint32_t index) { +G1Element CoreMPL::DeriveChildPkUnhardened(const G1Element& pk, uint32_t index) +{ return HDKeys::DeriveChildG1Unhardened(pk, index); } -bool BasicSchemeMPL::AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature) +bool BasicSchemeMPL::AggregateVerify( + const vector>& pubkeys, + const vector>& messages, + const vector& signature) { - const size_t nPubKeys = pubkeys.size(); - auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), G2Element::FromByteVector(signature)); - if (arg_check != CONTINUE) { - return arg_check; - } - - const std::set> setMessages(messages.begin(), messages.end()); - if (setMessages.size() != nPubKeys) { - return false; - } - return CoreMPL::AggregateVerify(pubkeys, messages, signature); + const std::vector vecPubKeyBytes(pubkeys.begin(), pubkeys.end()); + const std::vector vecMessagesBytes(messages.begin(), messages.end()); + return BasicSchemeMPL::AggregateVerify( + vecPubKeyBytes, vecMessagesBytes, Bytes(signature)); } -bool BasicSchemeMPL::AggregateVerify(const vector& pubkeys, - const vector& messages, - const Bytes& signature) +bool BasicSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, + const Bytes& signature) { const size_t nPubKeys = pubkeys.size(); - const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), G2Element::FromBytes(signature)); - if (arg_check != CONTINUE) return arg_check; + G2Element signatureElement; + try { + signatureElement = G2Element::FromBytes(signature); + } catch (...) { + return false; + } + const auto arg_check = VerifyAggregateSignatureArguments( + nPubKeys, messages.size(), signatureElement); + if (arg_check != CONTINUE) + return arg_check; std::set> setMessages; for (const auto& message : messages) { @@ -393,33 +468,49 @@ bool BasicSchemeMPL::AggregateVerify(const vector& pubkeys, if (setMessages.size() != nPubKeys) { return false; } - return CoreMPL::AggregateVerify(pubkeys, messages, signature); + + vector pubkeyElements; + pubkeyElements.reserve(nPubKeys); + try { + for (size_t i = 0; i < nPubKeys; ++i) { + pubkeyElements.push_back(G1Element::FromBytes(pubkeys[i])); + } + } catch (...) { + return false; + } + return CoreMPL::AggregateVerify(pubkeyElements, messages, signatureElement); } -bool BasicSchemeMPL::AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature) +bool BasicSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature) { const size_t nPubKeys = pubkeys.size(); - const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); + const auto arg_check = + VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); if (arg_check != CONTINUE) { return arg_check; } - const std::set> setMessages(messages.begin(), messages.end()); + const std::set> setMessages( + messages.begin(), messages.end()); if (setMessages.size() != nPubKeys) { return false; } return CoreMPL::AggregateVerify(pubkeys, messages, signature); } -bool BasicSchemeMPL::AggregateVerify(const vector& pubkeys, - const vector &messages, - const G2Element& signature) +bool BasicSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature) { const size_t nPubKeys = pubkeys.size(); - const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); - if (arg_check != CONTINUE) return arg_check; + const auto arg_check = + VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); + if (arg_check != CONTINUE) + return arg_check; std::set> setMessages; for (const auto& message : messages) { @@ -431,7 +522,9 @@ bool BasicSchemeMPL::AggregateVerify(const vector& pubkeys, return CoreMPL::AggregateVerify(pubkeys, messages, signature); } -G2Element AugSchemeMPL::Sign(const PrivateKey &seckey, const vector &message) +G2Element AugSchemeMPL::Sign( + const PrivateKey& seckey, + const vector& message) { return AugSchemeMPL::Sign(seckey, message, seckey.GetG1Element()); } @@ -442,17 +535,19 @@ G2Element AugSchemeMPL::Sign(const PrivateKey& seckey, const Bytes& message) } // Used for prepending different augMessage -G2Element AugSchemeMPL::Sign(const PrivateKey &seckey, - const vector &message, - const G1Element &prepend_pk) +G2Element AugSchemeMPL::Sign( + const PrivateKey& seckey, + const vector& message, + const G1Element& prepend_pk) { return AugSchemeMPL::Sign(seckey, Bytes(message), prepend_pk); } // Used for prepending different augMessage -G2Element AugSchemeMPL::Sign(const PrivateKey& seckey, - const Bytes& message, - const G1Element& prepend_pk) +G2Element AugSchemeMPL::Sign( + const PrivateKey& seckey, + const Bytes& message, + const G1Element& prepend_pk) { vector augMessage = prepend_pk.Serialize(); augMessage.reserve(augMessage.size() + message.size()); @@ -460,9 +555,10 @@ G2Element AugSchemeMPL::Sign(const PrivateKey& seckey, return CoreMPL::Sign(seckey, augMessage); } -bool AugSchemeMPL::Verify(const vector &pubkey, - const vector &message, - const vector &signature) +bool AugSchemeMPL::Verify( + const vector& pubkey, + const vector& message, + const vector& signature) { vector augMessage(pubkey); augMessage.reserve(augMessage.size() + message.size()); @@ -470,9 +566,10 @@ bool AugSchemeMPL::Verify(const vector &pubkey, return CoreMPL::Verify(pubkey, augMessage, signature); } -bool AugSchemeMPL::Verify(const Bytes& pubkey, - const Bytes& message, - const Bytes& signature) +bool AugSchemeMPL::Verify( + const Bytes& pubkey, + const Bytes& message, + const Bytes& signature) { vector augMessage(pubkey.begin(), pubkey.end()); augMessage.reserve(augMessage.size() + message.size()); @@ -480,16 +577,18 @@ bool AugSchemeMPL::Verify(const Bytes& pubkey, return CoreMPL::Verify(pubkey, Bytes(augMessage), Bytes(signature)); } -bool AugSchemeMPL::Verify(const G1Element &pubkey, - const vector &message, - const G2Element &signature) +bool AugSchemeMPL::Verify( + const G1Element& pubkey, + const vector& message, + const G2Element& signature) { return AugSchemeMPL::Verify(pubkey, Bytes(message), signature); } -bool AugSchemeMPL::Verify(const G1Element& pubkey, - const Bytes& message, - const G2Element& signature) +bool AugSchemeMPL::Verify( + const G1Element& pubkey, + const Bytes& message, + const G2Element& signature) { vector augMessage = pubkey.Serialize(); augMessage.reserve(augMessage.size() + message.size()); @@ -497,21 +596,31 @@ bool AugSchemeMPL::Verify(const G1Element& pubkey, return CoreMPL::Verify(pubkey, augMessage, signature); } -bool AugSchemeMPL::AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature) +bool AugSchemeMPL::AggregateVerify( + const vector>& pubkeys, + const vector>& messages, + const vector& signature) { std::vector vecPubKeyBytes(pubkeys.begin(), pubkeys.end()); std::vector vecMessagesBytes(messages.begin(), messages.end()); - return AugSchemeMPL::AggregateVerify(vecPubKeyBytes, vecMessagesBytes, Bytes(signature)); + return AugSchemeMPL::AggregateVerify( + vecPubKeyBytes, vecMessagesBytes, Bytes(signature)); } -bool AugSchemeMPL::AggregateVerify(const vector& pubkeys, - const vector& messages, - const Bytes& signature) +bool AugSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, + const Bytes& signature) { size_t nPubKeys = pubkeys.size(); - auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), G2Element::FromBytes(signature)); + G2Element signatureElement; + try { + signatureElement = G2Element::FromBytes(signature); + } catch (...) { + return false; + } + auto arg_check = VerifyAggregateSignatureArguments( + nPubKeys, messages.size(), signatureElement); if (arg_check != CONTINUE) { return arg_check; } @@ -524,30 +633,34 @@ bool AugSchemeMPL::AggregateVerify(const vector& pubkeys, aug.insert(aug.end(), messages[i].begin(), messages[i].end()); } - std::vector vecAugMessageBytes(augMessages.begin(), augMessages.end()); + std::vector vecAugMessageBytes( + augMessages.begin(), augMessages.end()); return CoreMPL::AggregateVerify(pubkeys, vecAugMessageBytes, signature); } -bool AugSchemeMPL::AggregateVerify(const vector& pubkeys, - const vector>& messages, - const G2Element& signature) +bool AugSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature) { std::vector vecMessagesBytes(messages.begin(), messages.end()); return AugSchemeMPL::AggregateVerify(pubkeys, vecMessagesBytes, signature); } -bool AugSchemeMPL::AggregateVerify(const vector& pubkeys, - const vector& messages, - const G2Element& signature) +bool AugSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature) { size_t nPubKeys = pubkeys.size(); - auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); + auto arg_check = + VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); if (arg_check != CONTINUE) { return arg_check; } vector> augMessages(nPubKeys); - for (int i = 0; i < nPubKeys; ++i) { + for (size_t i = 0; i < nPubKeys; ++i) { vector& aug = augMessages[i]; vector&& pubkey = pubkeys[i].Serialize(); aug.reserve(pubkey.size() + messages[i].size()); @@ -558,84 +671,142 @@ bool AugSchemeMPL::AggregateVerify(const vector& pubkeys, return CoreMPL::AggregateVerify(pubkeys, augMessages, signature); } -G2Element PopSchemeMPL::PopProve(const PrivateKey &seckey) -{ - const G1Element& pk = seckey.GetG1Element(); - const G2Element hashedKey = G2Element::FromMessage(pk.SerializeToArray(), (const uint8_t *)POP_CIPHERSUITE_ID.c_str(), POP_CIPHERSUITE_ID.length()); - return seckey.GetG2Power(hashedKey); -} +bool AugSchemeMPL::VerifySecure(const std::vector& vecPublicKeys, + const G2Element& signature, + const Bytes& message) { + // AugSchemeMPL::Sign hashes H(pk_i || msg) per signer. We cannot + // combine into a single pubkey because each signer's hash is different. + // Instead, pass T-weighted individual pubkeys with their augmented + // messages to CoreMPL::AggregateVerify. + for (const auto& pk : vecPublicKeys) { + if (!pk.IsValid() || pk == G1Element()) { + return false; + } + } + if (!signature.IsValid() || signature == G2Element()) { + return false; + } + std::vector computedTs(vecPublicKeys.size()); + std::vector> vecSorted(vecPublicKeys.size()); + for (size_t i = 0; i < vecPublicKeys.size(); i++) { + vecSorted[i] = vecPublicKeys[i].SerializeToArray(false); + } + std::sort(vecSorted.begin(), vecSorted.end(), [](const auto& a, const auto& b) -> bool { + return std::memcmp(a.data(), b.data(), G1Element::SIZE) < 0; + }); + + HashPubKeys(computedTs.data(), vecSorted.size(), + [&](size_t i) { return vecSorted[i].data(); }); + + std::vector weightedPks(vecSorted.size()); + std::vector> augMessages(vecSorted.size()); + for (size_t i = 0; i < vecSorted.size(); ++i) { + G1Element g1 = G1Element::FromBytes(Bytes(vecSorted[i]), false); + weightedPks[i] = g1 * computedTs[i]; + augMessages[i].reserve(G1Element::SIZE + message.size()); + augMessages[i].insert(augMessages[i].end(), vecSorted[i].begin(), vecSorted[i].end()); + augMessages[i].insert(augMessages[i].end(), message.begin(), message.end()); + } + + return CoreMPL::AggregateVerify(weightedPks, augMessages, signature); +} -bool PopSchemeMPL::PopVerify(const G1Element &pubkey, const G2Element &signature_proof) +G2Element PopSchemeMPL::PopProve(const PrivateKey& seckey) { - const G2Element hashedPoint = G2Element::FromMessage(pubkey.SerializeToArray(), (const uint8_t*)POP_CIPHERSUITE_ID.c_str(), POP_CIPHERSUITE_ID.length()); + std::array pubkey_bytes = seckey.GetG1Element().SerializeToArray(); - g1_t g1s[2]; - g2_t g2s[2]; + return seckey.SignG2( + pubkey_bytes.data(), + pubkey_bytes.size(), + (const uint8_t*)POP_CIPHERSUITE_ID.c_str(), + POP_CIPHERSUITE_ID.length()); +} - if (!pubkey.IsValid()) { +bool PopSchemeMPL::PopVerify( + const G1Element& pubkey, + const G2Element& signature_proof) +{ + // Same semantics as CoreMPL::Verify (and the relic implementation): the + // elements are gated by IsValid() and the check is the product of + // pairings rather than blst_core_verify. + if (!pubkey.IsValid() || pubkey == G1Element()) { return false; } - if (!signature_proof.IsValid()) { + if (!signature_proof.IsValid() || signature_proof == G2Element()) { return false; } - G1Element::Generator().Negate().ToNative(g1s[0]); - pubkey.ToNative(g1s[1]); - signature_proof.ToNative(g2s[0]); - hashedPoint.ToNative(g2s[1]); - - return CoreMPL::NativeVerify(g1s, g2s, 2); + const std::array pubkey_bytes = pubkey.SerializeToArray(); + const G2Element hashedPoint = G2Element::FromMessage(Bytes(pubkey_bytes), (const uint8_t*)POP_CIPHERSUITE_ID.c_str(), POP_CIPHERSUITE_ID.length()); + const std::vector g1s{G1Element::Generator().Negate(), pubkey}; + const std::vector g2s{signature_proof, hashedPoint}; + return CoreMPL::NativeVerify(g1s, g2s); } -bool PopSchemeMPL::PopVerify(const vector &pubkey, const vector &proof) +bool PopSchemeMPL::PopVerify( + const vector& pubkey, + const vector& proof) { return PopSchemeMPL::PopVerify(Bytes(pubkey), Bytes(proof)); } bool PopSchemeMPL::PopVerify(const Bytes& pubkey, const Bytes& proof) { - const G2Element hashedPoint = G2Element::FromMessage(pubkey, (const uint8_t*)POP_CIPHERSUITE_ID.c_str(), POP_CIPHERSUITE_ID.length()); - - g1_t g1s[2]; - g2_t g2s[2]; - - G1Element::Generator().Negate().ToNative(g1s[0]); - G1Element::FromBytes(pubkey).ToNative(g1s[1]); - G2Element::FromBytes(proof).ToNative(g2s[0]); - hashedPoint.ToNative(g2s[1]); - - return CoreMPL::NativeVerify(g1s, g2s, 2); + G1Element pk; + G2Element proofElement; + try { + pk = G1Element::FromBytes(pubkey); + proofElement = G2Element::FromBytes(proof); + } catch (...) { + return false; + } + return PopSchemeMPL::PopVerify(pk, proofElement); } -bool PopSchemeMPL::FastAggregateVerify(const vector &pubkeys, - const vector &message, - const G2Element &signature) +bool PopSchemeMPL::FastAggregateVerify( + const vector& pubkeys, + const vector& message, + const G2Element& signature) { - return PopSchemeMPL::FastAggregateVerify(pubkeys, Bytes(message), signature); + return PopSchemeMPL::FastAggregateVerify( + pubkeys, Bytes(message), signature); } -bool PopSchemeMPL::FastAggregateVerify(const vector& pubkeys, - const Bytes& message, - const G2Element& signature) +bool PopSchemeMPL::FastAggregateVerify( + const vector& pubkeys, + const Bytes& message, + const G2Element& signature) { if (pubkeys.size() == 0) { return false; } - // No VerifyAggregateSignatureArguments checks required here as we have exactly one pubkey and one message. + if (!signature.IsValid() || signature == G2Element()) { + return false; + } + for (const auto& pk : pubkeys) { + if (!pk.IsValid() || pk == G1Element()) { + return false; + } + } + // No VerifyAggregateSignatureArguments checks required here as we have + // exactly one pubkey and one message. return CoreMPL::Verify(CoreMPL::Aggregate(pubkeys), message, signature); } -bool PopSchemeMPL::FastAggregateVerify(const vector> &pubkeys, - const vector &message, - const vector &signature) +bool PopSchemeMPL::FastAggregateVerify( + const vector>& pubkeys, + const vector& message, + const vector& signature) { const std::vector vecPubKeyBytes(pubkeys.begin(), pubkeys.end()); - return PopSchemeMPL::FastAggregateVerify(vecPubKeyBytes, Bytes(message), Bytes(signature)); + return PopSchemeMPL::FastAggregateVerify( + vecPubKeyBytes, Bytes(message), Bytes(signature)); } -bool PopSchemeMPL::FastAggregateVerify(const vector& pubkeys, - const Bytes& message, - const Bytes& signature) +bool PopSchemeMPL::FastAggregateVerify( + const vector& pubkeys, + const Bytes& message, + const Bytes& signature) { const size_t nPubKeys = pubkeys.size(); if (nPubKeys == 0) { @@ -643,11 +814,18 @@ bool PopSchemeMPL::FastAggregateVerify(const vector& pubkeys, } vector pkelements; - for (size_t i = 0; i < nPubKeys; ++i) { - pkelements.push_back(G1Element::FromBytes(pubkeys[i])); + G2Element signatureElement; + try { + for (size_t i = 0; i < nPubKeys; ++i) { + pkelements.push_back(G1Element::FromBytes(pubkeys[i])); + } + signatureElement = G2Element::FromBytes(signature); + } catch (...) { + return false; } - return PopSchemeMPL::FastAggregateVerify(pkelements, message, G2Element::FromBytes(signature)); + return PopSchemeMPL::FastAggregateVerify( + pkelements, message, signatureElement); } G2Element LegacySchemeMPL::Sign(const PrivateKey& seckey, const Bytes& message) @@ -657,15 +835,19 @@ G2Element LegacySchemeMPL::Sign(const PrivateKey& seckey, const Bytes& message) bool LegacySchemeMPL::Verify(const G1Element &pubkey, const Bytes& message, const G2Element &signature) { - g1_t g1s[2]; - g2_t g2s[2]; - - G1Element::Generator().Negate().ToNative(g1s[0]); - pubkey.ToNative(g1s[1]); - signature.ToNative(g2s[0]); - G2Element::FromMessage(message, nullptr, 0, true).ToNative(g2s[1]); - - return CoreMPL::NativeVerify(g1s, g2s, 2); + // the legacy scheme is defined on 32-byte message hashes + if (message.size() != BLS::MESSAGE_HASH_LEN) { + return false; + } + if (!pubkey.IsValid() || pubkey == G1Element()) { + return false; + } + if (!signature.IsValid() || signature == G2Element()) { + return false; + } + const std::vector g1s{G1Element::Generator().Negate(), pubkey}; + const std::vector g2s{signature, G2Element::FromMessage(message, nullptr, 0, true)}; + return CoreMPL::NativeVerify(g1s, g2s); } G2Element LegacySchemeMPL::AggregateSecure(std::vector const &vecPublicKeys, @@ -688,17 +870,27 @@ bool LegacySchemeMPL::AggregateVerify(const vector &pubkeys, const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); if (arg_check != CONTINUE) return arg_check; - std::vector vecG1(nPubKeys + 1); - std::vector vecG2(nPubKeys + 1); - G1Element::Generator().Negate().ToNative(&vecG1[0]); - signature.ToNative(&vecG2[0]); - + if (!signature.IsValid() || signature == G2Element()) { + return false; + } + std::vector vecG1; + std::vector vecG2; + vecG1.reserve(nPubKeys + 1); + vecG2.reserve(nPubKeys + 1); + vecG1.push_back(G1Element::Generator().Negate()); + vecG2.push_back(signature); for (size_t i = 0; i < nPubKeys; ++i) { - pubkeys[i].ToNative(&vecG1[i + 1]); - G2Element::FromMessage(messages[i], nullptr, 0, true).ToNative(&vecG2[i + 1]); + // the legacy scheme is defined on 32-byte message hashes + if (messages[i].size() != BLS::MESSAGE_HASH_LEN) { + return false; + } + if (!pubkeys[i].IsValid() || pubkeys[i] == G1Element()) { + return false; + } + vecG1.push_back(pubkeys[i]); + vecG2.push_back(G2Element::FromMessage(messages[i], nullptr, 0, true)); } - - return CoreMPL::NativeVerify((g1_t*)vecG1.data(), (g2_t*)vecG2.data(), nPubKeys + 1); + return CoreMPL::NativeVerify(vecG1, vecG2); } } // end namespace bls diff --git a/src/dashbls/src/test-bench.cpp b/src/dashbls/src/test-bench.cpp index 20bbbb443952..0cc476790624 100644 --- a/src/dashbls/src/test-bench.cpp +++ b/src/dashbls/src/test-bench.cpp @@ -13,22 +13,27 @@ // limitations under the License. #include + #include "bls.hpp" #include "test-utils.hpp" -extern "C" { -#include "relic.h" -} - using std::string; using std::vector; -using std::cout; -using std::endl; using namespace bls; +std::vector wjbgetRandomSeed() +{ + uint8_t buf[32]; + + for (int i = 0; i < 32; i++) buf[i] = rand(); -void benchSigs() { + std::vector ret(buf, buf + 32); + return ret; +} + +void benchSigs() +{ string testName = "Signing"; const int numIters = 5000; PrivateKey sk = BasicSchemeMPL().KeyGen(getRandomSeed()); @@ -42,21 +47,22 @@ void benchSigs() { endStopwatch(testName, start, numIters); } -void benchVerification() { +void benchVerification() +{ string testName = "Verification"; const int numIters = 1000; PrivateKey sk = BasicSchemeMPL().KeyGen(getRandomSeed()); G1Element pk = sk.GetG1Element(); - std::vector sigs; + vector pkBytes = pk.Serialize(); for (int i = 0; i < numIters; i++) { uint8_t message[4]; Util::IntToFourBytes(message, i); vector messageBytes(message, message + 4); - sigs.push_back(BasicSchemeMPL().Sign(sk, messageBytes)); + G2Element sig = BasicSchemeMPL().Sign(sk, messageBytes); + sigs.push_back(sig); } - auto start = startStopwatch(); for (int i = 0; i < numIters; i++) { uint8_t message[4]; @@ -68,7 +74,8 @@ void benchVerification() { endStopwatch(testName, start, numIters); } -void benchBatchVerification() { +void benchBatchVerification() +{ const int numIters = 10000; vector> sig_bytes; @@ -116,7 +123,8 @@ void benchBatchVerification() { endStopwatch("Batch verification", start, numIters); } -void benchSerialize() { +void benchSerialize() +{ const int numIters = 5000000; PrivateKey sk = BasicSchemeMPL().KeyGen(getRandomSeed()); G1Element pk = sk.GetG1Element(); @@ -142,7 +150,8 @@ void benchSerialize() { endStopwatch("Serialize G2Element", start, numIters); } -void benchSerializeToArray() { +void benchSerializeToArray() +{ const int numIters = 5000000; PrivateKey sk = BasicSchemeMPL().KeyGen(getRandomSeed()); G1Element pk = sk.GetG1Element(); @@ -168,7 +177,8 @@ void benchSerializeToArray() { endStopwatch("SerializeToArray G2Element", start, numIters); } -int main(int argc, char* argv[]) { +int main() +{ benchSigs(); benchVerification(); benchBatchVerification(); diff --git a/src/dashbls/src/test-vectors.hpp b/src/dashbls/src/test-vectors.hpp new file mode 100644 index 000000000000..430d7ec877e5 --- /dev/null +++ b/src/dashbls/src/test-vectors.hpp @@ -0,0 +1,575 @@ +// Copyright (c) 2026 The Dash Core developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef SRC_TEST_VECTORS_HPP_ +#define SRC_TEST_VECTORS_HPP_ + +// Reference consensus vectors. +// +// GenerateReferenceVectors() deterministically exercises the public dashbls +// API - legacy and basic serialization (including malformed input), legacy +// signing, secure aggregation, threshold signing, extended keys and the +// private key edge cases - and emits one "name=value" line per result. +// +// test-vectors/reference.txt holds the output of the relic-based library; +// runtest compares the current library against it line by line, and +// tools/vectorgen.cpp regenerates it. Only the public API is used so the +// same code builds against any backend. + +#include +#include +#include +#include +#include +#include + +#include "bls.hpp" + +namespace bls_test_vectors { + +using namespace bls; +using std::vector; + +struct Emitter { + std::vector lines; + + static std::string hex(const uint8_t* p, size_t n) + { + static const char* digits = "0123456789abcdef"; + std::string s; + s.reserve(n * 2); + for (size_t i = 0; i < n; i++) { + s.push_back(digits[p[i] >> 4]); + s.push_back(digits[p[i] & 0x0f]); + } + return s; + } + + void raw(const std::string& line) { lines.push_back(line); } + void dump(const std::string& name, const vector& v) { lines.push_back(name + "=" + hex(v.data(), v.size())); } + template + void dump(const std::string& name, const std::array& v) { lines.push_back(name + "=" + hex(v.data(), N)); } + void dumpb(const std::string& name, bool v) { lines.push_back(name + "=" + (v ? "1" : "0")); } + void dumpu(const std::string& name, uint32_t v) + { + char buf[16]; + snprintf(buf, sizeof(buf), "%08x", v); + lines.push_back(name + "=" + buf); + } + void exc(const std::string& name) { lines.push_back(name + "=EXC"); } +}; + +inline vector seedN(int i) +{ + vector s(32); + for (int j = 0; j < 32; j++) s[j] = (uint8_t)(0x11 * (i + 1) + j * 7); + return s; +} + +inline vector hashN(int i) +{ + vector h(32); + for (int j = 0; j < 32; j++) h[j] = (uint8_t)(0xA5 ^ (i * 31 + j * 13)); + return h; +} + +inline std::string tag(const char* base, int i) +{ + char buf[96]; + snprintf(buf, sizeof(buf), "%s.%d", base, i); + return std::string(buf); +} + +// ---------------------------------------------------------------- section A/B +inline void KeysAndSignatures(Emitter& e) +{ + LegacySchemeMPL legacy; + BasicSchemeMPL basic; + + for (int i = 0; i < 8; i++) { + PrivateKey sk = basic.KeyGen(seedN(i)); + e.dump(tag("A.sk", i), sk.Serialize()); + + G1Element pk = sk.GetG1Element(); + e.dump(tag("A.pk.basic", i), pk.Serialize(false)); + e.dump(tag("A.pk.legacy", i), pk.Serialize(true)); + e.dumpu(tag("A.fp.basic", i), pk.GetFingerprint(false)); + e.dumpu(tag("A.fp.legacy", i), pk.GetFingerprint(true)); + e.dump(tag("A.skG2.basic", i), sk.GetG2Element().Serialize(false)); + e.dump(tag("A.skG2.legacy", i), sk.GetG2Element().Serialize(true)); + + // round-trips through both codecs + e.dump(tag("A.pk.rt.legacy", i), + G1Element::FromBytes(Bytes(pk.Serialize(true)), true).Serialize(true)); + e.dump(tag("A.pk.rt.basic", i), + G1Element::FromBytes(Bytes(pk.Serialize(false)), false).Serialize(false)); + + // legacy sign over a 32-byte hash; serialize under both codecs + vector h = hashN(i); + G2Element lsig = legacy.Sign(sk, Bytes(h)); + e.dump(tag("B.lsig.legacy", i), lsig.Serialize(true)); + e.dump(tag("B.lsig.basic", i), lsig.Serialize(false)); + e.dumpb(tag("B.lverify", i), legacy.Verify(pk, Bytes(h), lsig)); + // wrong message must fail + vector h2 = hashN(i + 100); + e.dumpb(tag("B.lverify.bad", i), legacy.Verify(pk, Bytes(h2), lsig)); + // legacy sig round-trip through legacy codec + e.dump(tag("B.lsig.rt", i), + G2Element::FromBytes(Bytes(lsig.Serialize(true)), true).Serialize(true)); + + // basic scheme (arbitrary-length message) + vector msg = {(uint8_t)i, 1, 2, 3, 200, 255}; + G2Element bsig = basic.Sign(sk, msg); + e.dump(tag("B.bsig.basic", i), bsig.Serialize(false)); + e.dump(tag("B.bsig.legacy", i), bsig.Serialize(true)); + e.dumpb(tag("B.bverify", i), basic.Verify(pk, msg, bsig)); + + // EIP-2333 derivation + e.dump(tag("A.child.hard", i), basic.DeriveChildSk(sk, 0x8000002a).Serialize()); + e.dump(tag("A.child.soft", i), basic.DeriveChildSkUnhardened(sk, 1337).Serialize()); + } +} + +// ---------------------------------------------------------------- section C/D +inline void SecureAggregation(Emitter& e) +{ + LegacySchemeMPL legacy; + BasicSchemeMPL basic; + + for (int n : {1, 2, 3, 10}) { + vector sks; + vector pks; + vector lsigs, bsigs; + vector h = hashN(n); + for (int i = 0; i < n; i++) { + sks.push_back(basic.KeyGen(seedN(200 + n * 16 + i))); + pks.push_back(sks.back().GetG1Element()); + lsigs.push_back(legacy.Sign(sks.back(), Bytes(h))); + bsigs.push_back(basic.Sign(sks.back(), Bytes(h))); + } + G2Element lagg = legacy.AggregateSecure(pks, lsigs, Bytes(h)); + e.dump(tag("C.aggsec.legacy", n), lagg.Serialize(true)); + e.dumpb(tag("C.versec.legacy", n), legacy.VerifySecure(pks, lagg, Bytes(h))); + + G2Element bagg = basic.AggregateSecure(pks, bsigs, Bytes(h)); + e.dump(tag("C.aggsec.basic", n), bagg.Serialize(false)); + e.dumpb(tag("C.versec.basic", n), basic.VerifySecure(pks, bagg, Bytes(h))); + + // cross checks must fail + e.dumpb(tag("C.versec.legacy.bad", n), + legacy.VerifySecure(pks, lagg, Bytes(hashN(n + 50)))); + + // plain aggregation + e.dump(tag("C.agg.G2", n), basic.Aggregate(bsigs).Serialize(false)); + e.dump(tag("C.agg.G1", n), basic.Aggregate(pks).Serialize(false)); + e.dump(tag("C.agg.sk", n), PrivateKey::Aggregate(sks).Serialize()); + } + + // legacy multi-message AggregateVerify + { + int n = 4; + vector sks; + vector pks; + vector sigs; + vector> msgs; + for (int i = 0; i < n; i++) { + sks.push_back(basic.KeyGen(seedN(300 + i))); + pks.push_back(sks.back().GetG1Element()); + msgs.push_back(hashN(300 + i)); + sigs.push_back(legacy.Sign(sks.back(), Bytes(msgs.back()))); + } + G2Element agg = basic.Aggregate(sigs); // plain point sum + vector msgRefs; + for (auto& m : msgs) msgRefs.push_back(Bytes(m)); + e.dump("D.lagg", agg.Serialize(true)); + e.dumpb("D.laggverify", legacy.AggregateVerify(pks, msgRefs, agg)); + vector badRefs; + badRefs.push_back(Bytes(msgs[1])); + for (size_t i = 1; i < msgs.size(); i++) badRefs.push_back(Bytes(msgs[i])); + e.dumpb("D.laggverify.bad", legacy.AggregateVerify(pks, badRefs, agg)); + } +} + +// ------------------------------------------------------------------ section E +inline void ThresholdVectors(Emitter& e) +{ + BasicSchemeMPL basic; + const int m = 3, n = 5; + + // polynomial coefficients (the "master" keys) + vector coeffs; + vector vvec; + vector sigCoeffs; + vector h = hashN(77); + for (int i = 0; i < m; i++) { + coeffs.push_back(basic.KeyGen(seedN(400 + i))); + vvec.push_back(coeffs.back().GetG1Element()); + sigCoeffs.push_back(Threshold::Sign(coeffs[i], Bytes(h))); + } + e.dump("E.mastersig", Threshold::Sign(coeffs[0], Bytes(h)).Serialize(true)); + e.dumpb("E.masterverify", + Threshold::Verify(vvec[0], Bytes(h), Threshold::Sign(coeffs[0], Bytes(h)))); + + vector> ids; + for (int i = 0; i < n; i++) ids.push_back(hashN(500 + i)); + + vector skShares; + vector sigShares; + for (int i = 0; i < n; i++) { + PrivateKey sh = Threshold::PrivateKeyShare(coeffs, Bytes(ids[i])); + skShares.push_back(sh); + e.dump(tag("E.skshare", i), sh.Serialize()); + G1Element pkShare = Threshold::PublicKeyShare(vvec, Bytes(ids[i])); + e.dump(tag("E.pkshare", i), pkShare.Serialize(true)); + e.dumpb(tag("E.sharematch", i), pkShare == sh.GetG1Element()); + G2Element sigShare = Threshold::SignatureShare(sigCoeffs, Bytes(ids[i])); + e.dump(tag("E.sigshare.poly", i), sigShare.Serialize(true)); + G2Element sigShare2 = Threshold::Sign(sh, Bytes(h)); + e.dump(tag("E.sigshare.sign", i), sigShare2.Serialize(true)); + sigShares.push_back(sigShare2); + } + + // recover from first m shares + vector mSk(skShares.begin(), skShares.begin() + m); + vector mSig(sigShares.begin(), sigShares.begin() + m); + vector mIds; + for (int i = 0; i < m; i++) mIds.push_back(Bytes(ids[i])); + + PrivateKey skRec = Threshold::PrivateKeyRecover(mSk, mIds); + e.dump("E.skrecover", skRec.Serialize()); + e.dumpb("E.skrecover.match", skRec == coeffs[0]); + + vector mPk; + for (int i = 0; i < m; i++) mPk.push_back(skShares[i].GetG1Element()); + e.dump("E.pkrecover", Threshold::PublicKeyRecover(mPk, mIds).Serialize(true)); + + G2Element sigRec = Threshold::SignatureRecover(mSig, mIds); + e.dump("E.sigrecover", sigRec.Serialize(true)); + e.dumpb("E.sigrecover.verify", Threshold::Verify(vvec[0], Bytes(h), sigRec)); + + // recovery from a different share subset must give the same signature + vector mSig2(sigShares.begin() + 1, sigShares.begin() + 1 + m); + vector mIds2; + for (int i = 1; i < 1 + m; i++) mIds2.push_back(Bytes(ids[i])); + e.dumpb("E.sigrecover.same", + Threshold::SignatureRecover(mSig2, mIds2) == sigRec); +} + +// ------------------------------------------------------------------ section F +inline void ExtendedKeys(Emitter& e) +{ + vector seed = seedN(600); + ExtendedPrivateKey esk = ExtendedPrivateKey::FromSeed(Bytes(seed)); + e.dump("F.esk", esk.Serialize()); + e.dump("F.esk.pk.legacy", esk.GetPublicKey().Serialize(true)); + e.dump("F.esk.pk.basic", esk.GetPublicKey().Serialize(false)); + e.dump("F.esk.chaincode", esk.GetChainCode().Serialize()); + + // legacy derivation chain (fLegacy defaults true on these APIs) + ExtendedPrivateKey c1l = esk.PrivateChild(1, true); + ExtendedPrivateKey c2l = c1l.PrivateChild(0x8000002a, true); + e.dump("F.child.legacy", c2l.Serialize()); + e.dump("F.child.legacy.sk", c2l.GetPrivateKey().Serialize()); + + // modern derivation chain + ExtendedPrivateKey c1b = esk.PrivateChild(1, false); + ExtendedPrivateKey c2b = c1b.PrivateChild(0x8000002a, false); + e.dump("F.child.basic", c2b.Serialize()); + e.dump("F.child.basic.sk", c2b.GetPrivateKey().Serialize()); + + // extended public keys and public derivation + ExtendedPublicKey epkl = esk.GetExtendedPublicKey(true); + e.dump("F.epk.legacy", epkl.Serialize(true)); + ExtendedPublicKey epkb = esk.GetExtendedPublicKey(false); + e.dump("F.epk.basic", epkb.Serialize(false)); + e.dump("F.epk.child.legacy", epkl.PublicChild(1, true).Serialize(true)); + e.dump("F.epk.child.basic", epkb.PublicChild(1, false).Serialize(false)); + e.dumpb("F.pubpriv.match.legacy", + epkl.PublicChild(1, true).GetPublicKey() == + esk.PrivateChild(1, true).GetPublicKey()); + + // round-trips + e.dump("F.esk.rt", + ExtendedPrivateKey::FromBytes(Bytes(esk.Serialize())).Serialize()); + e.dump("F.epk.rt.legacy", + ExtendedPublicKey::FromBytes(Bytes(epkl.Serialize(true)), true).Serialize(true)); +} + +// ------------------------------------------------------------------ section G +inline void PrivateKeyEdges(Emitter& e) +{ + // in-range key round-trip, both modOrder values + PrivateKey sk = BasicSchemeMPL().KeyGen(seedN(700)); + vector raw = sk.Serialize(); + e.dump("G.inrange.mod0", PrivateKey::FromBytes(Bytes(raw), false).Serialize()); + e.dump("G.inrange.mod1", PrivateKey::FromBytes(Bytes(raw), true).Serialize()); + + // value >= group order: modOrder=true reduces, modOrder=false throws + vector big(32, 0xff); + try { e.dump("G.big.mod1", PrivateKey::FromBytes(Bytes(big), true).Serialize()); } + catch (const std::exception&) { e.exc("G.big.mod1"); } + try { e.dump("G.big.mod0", PrivateKey::FromBytes(Bytes(big), false).Serialize()); } + catch (const std::exception&) { e.exc("G.big.mod0"); } + + // the group order itself, and order-1 + // r = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 + vector order = { + 0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48, 0x33, 0x39, 0xd8, + 0x08, 0x09, 0xa1, 0xd8, 0x05, 0x53, 0xbd, 0xa4, 0x02, 0xff, 0xfe, + 0x5b, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01}; + try { e.dump("G.order.mod1", PrivateKey::FromBytes(Bytes(order), true).Serialize()); } + catch (const std::exception&) { e.exc("G.order.mod1"); } + try { e.dump("G.order.mod0", PrivateKey::FromBytes(Bytes(order), false).Serialize()); } + catch (const std::exception&) { e.exc("G.order.mod0"); } + vector orderm1 = order; + orderm1[31] = 0x00; + try { e.dump("G.orderm1.mod0", PrivateKey::FromBytes(Bytes(orderm1), false).Serialize()); } + catch (const std::exception&) { e.exc("G.orderm1.mod0"); } + + // zero key + vector zero(32, 0x00); + try { + PrivateKey z = PrivateKey::FromBytes(Bytes(zero), false); + e.dump("G.zero.sk", z.Serialize()); + e.dump("G.zero.pk", z.GetG1Element().Serialize(false)); + } catch (const std::exception&) { e.exc("G.zero.sk"); } + + // FromSeedBIP32 + e.dump("G.bip32seed", PrivateKey::FromSeedBIP32(Bytes(seedN(701))).Serialize()); + + // DH key exchange: sk_a * pk_b == sk_b * pk_a + PrivateKey a = BasicSchemeMPL().KeyGen(seedN(702)); + PrivateKey b = BasicSchemeMPL().KeyGen(seedN(703)); + G1Element dh = a * b.GetG1Element(); + e.dump("G.dh", dh.Serialize(false)); + e.dumpb("G.dh.sym", dh == (b * a.GetG1Element())); +} + +// ------------------------------------------------------------------ section H +// Crafted byte strings through every decode path. For each: either the +// round-trip hex (proving accept + canonical re-encoding) or EXC. +inline void decodeProbe(Emitter& e, const std::string& name, const vector& in, bool fLegacy) +{ + bool isG1 = in.size() == 48; + try { + if (isG1) { + G1Element el = G1Element::FromBytes(Bytes(in), fLegacy); + e.dump(name + ".ser", el.Serialize(fLegacy)); + e.dumpb(name + ".valid", el.IsValid()); + } else { + G2Element el = G2Element::FromBytes(Bytes(in), fLegacy); + e.dump(name + ".ser", el.Serialize(fLegacy)); + e.dumpb(name + ".valid", el.IsValid()); + } + } catch (const std::exception&) { e.exc(name); } +} + +inline void decodeProbeUnchecked(Emitter& e, const std::string& name, const vector& in, bool fLegacy) +{ + bool isG1 = in.size() == 48; + try { + if (isG1) { + G1Element el = G1Element::FromBytesUnchecked(Bytes(in), fLegacy); + e.dump(name + ".ser", el.Serialize(fLegacy)); + e.dumpb(name + ".valid", el.IsValid()); + } else { + G2Element el = G2Element::FromBytesUnchecked(Bytes(in), fLegacy); + e.dump(name + ".ser", el.Serialize(fLegacy)); + e.dumpb(name + ".valid", el.IsValid()); + } + } catch (const std::exception&) { e.exc(name); } +} + +inline vector fromHex(const char* hex) +{ + vector out; + for (size_t i = 0; hex[i] && hex[i + 1]; i += 2) { + auto nyb = [](char c) -> int { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + return c - 'A' + 10; + }; + out.push_back((uint8_t)((nyb(hex[i]) << 4) | nyb(hex[i + 1]))); + } + return out; +} + +inline void EdgeDecodes(Emitter& e) +{ + BasicSchemeMPL basic; + PrivateKey sk = basic.KeyGen(seedN(800)); + G1Element pk = sk.GetG1Element(); + G2Element sig = LegacySchemeMPL().Sign(sk, Bytes(hashN(800))); + + // 1. canonical infinity, both sizes, both modes + vector inf48(48, 0); + inf48[0] = 0xc0; + vector inf96(96, 0); + inf96[0] = 0xc0; + decodeProbe(e, "H.g1.inf.basic", inf48, false); + decodeProbe(e, "H.g1.inf.legacy", inf48, true); + decodeProbe(e, "H.g2.inf.basic", inf96, false); + decodeProbe(e, "H.g2.inf.legacy", inf96, true); + + // 2. non-canonical infinity (0xc0 with a trailing nonzero byte) + vector badInf48 = inf48; + badInf48[47] = 0x01; + vector badInf96 = inf96; + badInf96[95] = 0x01; + decodeProbe(e, "H.g1.badinf.basic", badInf48, false); + decodeProbe(e, "H.g1.badinf.legacy", badInf48, true); + decodeProbe(e, "H.g2.badinf.basic", badInf96, false); + decodeProbe(e, "H.g2.badinf.legacy", badInf96, true); + + // 3. all zeros + decodeProbe(e, "H.g1.zeros.basic", vector(48, 0), false); + decodeProbe(e, "H.g1.zeros.legacy", vector(48, 0), true); + decodeProbe(e, "H.g2.zeros.basic", vector(96, 0), false); + decodeProbe(e, "H.g2.zeros.legacy", vector(96, 0), true); + decodeProbeUnchecked(e, "H.g1.zeros.legacy.unchk", vector(48, 0), true); + decodeProbeUnchecked(e, "H.g2.zeros.legacy.unchk", vector(96, 0), true); + + // 4. x >= field prime (0xff filler), with/without legacy sign bit + vector ff48(48, 0xff); + vector ff96(96, 0xff); + decodeProbe(e, "H.g1.ff.basic", ff48, false); + decodeProbe(e, "H.g1.ff.legacy", ff48, true); + decodeProbe(e, "H.g2.ff.basic", ff96, false); + decodeProbe(e, "H.g2.ff.legacy", ff96, true); + vector ff48low = ff48; + ff48low[0] = 0x1f; // below prime top byte range but x still >= p + decodeProbe(e, "H.g1.fflow.legacy", ff48low, true); + + // 5. legacy bytes fed to the modern decoder and vice versa + decodeProbe(e, "H.g1.legacyAsBasic", pk.Serialize(true), false); + decodeProbe(e, "H.g1.basicAsLegacy", pk.Serialize(false), true); + decodeProbe(e, "H.g2.legacyAsBasic", sig.Serialize(true), false); + decodeProbe(e, "H.g2.basicAsLegacy", sig.Serialize(false), true); + + // 6. valid encodings with flipped sign bit (the negated point) + vector pkl = pk.Serialize(true); + pkl[0] ^= 0x80; + decodeProbe(e, "H.g1.negated.legacy", pkl, true); + vector pkb = pk.Serialize(false); + pkb[0] ^= 0x20; + decodeProbe(e, "H.g1.negated.basic", pkb, false); + + // 7. on-curve but non-subgroup points (found by scanning small x with a + // blst helper; each x satisfies y^2 = x^3 + 4 (+4i) with the point + // outside the r-torsion). Encodings below use y = the "smaller" root + // (sign bit 0), in each codec's byte layout. + // G1: x = 4 -> not in subgroup. + vector nsG1(48, 0); + nsG1[47] = 0x04; + decodeProbe(e, "H.g1.nonsub.legacy", nsG1, true); + decodeProbeUnchecked(e, "H.g1.nonsub.legacy.unchk", nsG1, true); + vector nsG1b = nsG1; + nsG1b[0] |= 0x80; // modern compression flag + decodeProbe(e, "H.g1.nonsub.basic", nsG1b, false); + decodeProbeUnchecked(e, "H.g1.nonsub.basic.unchk", nsG1b, false); + // G2: x = (1, 0) -> not in subgroup (legacy layout: c0 || c1). + vector nsG2(96, 0); + nsG2[47] = 0x01; + decodeProbe(e, "H.g2.nonsub.legacy", nsG2, true); + decodeProbeUnchecked(e, "H.g2.nonsub.legacy.unchk", nsG2, true); + // modern layout: c1 || c0 with flags on byte 0 + vector nsG2b(96, 0); + nsG2b[95] = 0x01; + nsG2b[0] |= 0x80; + decodeProbe(e, "H.g2.nonsub.basic", nsG2b, false); + decodeProbeUnchecked(e, "H.g2.nonsub.basic.unchk", nsG2b, false); + + // 8. x not on curve (no square root exists): x = 1 for G1 + vector noc(48, 0); + noc[47] = 0x01; + decodeProbe(e, "H.g1.nocurve.legacy", noc, true); + vector nocb = noc; + nocb[0] |= 0x80; + decodeProbe(e, "H.g1.nocurve.basic", nocb, false); + + // 9. modern G2 with the reserved top bits of byte 48 set + vector flag48 = sig.Serialize(false); + flag48[48] |= 0xe0; + decodeProbe(e, "H.g2.flag48.basic", flag48, false); + + // 10. wrong length + try { + G1Element::FromBytes(Bytes(vector(47, 0)), false); + e.raw("H.len47=NOEXC"); + } catch (const std::exception&) { e.exc("H.len47"); } + + // 11. legacy sign bit set on degenerate x values (exercises the + // sqrt-failure and x>=p fallback paths with stored sign = 1) + vector s1(48, 0); + s1[0] = 0x80; + s1[47] = 0x01; // x = 1, not on curve + decodeProbe(e, "H.g1.nocurve.sign.legacy", s1, true); + vector sp(48, 0xff); + sp[0] = 0x9f; // sign bit + x = 0x1fff... >= p + decodeProbe(e, "H.g1.overp.sign.legacy", sp, true); + vector g2s(96, 0); + g2s[0] = 0x80; + g2s[47] = 0x02; // x = (2, 0), sign bit set + decodeProbe(e, "H.g2.x2.sign.legacy", g2s, true); + vector g2s3(96, 0); + g2s3[0] = 0x80; + g2s3[47] = 0x03; // x = (3, 0), sign bit set + decodeProbe(e, "H.g2.x3.sign.legacy", g2s3, true); + vector g2nc(96, 0); + g2nc[47] = 0x02; // x = (2, 0), sign bit clear + decodeProbe(e, "H.g2.x2.legacy", g2nc, true); + vector g2sp(96, 0xff); + g2sp[0] = 0x9f; // c0 >= p (sign set), c1 >= p + decodeProbe(e, "H.g2.overp.sign.legacy", g2sp, true); +} + +// ------------------------------------------------------------------ section I +// Verification semantics with infinity elements and empty inputs. +inline void VerifyEdges(Emitter& e) +{ + BasicSchemeMPL basic; + LegacySchemeMPL legacy; + vector msg = {9, 9, 9}; + vector h = hashN(900); + + e.dumpb("I.basic.verify.infinf", basic.Verify(G1Element(), msg, G2Element())); + e.dumpb("I.legacy.verify.infinf", legacy.Verify(G1Element(), Bytes(h), G2Element())); + + PrivateKey sk = basic.KeyGen(seedN(900)); + G2Element sig = basic.Sign(sk, msg); + e.dumpb("I.basic.verify.infpk", basic.Verify(G1Element(), msg, sig)); + e.dumpb("I.basic.verify.infsig", basic.Verify(sk.GetG1Element(), msg, G2Element())); + + // AggregateVerify argument invariants + e.dumpb("I.aggver.empty.infsig", + basic.AggregateVerify(vector{}, vector{}, G2Element())); + e.dumpb("I.aggver.empty.realsig", + basic.AggregateVerify(vector{}, vector{}, sig)); + e.dumpb("I.aggver.mismatch", + basic.AggregateVerify(vector{sk.GetG1Element()}, vector{}, sig)); + + // VerifySecure with an infinity pubkey in the list + vector pks = {sk.GetG1Element(), G1Element()}; + e.dumpb("I.versec.withinf", basic.VerifySecure(pks, sig, Bytes(h))); +} + + +inline std::vector GenerateReferenceVectors() +{ + Emitter e; + e.raw("# dashbls reference vectors v1"); + KeysAndSignatures(e); + SecureAggregation(e); + ThresholdVectors(e); + ExtendedKeys(e); + PrivateKeyEdges(e); + EdgeDecodes(e); + VerifyEdges(e); + e.raw("# end"); + return e.lines; +} + +} // namespace bls_test_vectors + +#endif // SRC_TEST_VECTORS_HPP_ diff --git a/src/dashbls/src/test.cpp b/src/dashbls/src/test.cpp index 0bc920edf594..d6572cbe111d 100644 --- a/src/dashbls/src/test.cpp +++ b/src/dashbls/src/test.cpp @@ -19,18 +19,25 @@ #include "bls.hpp" #include -extern "C" { -#include "relic.h" -} #include "test-utils.hpp" -using std::cout; -using std::endl; +#include "test-vectors.hpp" + +#include +#include + using std::string; using std::vector; using namespace bls; -void TestHKDF(string ikm_hex, string salt_hex, string info_hex, string prk_expected_hex, string okm_expected_hex, int L) { +void TestHKDF( + string ikm_hex, + string salt_hex, + string info_hex, + string prk_expected_hex, + string okm_expected_hex, + int L) +{ vector ikm = Util::HexToBytes(ikm_hex); vector salt = Util::HexToBytes(salt_hex); vector info = Util::HexToBytes(info_hex); @@ -42,42 +49,45 @@ void TestHKDF(string ikm_hex, string salt_hex, string info_hex, string prk_expec HKDF256::Expand(okm, L, prk, info.data(), info.size()); REQUIRE(32 == prk_expected.size()); - REQUIRE(L == okm_expected.size()); + REQUIRE(L == (int)okm_expected.size()); - for (size_t i=0; i < 32; i++) { + for (size_t i = 0; i < 32; i++) { REQUIRE(prk[i] == prk_expected[i]); } - for (size_t i=0; i < L; i++) { + for (int i = 0; i < L; i++) { REQUIRE(okm[i] == okm_expected[i]); } delete[] okm; } -TEST_CASE("class PrivateKey") { +TEST_CASE("class PrivateKey") +{ uint8_t buffer[PrivateKey::PRIVATE_KEY_SIZE]; memcpy(buffer, getRandomSeed().data(), PrivateKey::PRIVATE_KEY_SIZE); - SECTION("Copy {constructor|assignment operator}") { - PrivateKey pk1 = PrivateKey::RandomPrivateKey(); - PrivateKey pk2 = PrivateKey::RandomPrivateKey(); + SECTION("Copy {constructor|assignment operator}") + { + PrivateKey pk1 = PrivateKey::FromByteVector(getRandomSeed(), true); + PrivateKey pk2 = PrivateKey::FromByteVector(getRandomSeed(), true); PrivateKey pk3 = PrivateKey(pk2); REQUIRE(!pk1.IsZero()); REQUIRE(!pk2.IsZero()); REQUIRE(!pk3.IsZero()); REQUIRE(pk1 != pk2); REQUIRE(pk3 == pk2); - REQUIRE(pk2.GetG1Element().IsValid()); // cache previous g1 - REQUIRE(pk2.GetG2Element().IsValid()); // cache previous g2 + REQUIRE(pk2.GetG1Element().IsValid()); // cache previous g1 + REQUIRE(pk2.GetG2Element().IsValid()); // cache previous g2 pk2 = pk1; REQUIRE(pk1 == pk2); REQUIRE(pk1.GetG1Element() == pk2.GetG1Element()); REQUIRE(pk1.GetG2Element() == pk2.GetG2Element()); REQUIRE(pk3 != pk2); } - SECTION("Move {constructor|assignment operator}") { - PrivateKey pk1 = PrivateKey::RandomPrivateKey(); + SECTION("Move {constructor|assignment operator}") + { + PrivateKey pk1 = PrivateKey::FromByteVector(getRandomSeed(), true); std::vector vec1 = pk1.Serialize(); - PrivateKey pk2 = PrivateKey::RandomPrivateKey(); + PrivateKey pk2 = PrivateKey::FromByteVector(getRandomSeed(), true); std::vector vec2 = pk2.Serialize(); PrivateKey pk3 = PrivateKey(std::move(pk2)); REQUIRE(!pk1.IsZero()); @@ -94,48 +104,71 @@ TEST_CASE("class PrivateKey") { REQUIRE_THROWS(pk2.IsZero()); REQUIRE_THROWS(pk3.IsZero()); } - SECTION("Equality operators") { - PrivateKey pk1 = PrivateKey::RandomPrivateKey(); - PrivateKey pk2 = PrivateKey::RandomPrivateKey(); + SECTION("Equality operators") + { + PrivateKey pk1 = PrivateKey::FromByteVector(getRandomSeed(), true); + PrivateKey pk2 = PrivateKey::FromByteVector(getRandomSeed(), true); PrivateKey pk3 = pk2; REQUIRE(pk1 != pk2); REQUIRE(pk1 != pk3); REQUIRE(pk2 == pk3); } - SECTION("(De)Serialization") { - PrivateKey pk1 = PrivateKey::RandomPrivateKey(); + SECTION("(De)Serialization") + { + PrivateKey pk1 = PrivateKey::FromByteVector(getRandomSeed(), true); pk1.Serialize(buffer); - REQUIRE(memcmp(buffer, pk1.Serialize().data(), PrivateKey::PRIVATE_KEY_SIZE) == 0); + REQUIRE( + memcmp( + buffer, pk1.Serialize().data(), PrivateKey::PRIVATE_KEY_SIZE) == + 0); PrivateKey pk2 = PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true); REQUIRE(pk1 == pk2); - REQUIRE_THROWS(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE - 1), true)); - REQUIRE_THROWS(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE + 1), true)); - REQUIRE_NOTHROW(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true)); - bn_t order; - bn_new(order); - g1_get_ord(order); - bn_write_bin(buffer, PrivateKey::PRIVATE_KEY_SIZE, order); + REQUIRE_THROWS(PrivateKey::FromBytes( + Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE - 1), true)); + REQUIRE_THROWS(PrivateKey::FromBytes( + Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE + 1), true)); + REQUIRE_NOTHROW(PrivateKey::FromBytes( + Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true)); + // the group order r itself is accepted (bn_cmp > 0 semantics) + const vector order = Util::HexToBytes( + "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); + memcpy(buffer, order.data(), PrivateKey::PRIVATE_KEY_SIZE); REQUIRE_NOTHROW(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), false)); REQUIRE_NOTHROW(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true)); - bn_add(order, order, order); - bn_write_bin(buffer, PrivateKey::PRIVATE_KEY_SIZE, order); + // 2 * r is above the order and must be rejected without modOrder + const vector order2 = Util::HexToBytes( + "e7db4ea6533afa906673b0101343b00aa77b4805fffcb7fdfffffffe00000002"); + memcpy(buffer, order2.data(), PrivateKey::PRIVATE_KEY_SIZE); REQUIRE_THROWS(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), false)); REQUIRE_NOTHROW(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true)); + // The hardcoded order must agree with blst's own, which is only + // reachable through blst_scalar_fr_check (true iff below r): r itself + // is not a valid Fr element, r - 1 is. + blst_scalar s; + blst_scalar_from_bendian(&s, order.data()); + REQUIRE(!blst_scalar_fr_check(&s)); + vector orderm1 = order; + orderm1[31] = 0x00; + blst_scalar_from_bendian(&s, orderm1.data()); + REQUIRE(blst_scalar_fr_check(&s)); } SECTION("BIP32 Seed") { uint8_t aliceSeed[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; PrivateKey pk1 = PrivateKey::FromSeedBIP32(Bytes(aliceSeed, 10)); REQUIRE(pk1.HasKeyData()); - vector privateKey = pk1.Serialize(true); + vector privateKey = pk1.Serialize(); vector knownPrivateKey = Util::HexToBytes("46891c2cec49593c81921e473db7480029e0fc1eb933c6b93d81f5370eb19fbd"); REQUIRE(privateKey == knownPrivateKey); G1Element pubKey1 = pk1.GetG1Element(); vector pubKey1Bytes = pubKey1.Serialize(true); + vector pubKey2Bytes = pubKey1.Serialize(false); vector knownPublicKey = Util::HexToBytes("1790635de8740e9a6a6b15fb6b72f3a16afa0973d971979b6ba54761d6e2502c50db76f4d26143f05459a42cfd520d44"); REQUIRE(pubKey1Bytes == knownPublicKey); + REQUIRE(pubKey2Bytes != pubKey1Bytes); } - SECTION("keydata checks") { - PrivateKey pk1 = PrivateKey::RandomPrivateKey(); + SECTION("keydata checks") + { + PrivateKey pk1 = PrivateKey::FromByteVector(getRandomSeed(), true); G1Element g1 = pk1.GetG1Element(); G2Element g2 = pk1.GetG2Element(); PrivateKey pk2 = std::move(pk1); @@ -154,69 +187,86 @@ TEST_CASE("class PrivateKey") { REQUIRE_THROWS(pk1 != pk2); REQUIRE_THROWS(pk1.Serialize(buffer)); REQUIRE_THROWS(pk1.Serialize()); - REQUIRE_THROWS(pk1.SignG2(buffer, sizeof(buffer), buffer, sizeof(buffer))); + REQUIRE_THROWS( + pk1.SignG2(buffer, sizeof(buffer), buffer, sizeof(buffer))); } } -TEST_CASE("HKDF") { +TEST_CASE("HKDF") +{ // https://tools.ietf.org/html/rfc5869 test vectors - SECTION("Test case 2") { - TestHKDF("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - "000102030405060708090a0b0c", - "f0f1f2f3f4f5f6f7f8f9", - "077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5", - "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865", - 42 - ); - } - SECTION("Test case 2") { - TestHKDF("000102030405060708090a0b0c0d0e0f" - "101112131415161718191a1b1c1d1e1f" - "202122232425262728292a2b2c2d2e2f" - "303132333435363738393a3b3c3d3e3f" - "404142434445464748494a4b4c4d4e4f", // 80 octets - "0x606162636465666768696a6b6c6d6e6f" - "707172737475767778797a7b7c7d7e7f" - "808182838485868788898a8b8c8d8e8f" - "909192939495969798999a9b9c9d9e9f" - "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", // 80 octets - "0xb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" - "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" - "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" - "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", // 80 octets - "0x06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244", // 32 octets - "0xb11e398dc80327a1c8e7f78c596a4934" - "4f012eda2d4efad8a050cc4c19afa97c" - "59045a99cac7827271cb41c65e590e09" - "da3275600c2f09b8367793a9aca3db71" - "cc30c58179ec3e87c14c01d5c1f3434f" - "1d87", // 82 octets - 82 - ); - } - SECTION("Test case 3") { - TestHKDF("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - "", - "", - "19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04", - "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8", - 42 - ); - } - SECTION("Works with multiple of 32") { - // This generates exactly 64 bytes. Uses a 32 byte key and 4 byte salt as in EIP2333. - TestHKDF("8704f9ac024139fe62511375cf9bc534c0507dcf00c41603ac935cd5943ce0b4b88599390de14e743ca2f56a73a04eae13aa3f3b969b39d8701e0d69a6f8d42f", - "53d8e19b", - "", - "eb01c9cd916653df76ffa61b6ab8a74e254ebfd9bfc43e624cc12a72b0373dee", - "8faabea85fc0c64e7ca86217cdc6dcdc88551c3244d56719e630a3521063082c46455c2fd5483811f9520a748f0099c1dfcfa52c54e1c22b5cdf70efb0f3c676", - 64 - ); + SECTION("Test case 2") + { + TestHKDF( + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "000102030405060708090a0b0c", + "f0f1f2f3f4f5f6f7f8f9", + "077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5", + "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34" + "007208d5b887185865", + 42); + } + SECTION("Test case 2") + { + TestHKDF( + "000102030405060708090a0b0c0d0e0f" + "101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f" + "303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f", // 80 octets + "0x606162636465666768696a6b6c6d6e6f" + "707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f" + "909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", // 80 octets + "0xb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", // 80 octets + "0x06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc24" + "4", // 32 octets + "0xb11e398dc80327a1c8e7f78c596a4934" + "4f012eda2d4efad8a050cc4c19afa97c" + "59045a99cac7827271cb41c65e590e09" + "da3275600c2f09b8367793a9aca3db71" + "cc30c58179ec3e87c14c01d5c1f3434f" + "1d87", // 82 octets + 82); + } + SECTION("Test case 3") + { + TestHKDF( + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "", + "", + "19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04", + "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d" + "201395faa4b61a96c8", + 42); + } + SECTION("Works with multiple of 32") + { + // This generates exactly 64 bytes. Uses a 32 byte key and 4 byte salt + // as in EIP2333. + TestHKDF( + "8704f9ac024139fe62511375cf9bc534c0507dcf00c41603ac935cd5943ce0b4b8" + "8599390de14e743ca2f56a73a04eae13aa3f3b969b39d8701e0d69a6f8d42f", + "53d8e19b", + "", + "eb01c9cd916653df76ffa61b6ab8a74e254ebfd9bfc43e624cc12a72b0373dee", + "8faabea85fc0c64e7ca86217cdc6dcdc88551c3244d56719e630a3521063082c46" + "455c2fd5483811f9520a748f0099c1dfcfa52c54e1c22b5cdf70efb0f3c676", + 64); } } -void TestEIP2333(string seedHex, string masterSkHex, string childSkHex, uint32_t childIndex) { +void TestEIP2333( + string seedHex, + string masterSkHex, + string childSkHex, + uint32_t childIndex) +{ auto masterSk = Util::HexToBytes(masterSkHex); auto childSk = Util::HexToBytes(childSkHex); @@ -230,60 +280,73 @@ void TestEIP2333(string seedHex, string masterSkHex, string childSkHex, uint32_t REQUIRE(calculatedMaster.size() == 32); REQUIRE(calculatedChild.size() == 32); - for (int i=0; i<32; i++) { + for (int i = 0; i < 32; i++) { REQUIRE(calculatedMaster[i] == masterSk[i]); } - for (int i=0; i<32; i++) { + for (int i = 0; i < 32; i++) { REQUIRE(calculatedChild[i] == childSk[i]); } } -TEST_CASE("EIP-2333 hardened HD keys") { - // The comments in the test cases correspond to integers that are converted to - // bytes using python int.to_bytes(32, "big").hex(), since the EIP spec provides ints, but c++ - // does not support bigint by default - SECTION("EIP-2333 Test case 1"){ - TestEIP2333("3141592653589793238462643383279502884197169399375105820974944592", - // 36167147331491996618072159372207345412841461318189449162487002442599770291484 - "4ff5e145590ed7b71e577bb04032396d1619ff41cb4e350053ed2dce8d1efd1c", - // 41787458189896526028601807066547832426569899195138584349427756863968330588237 - "5c62dcf9654481292aafa3348f1d1b0017bbfb44d6881d26d2b17836b38f204d", - 3141592653 - ); - } - SECTION("EIP-2333 Test case 2"){ - TestEIP2333("0x0099FF991111002299DD7744EE3355BBDD8844115566CC55663355668888CC00", - // 13904094584487173309420026178174172335998687531503061311232927109397516192843 - "1ebd704b86732c3f05f30563dee6189838e73998ebc9c209ccff422adee10c4b", - // 12482522899285304316694838079579801944734479969002030150864436005368716366140 - "1b98db8b24296038eae3f64c25d693a269ef1e4d7ae0f691c572a46cf3c0913c", - 4294967295 - ); - } - SECTION("EIP-2333 Test case 3"){ - TestEIP2333("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", - // 44010626067374404458092393860968061149521094673473131545188652121635313364506 - "614d21b10c0e4996ac0608e0e7452d5720d95d20fe03c59a3321000a42432e1a", - // 4011524214304750350566588165922015929937602165683407445189263506512578573606 - "08de7136e4afc56ae3ec03b20517d9c1232705a747f588fd17832f36ae337526", - 42 - ); - } - SECTION("EIP-2333 Test vector with intermediate values"){ - TestEIP2333("c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04", - // 5399117110774477986698372024995405256382522670366369834617409486544348441851 - "0x0befcabff4a664461cc8f190cdd51c05621eb2837c71a1362df5b465a674ecfb", - // 11812940737387919040225825939013910852517748782307378293770044673328955938106 - "1a1de3346883401f1e3b2281be5774080edb8e5ebe6f776b0f7af9fea942553a", - 0 - ); +TEST_CASE("EIP-2333 hardened HD keys") +{ + // The comments in the test cases correspond to integers that are converted + // to bytes using python int.to_bytes(32, "big").hex(), since the EIP spec + // provides ints, but c++ does not support bigint by default + SECTION("EIP-2333 Test case 1") + { + TestEIP2333( + "3141592653589793238462643383279502884197169399375105820974944592", + // 36167147331491996618072159372207345412841461318189449162487002442599770291484 + "4ff5e145590ed7b71e577bb04032396d1619ff41cb4e350053ed2dce8d1efd1c", + // 41787458189896526028601807066547832426569899195138584349427756863968330588237 + "5c62dcf9654481292aafa3348f1d1b0017bbfb44d6881d26d2b17836b38f204d", + 3141592653); + } + SECTION("EIP-2333 Test case 2") + { + TestEIP2333( + "0x0099FF991111002299DD7744EE3355BBDD8844115566CC55663355668888CC0" + "0", + // 13904094584487173309420026178174172335998687531503061311232927109397516192843 + "1ebd704b86732c3f05f30563dee6189838e73998ebc9c209ccff422adee10c4b", + // 12482522899285304316694838079579801944734479969002030150864436005368716366140 + "1b98db8b24296038eae3f64c25d693a269ef1e4d7ae0f691c572a46cf3c0913c", + 4294967295); + } + SECTION("EIP-2333 Test case 3") + { + TestEIP2333( + "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa" + "3", + // 44010626067374404458092393860968061149521094673473131545188652121635313364506 + "614d21b10c0e4996ac0608e0e7452d5720d95d20fe03c59a3321000a42432e1a", + // 4011524214304750350566588165922015929937602165683407445189263506512578573606 + "08de7136e4afc56ae3ec03b20517d9c1232705a747f588fd17832f36ae337526", + 42); + } + SECTION("EIP-2333 Test vector with intermediate values") + { + TestEIP2333( + "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f" + "09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04", + // 5399117110774477986698372024995405256382522670366369834617409486544348441851 + "0x0befcabff4a664461cc8f190cdd51c05621eb2837c71a1362df5b465a674ecf" + "b", + // 11812940737387919040225825939013910852517748782307378293770044673328955938106 + "1a1de3346883401f1e3b2281be5774080edb8e5ebe6f776b0f7af9fea942553a", + 0); } } -TEST_CASE("Unhardened HD keys") { - SECTION("Should match derivation through private and public keys"){ - const vector seed = {1, 50, 6, 244, 24, 199, 1, 25, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}; +TEST_CASE("Unhardened HD keys") +{ + SECTION("Should match derivation through private and public keys") + { + const vector seed = {1, 50, 6, 244, 24, 199, 1, 25, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29}; PrivateKey sk = BasicSchemeMPL().KeyGen(seed); G1Element pk = sk.GetG1Element(); @@ -293,15 +356,20 @@ TEST_CASE("Unhardened HD keys") { REQUIRE(childSk.GetG1Element() == childPk); - PrivateKey grandchildSk = BasicSchemeMPL().DeriveChildSkUnhardened(childSk, 12142); - G1Element grandcihldPk = BasicSchemeMPL().DeriveChildPkUnhardened(childPk, 12142); + PrivateKey grandchildSk = + BasicSchemeMPL().DeriveChildSkUnhardened(childSk, 12142); + G1Element grandchildPk = + BasicSchemeMPL().DeriveChildPkUnhardened(childPk, 12142); - REQUIRE(grandchildSk.GetG1Element() == grandcihldPk); + REQUIRE(grandchildSk.GetG1Element() == grandchildPk); } - SECTION("Should derive public child from parent") { - const vector seed = {2, 50, 6, 244, 24, 199, 1, 25, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}; + SECTION("Should derive public child from parent") + { + const vector seed = {2, 50, 6, 244, 24, 199, 1, 25, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29}; PrivateKey sk = BasicSchemeMPL().KeyGen(seed); G1Element pk = sk.GetG1Element(); @@ -316,10 +384,17 @@ TEST_CASE("Unhardened HD keys") { } } -TEST_CASE("IETF test vectors") { - SECTION ("Pyecc vector") { - string sig1BasicHex = "96ba34fac33c7f129d602a0bc8a3d43f9abc014eceaab7359146b4b150e57b808645738f35671e9e10e0d862a30cab70074eb5831d13e6a5b162d01eebe687d0164adbd0a864370a7c222a2768d7704da254f1bf1823665bc2361f9dd8c00e99"; - string sk = "0x0101010101010101010101010101010101010101010101010101010101010101"; +TEST_CASE("IETF test vectors") +{ + SECTION("Pyecc vector") + { + string sig1BasicHex = + "96ba34fac33c7f129d602a0bc8a3d43f9abc014eceaab7359146b4b150e57b8086" + "45738f35671e9e10e0d862a30cab70074eb5831d13e6a5b162d01eebe687d0164a" + "dbd0a864370a7c222a2768d7704da254f1bf1823665bc2361f9dd8c00e99"; + string sk = + "0x010101010101010101010101010101010101010101010101010101010101010" + "1"; vector msg = {3, 1, 4, 1, 5, 9}; auto skobj = PrivateKey::FromBytes(Bytes(Util::HexToBytes(sk))); G2Element sig = BasicSchemeMPL().Sign(skobj, msg); @@ -331,9 +406,10 @@ TEST_CASE("IETF test vectors") { } } - -TEST_CASE("Chia test vectors") { - SECTION("Chia test vectors 1 (Basic)") { +TEST_CASE("Chia test vectors") +{ + SECTION("Chia test vectors 1 (Basic)") + { vector seed1(32, 0x00); // All 0s vector seed2(32, 0x01); // All 1s vector message1 = {7, 8, 9}; @@ -343,7 +419,6 @@ TEST_CASE("Chia test vectors") { G1Element pk1 = sk1.GetG1Element(); G2Element sig1 = BasicSchemeMPL().Sign(sk1, message1); - PrivateKey sk2 = BasicSchemeMPL().KeyGen(seed2); G1Element pk2 = sk2.GetG1Element(); G2Element sig2 = BasicSchemeMPL().Sign(sk2, message2); @@ -366,20 +441,26 @@ TEST_CASE("Chia test vectors") { REQUIRE( Util::HexStr(sig2.Serialize()) == - "a9c4d3e689b82c7ec7e838dac2380cb014f9a08f6cd6ba044c263746e39a8f7a60ffee4afb7" - "8f146c2e421360784d58f0029491e3bd8ab84f0011d258471ba4e87059de295d9aba845c044e" + "a9c4d3e689b82c7ec7e838dac2380cb014f9a08f6cd6ba044c263746e39a8f7a60" + "ffee4afb7" + "8f146c2e421360784d58f0029491e3bd8ab84f0011d258471ba4e87059de295d9a" + "ba845c044e" "e83f6cf2411efd379ef38bf4cf41d5f3c0ae1205d"); G2Element aggSig1 = BasicSchemeMPL().Aggregate({sig1, sig2}); REQUIRE( Util::HexStr(aggSig1.Serialize()) == - "aee003c8cdaf3531b6b0ca354031b0819f7586b5846796615aee8108fec75ef838d181f9d24" - "4a94d195d7b0231d4afcf06f27f0cc4d3c72162545c240de7d5034a7ef3a2a03c0159de982fb" + "aee003c8cdaf3531b6b0ca354031b0819f7586b5846796615aee8108fec75ef838" + "d181f9d24" + "4a94d195d7b0231d4afcf06f27f0cc4d3c72162545c240de7d5034a7ef3a2a03c0" + "159de982fb" "c2e7790aeb455e27beae91d64e077c70b5506dea3"); - REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message1, message2}, aggSig1)); - REQUIRE(!BasicSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message1, message2}, sig1)); + REQUIRE(BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{message1, message2}, aggSig1)); + REQUIRE(!BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{message1, message2}, sig1)); REQUIRE(!BasicSchemeMPL().Verify(pk1, message1, sig2)); REQUIRE(!BasicSchemeMPL().Verify(pk1, message2, sig1)); @@ -393,15 +474,21 @@ TEST_CASE("Chia test vectors") { G2Element aggSig2 = BasicSchemeMPL().Aggregate({sig3, sig4, sig5}); - REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk1, pk2}, vector>{message3, message4, message5}, aggSig2)); + REQUIRE(BasicSchemeMPL().AggregateVerify( + {pk1, pk1, pk2}, + vector>{message3, message4, message5}, + aggSig2)); REQUIRE( Util::HexStr(aggSig2.Serialize()) == - "a0b1378d518bea4d1100adbc7bdbc4ff64f2c219ed6395cd36fe5d2aa44a4b8e710b607afd9" - "65e505a5ac3283291b75413d09478ab4b5cfbafbeea366de2d0c0bcf61deddaa521f6020460f" + "a0b1378d518bea4d1100adbc7bdbc4ff64f2c219ed6395cd36fe5d2aa44a4b8e71" + "0b607afd9" + "65e505a5ac3283291b75413d09478ab4b5cfbafbeea366de2d0c0bcf61deddaa52" + "1f6020460f" "d547ab37659ae207968b545727beba0a3c5572b9c"); } - SECTION("Chia test vector 2 (Augmented, aggregate of aggregates)") { + SECTION("Chia test vector 2 (Augmented, aggregate of aggregates)") + { vector message1 = {1, 2, 3, 40}; vector message2 = {5, 6, 70, 201}; vector message3 = {9, 10, 11, 12, 13}; @@ -423,20 +510,26 @@ TEST_CASE("Chia test vectors") { G2Element sig5 = AugSchemeMPL().Sign(sk1, message1); G2Element sig6 = AugSchemeMPL().Sign(sk1, message4); - G2Element aggSigL = AugSchemeMPL().Aggregate({sig1, sig2}); G2Element aggSigR = AugSchemeMPL().Aggregate({sig3, sig4, sig5}); G2Element aggSig = AugSchemeMPL().Aggregate({aggSigL, aggSigR, sig6}); - REQUIRE(AugSchemeMPL().AggregateVerify({pk1, pk2, pk2, pk1, pk1, pk1}, vector>{message1, message2, message1, message3, message1, message4}, aggSig)); + REQUIRE(AugSchemeMPL().AggregateVerify( + {pk1, pk2, pk2, pk1, pk1, pk1}, + vector>{ + message1, message2, message1, message3, message1, message4}, + aggSig)); REQUIRE( Util::HexStr(aggSig.Serialize()) == - "a1d5360dcb418d33b29b90b912b4accde535cf0e52caf467a005dc632d9f7af44b6c4e9acd4" - "6eac218b28cdb07a3e3bc087df1cd1e3213aa4e11322a3ff3847bbba0b2fd19ddc25ca964871" + "a1d5360dcb418d33b29b90b912b4accde535cf0e52caf467a005dc632d9f7af44b" + "6c4e9acd4" + "6eac218b28cdb07a3e3bc087df1cd1e3213aa4e11322a3ff3847bbba0b2fd19ddc" + "25ca964871" "997b9bceeab37a4c2565876da19382ea32a962200"); } - SECTION("Chia test vector 3 (PoP)") { + SECTION("Chia test vector 3 (PoP)") + { vector message1 = {1, 2, 3, 40, 50}; vector seed1(32, 0x04); // All 4s @@ -446,13 +539,16 @@ TEST_CASE("Chia test vectors") { G2Element pop = PopSchemeMPL().PopProve(sk1); REQUIRE(PopSchemeMPL().PopVerify(sk1.GetG1Element(), pop)); - REQUIRE(Util::HexStr(pop.Serialize()) == "84f709159435f0dc73b3e8bf6c78d85282d19231555a8ee3b6e2573aaf66872d9203fefa1ef" - "700e34e7c3f3fb28210100558c6871c53f1ef6055b9f06b0d1abe22ad584ad3b957f3018a8f5" - "8227c6c716b1e15791459850f2289168fa0cf9115"); + REQUIRE( + Util::HexStr(pop.Serialize()) == + "84f709159435f0dc73b3e8bf6c78d85282d19231555a8ee3b6e2573aaf66872d92" + "03fefa1ef" + "700e34e7c3f3fb28210100558c6871c53f1ef6055b9f06b0d1abe22ad584ad3b95" + "7f3018a8f5" + "8227c6c716b1e15791459850f2289168fa0cf9115"); } } - TEST_CASE("Key generation") { SECTION("Should generate a keypair from a seed") @@ -463,12 +559,10 @@ TEST_CASE("Key generation") REQUIRE_THROWS(BasicSchemeMPL().KeyGen(seed1)); PrivateKey sk = BasicSchemeMPL().KeyGen(seed2); G1Element pk = sk.GetG1Element(); - REQUIRE(core_get()->code == RLC_OK); REQUIRE(pk.GetFingerprint() == 0x8ee7ba56); } } - TEST_CASE("Error handling") { SECTION("Should throw on a bad private key") @@ -478,7 +572,8 @@ TEST_CASE("Error handling") uint8_t* skData = Util::SecAlloc(G2Element::SIZE); sk1.Serialize(skData); skData[0] = 255; - REQUIRE_THROWS(PrivateKey::FromBytes(Bytes(skData, PrivateKey::PRIVATE_KEY_SIZE))); + REQUIRE_THROWS( + PrivateKey::FromBytes(Bytes(skData, PrivateKey::PRIVATE_KEY_SIZE))); Util::SecFree(skData); } @@ -487,7 +582,8 @@ TEST_CASE("Error handling") vector buf(G1Element::SIZE, 0); for (int i = 0; i < 0xFF; i++) { buf[0] = (uint8_t)i; - if (i == 0xc0) { // Infinity prefix shouldn't throw here as we have only zero values + if (i == 0xc0) { // Infinity prefix shouldn't throw here as we have + // only zero values REQUIRE_NOTHROW(G1Element::FromByteVector(buf)); } else { REQUIRE_THROWS(G1Element::FromByteVector(buf)); @@ -500,47 +596,20 @@ TEST_CASE("Error handling") vector buf(G2Element::SIZE, 0); for (int i = 0; i < 0xFF; i++) { buf[0] = (uint8_t)i; - if (i == 0xc0) { // Infinity prefix shouldn't throw here as we have only zero values + if (i == 0xc0) { // Infinity prefix shouldn't throw here as we have + // only zero values REQUIRE_NOTHROW(G2Element::FromByteVector(buf)); } else { REQUIRE_THROWS(G2Element::FromByteVector(buf)); } } - // Trigger "G2 element must always have 48th byte start with 0b000" error case + // Trigger "G2 element must always have 48th byte start with 0b000" + // error case buf[48] = 0xFF; REQUIRE_THROWS(G2Element::FromByteVector(buf)); } - - SECTION("Error handling should be thread safe") - { - core_get()->code = 10; - REQUIRE(core_get()->code == 10); - - ctx_t* ctx1 = core_get(); - - // spawn a thread and make sure it uses a different/same context depending on relic's multithreading setup - std::thread([&]() { -#if MULTI != RELIC_NONE - REQUIRE(ctx1 != core_get()); - REQUIRE(core_get()->code == RLC_OK); -#else - REQUIRE(ctx1 == core_get()); - REQUIRE(core_get()->code != RLC_OK); -#endif - core_get()->code = 1; - }).join(); - -#if MULTI != RELIC_NONE - REQUIRE(core_get()->code == 10); -#else - REQUIRE(core_get()->code == 1); -#endif - // reset so that future test cases don't fail - core_get()->code = RLC_OK; - } } - TEST_CASE("Util tests") { SECTION("Should convert an int to four bytes") @@ -558,7 +627,6 @@ TEST_CASE("Util tests") } } - TEST_CASE("Signature tests") { SECTION("Should use copy constructor") @@ -572,7 +640,8 @@ TEST_CASE("Signature tests") uint8_t skBytes[PrivateKey::PRIVATE_KEY_SIZE]; sk2.Serialize(skBytes); - PrivateKey sk4 = PrivateKey::FromBytes(Bytes(skBytes, PrivateKey::PRIVATE_KEY_SIZE)); + PrivateKey sk4 = + PrivateKey::FromBytes(Bytes(skBytes, PrivateKey::PRIVATE_KEY_SIZE)); G1Element pk2 = G1Element(pk1); G2Element sig1 = BasicSchemeMPL().Sign(sk4, message1); @@ -581,7 +650,8 @@ TEST_CASE("Signature tests") REQUIRE(BasicSchemeMPL().Verify(pk2, message1, sig2)); } - SECTION("Should sign with the zero key") { + SECTION("Should sign with the zero key") + { vector sk0(32, 0); PrivateKey sk = PrivateKey::FromByteVector(sk0); REQUIRE(sk.GetG1Element() == G1Element()); // Infinity @@ -632,7 +702,8 @@ TEST_CASE("Signature tests") uint8_t* skData = Util::SecAlloc(G2Element::SIZE); sk1.Serialize(skData); - PrivateKey sk2 = PrivateKey::FromBytes(Bytes(skData, PrivateKey::PRIVATE_KEY_SIZE)); + PrivateKey sk2 = + PrivateKey::FromBytes(Bytes(skData, PrivateKey::PRIVATE_KEY_SIZE)); REQUIRE(sk1 == sk2); auto pkData = pk1.Serialize(); @@ -654,7 +725,6 @@ TEST_CASE("Signature tests") SECTION("Should not verify aggregate with same message under BasicScheme") { vector message = {100, 2, 254, 88, 90, 45, 23}; - uint8_t hash[BLS::MESSAGE_HASH_LEN]; vector seed(32, 0x50); vector seed2(32, 0x70); @@ -669,13 +739,17 @@ TEST_CASE("Signature tests") G2Element sig2 = BasicSchemeMPL().Sign(sk2, message); G2Element aggSig = BasicSchemeMPL().Aggregate({sig1, sig2}); - REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message}, aggSig) == false); + REQUIRE( + BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, + vector>{message, message}, + aggSig) == false); } - SECTION("Should verify aggregate with same message under AugScheme/PopScheme") + SECTION( + "Should verify aggregate with same message under AugScheme/PopScheme") { vector message = {100, 2, 254, 88, 90, 45, 23}; - uint8_t hash[BLS::MESSAGE_HASH_LEN]; vector seed(32, 0x50); vector seed2(32, 0x70); @@ -689,19 +763,21 @@ TEST_CASE("Signature tests") G2Element sig1Aug = AugSchemeMPL().Sign(sk1, message); G2Element sig2Aug = AugSchemeMPL().Sign(sk2, message); G2Element aggSigAug = AugSchemeMPL().Aggregate({sig1Aug, sig2Aug}); - REQUIRE(AugSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message}, aggSigAug)); + REQUIRE(AugSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{message, message}, aggSigAug)); G2Element sig1Pop = PopSchemeMPL().Sign(sk1, message); G2Element sig2Pop = PopSchemeMPL().Sign(sk2, message); G2Element aggSigPop = PopSchemeMPL().Aggregate({sig1Pop, sig2Pop}); - REQUIRE(PopSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message}, aggSigPop)); + REQUIRE(PopSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{message, message}, aggSigPop)); } SECTION("Should Aug aggregate many G2Elements, diff message") { vector pks; vector sigs; - vector > ms; + vector> ms; for (uint8_t i = 0; i < 80; i++) { vector message = {0, 100, 2, 45, 64, 12, 12, 63, i}; @@ -720,8 +796,8 @@ TEST_CASE("Signature tests") SECTION("Aggregate Verification of zero items with infinity should pass") { vector pks_as_g1; - vector > pks_as_bytes; - vector > msgs; + vector> pks_as_bytes; + vector> msgs; vector sigs; sigs.push_back(G2Element()); @@ -731,22 +807,65 @@ TEST_CASE("Signature tests") REQUIRE(aggSig == G2Element()); REQUIRE(AugSchemeMPL().AggregateVerify(pks_as_g1, msgs, aggSig)); - REQUIRE(AugSchemeMPL().AggregateVerify(pks_as_bytes, msgs, aggSig.Serialize())); + REQUIRE(AugSchemeMPL().AggregateVerify( + pks_as_bytes, msgs, aggSig.Serialize())); REQUIRE(BasicSchemeMPL().AggregateVerify(pks_as_g1, msgs, aggSig)); - REQUIRE(BasicSchemeMPL().AggregateVerify(pks_as_bytes, msgs, aggSig.Serialize())); + REQUIRE(BasicSchemeMPL().AggregateVerify( + pks_as_bytes, msgs, aggSig.Serialize())); - // FastAggregateVerify takes one message, and requires at least one key + // FastAggregateVerify takes one message, and requires at least one key vector msg; REQUIRE(pks_as_g1.size() == 0); - REQUIRE(PopSchemeMPL().FastAggregateVerify(pks_as_g1, msg, aggSig) == false); + REQUIRE( + PopSchemeMPL().FastAggregateVerify(pks_as_g1, msg, aggSig) == + false); REQUIRE(pks_as_bytes.size() == 0); - REQUIRE(PopSchemeMPL().FastAggregateVerify(pks_as_bytes, msg, aggSig.Serialize()) == false); + REQUIRE( + PopSchemeMPL().FastAggregateVerify( + pks_as_bytes, msg, aggSig.Serialize()) == false); + } + SECTION("Verification with identity pubkey or signature should fail") + { + // Single verify: identity pubkey must be rejected + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = BasicSchemeMPL().Sign(sk, msg); + REQUIRE(BasicSchemeMPL().Verify(G1Element(), msg, sig) == false); + + // Single verify: identity signature must be rejected + auto pk = sk.GetG1Element(); + REQUIRE(BasicSchemeMPL().Verify(pk, msg, G2Element()) == false); + + // AggregateVerify: identity pubkey in non-empty list must be rejected + vector pks = {G1Element()}; + vector msgs_b = {Bytes(msg)}; + REQUIRE(BasicSchemeMPL().AggregateVerify(pks, msgs_b, sig) == false); + + // AggregateVerify: identity signature with non-empty pubkeys must be rejected + pks = {pk}; + REQUIRE(BasicSchemeMPL().AggregateVerify(pks, msgs_b, G2Element()) == false); + } + SECTION("Aggregate same sig element") + { + vector message = {100, 2, 254, 88, 90, 45, 23}; + + vector seed(32, 0x50); + + PrivateKey sk1 = BasicSchemeMPL().KeyGen(seed); + + G1Element pk1 = sk1.GetG1Element(); + + G2Element sig1Aug = AugSchemeMPL().Sign(sk1, message); + G2Element aggSigAug = AugSchemeMPL().Aggregate({sig1Aug, sig1Aug}); + REQUIRE(AugSchemeMPL().AggregateVerify( + {pk1, pk1}, vector>{message, message}, aggSigAug)); } } -TEST_CASE("Agg sks") { +TEST_CASE("Agg sks") +{ SECTION("Should create aggregates with agg sk (basic scheme)") { const vector message = {100, 2, 254, 88, 90, 45, 23}; @@ -771,7 +890,6 @@ TEST_CASE("Agg sks") { const G2Element aggSig2 = BasicSchemeMPL().Sign(aggSk, message); - const G2Element aggSig = BasicSchemeMPL().Aggregate({sig1, sig2}); REQUIRE(aggSig == aggSig2); @@ -780,8 +898,16 @@ TEST_CASE("Agg sks") { REQUIRE(BasicSchemeMPL().Verify(aggPubKey, message, aggSig2)); // Verify aggregate with both keys (Fails since not distinct) - REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message}, aggSig) == false); - REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message}, aggSig2) == false); + REQUIRE( + BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, + vector>{message, message}, + aggSig) == false); + REQUIRE( + BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, + vector>{message, message}, + aggSig2) == false); // Try the same with distinct message, and same sk vector message2 = {200, 29, 54, 8, 9, 29, 155, 55}; @@ -803,12 +929,17 @@ TEST_CASE("Agg sks") { REQUIRE(pkFinal != aggPubKey); // Cannot verify with aggPubKey (since we have multiple messages) - REQUIRE(BasicSchemeMPL().AggregateVerify({aggPubKey, pk2}, vector>{message, message2}, aggSigFinal)); + REQUIRE(BasicSchemeMPL().AggregateVerify( + {aggPubKey, pk2}, + vector>{message, message2}, + aggSigFinal)); } } -TEST_CASE("Advanced") { - SECTION("Should aggregate with multiple levels, degenerate") { +TEST_CASE("Advanced") +{ + SECTION("Should aggregate with multiple levels, degenerate") + { vector message1 = {100, 2, 254, 88, 90, 45, 23}; PrivateKey sk1 = AugSchemeMPL().KeyGen(getRandomSeed()); G1Element pk1 = sk1.GetG1Element(); @@ -827,7 +958,8 @@ TEST_CASE("Advanced") { REQUIRE(AugSchemeMPL().AggregateVerify(pks, ms, aggSig)); } - SECTION("Should aggregate with multiple levels, different messages") { + SECTION("Should aggregate with multiple levels, different messages") + { vector message1 = {100, 2, 254, 88, 90, 45, 23}; vector message2 = {192, 29, 2, 0, 0, 45, 23}; vector message3 = {52, 29, 2, 0, 0, 45, 102}; @@ -865,25 +997,24 @@ TEST_CASE("Advanced") { SECTION("README") { // Example seed, used to generate private key. Always use - // a secure RNG with sufficient entropy to generate a seed (at least 32 bytes). - vector seed = {0, 50, 6, 244, 24, 199, 1, 25, 52, 88, 192, - 19, 18, 12, 89, 6, 220, 18, 102, 58, 209, 82, - 12, 62, 89, 110, 182, 9, 44, 20, 254, 22}; + // a secure RNG with sufficient entropy to generate a seed (at least 32 + // bytes). + vector seed = {0, 50, 6, 244, 24, 199, 1, 25, + 52, 88, 192, 19, 18, 12, 89, 6, + 220, 18, 102, 58, 209, 82, 12, 62, + 89, 110, 182, 9, 44, 20, 254, 22}; PrivateKey sk = AugSchemeMPL().KeyGen(seed); G1Element pk = sk.GetG1Element(); - vector message = {1, 2, 3, 4, 5}; // Message is passed in as a byte vector + vector message = { + 1, 2, 3, 4, 5}; // Message is passed in as a byte vector G2Element signature = AugSchemeMPL().Sign(sk, message); vector skBytes = sk.Serialize(); vector pkBytes = pk.Serialize(); vector signatureBytes = signature.Serialize(); - cout << Util::HexStr(skBytes) << endl; // 32 bytes - cout << Util::HexStr(pkBytes) << endl; // 48 bytes - cout << Util::HexStr(signatureBytes) << endl; // 96 bytes - // Takes array of 32 bytes PrivateKey skc = PrivateKey::FromByteVector(skBytes); @@ -913,7 +1044,8 @@ TEST_CASE("Advanced") { // Signatures can be noninteractively combined by anyone G2Element aggSig = AugSchemeMPL().Aggregate({sig1, sig2}); - REQUIRE(AugSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message2}, aggSig)); + REQUIRE(AugSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{message, message2}, aggSig)); seed[0] = 3; PrivateKey sk3 = AugSchemeMPL().KeyGen(seed); @@ -921,14 +1053,17 @@ TEST_CASE("Advanced") { vector message3 = {100, 2, 254, 88, 90, 45, 23}; G2Element sig3 = AugSchemeMPL().Sign(sk3, message3); - // Arbitrary trees of aggregates G2Element aggSigFinal = AugSchemeMPL().Aggregate({aggSig, sig3}); - REQUIRE(AugSchemeMPL().AggregateVerify({pk1, pk2, pk3}, vector>{message, message2, message3}, aggSigFinal)); + REQUIRE(AugSchemeMPL().AggregateVerify( + {pk1, pk2, pk3}, + vector>{message, message2, message3}, + aggSigFinal)); - // If the same message is signed, you can use Proof of Posession (PopScheme) for efficiency - // A proof of possession MUST be passed around with the PK to ensure security. + // If the same message is signed, you can use Proof of Posession + // (PopScheme) for efficiency A proof of possession MUST be passed + // around with the PK to ensure security. G2Element popSig1 = PopSchemeMPL().Sign(sk1, message); G2Element popSig2 = PopSchemeMPL().Sign(sk2, message); @@ -940,9 +1075,11 @@ TEST_CASE("Advanced") { REQUIRE(PopSchemeMPL().PopVerify(pk1, pop1)); REQUIRE(PopSchemeMPL().PopVerify(pk2, pop2)); REQUIRE(PopSchemeMPL().PopVerify(pk3, pop3)); - G2Element popSigAgg = PopSchemeMPL().Aggregate({popSig1, popSig2, popSig3}); + G2Element popSigAgg = + PopSchemeMPL().Aggregate({popSig1, popSig2, popSig3}); - REQUIRE(PopSchemeMPL().FastAggregateVerify({pk1, pk2, pk3}, message, popSigAgg)); + REQUIRE(PopSchemeMPL().FastAggregateVerify( + {pk1, pk2, pk3}, message, popSigAgg)); // Aggregate public key, indistinguishable from a single public key G1Element popAggPk = pk1 + pk2 + pk3; @@ -952,17 +1089,20 @@ TEST_CASE("Advanced") { PrivateKey aggSk = PrivateKey::Aggregate({sk1, sk2, sk3}); REQUIRE(PopSchemeMPL().Sign(aggSk, message) == popSigAgg); - PrivateKey masterSk = AugSchemeMPL().KeyGen(seed); PrivateKey child = AugSchemeMPL().DeriveChildSk(masterSk, 152); PrivateKey grandchild = AugSchemeMPL().DeriveChildSk(child, 952); G1Element masterPk = masterSk.GetG1Element(); - PrivateKey childU = AugSchemeMPL().DeriveChildSkUnhardened(masterSk, 22); - PrivateKey grandchildU = AugSchemeMPL().DeriveChildSkUnhardened(childU, 0); + PrivateKey childU = + AugSchemeMPL().DeriveChildSkUnhardened(masterSk, 22); + PrivateKey grandchildU = + AugSchemeMPL().DeriveChildSkUnhardened(childU, 0); - G1Element childUPk = AugSchemeMPL().DeriveChildPkUnhardened(masterPk, 22); - G1Element grandchildUPk = AugSchemeMPL().DeriveChildPkUnhardened(childUPk, 0); + G1Element childUPk = + AugSchemeMPL().DeriveChildPkUnhardened(masterPk, 22); + G1Element grandchildUPk = + AugSchemeMPL().DeriveChildPkUnhardened(childUPk, 0); REQUIRE(grandchildUPk == grandchildU.GetG1Element()); } @@ -984,12 +1124,16 @@ TEST_CASE("Advanced") { G2Element g2Bytes = G2Element::FromBytes(Bytes(vecG2Element)); REQUIRE(g2Vector == g2Bytes); - G1Element g1MessageVector = G1Element::FromMessage(vecHash, vecHash.data(), vecHash.size()); - G1Element g1MessageBytes = G1Element::FromMessage(Bytes(vecHash), vecHash.data(), vecHash.size()); + G1Element g1MessageVector = + G1Element::FromMessage(vecHash, vecHash.data(), vecHash.size()); + G1Element g1MessageBytes = G1Element::FromMessage( + Bytes(vecHash), vecHash.data(), vecHash.size()); REQUIRE(g1MessageVector == g1MessageBytes); - G2Element g2MessageVector = G2Element::FromMessage(vecHash, vecHash.data(), vecHash.size()); - G2Element g2MessageBytes = G2Element::FromMessage(Bytes(vecHash), vecHash.data(), vecHash.size()); + G2Element g2MessageVector = + G2Element::FromMessage(vecHash, vecHash.data(), vecHash.size()); + G2Element g2MessageBytes = G2Element::FromMessage( + Bytes(vecHash), vecHash.data(), vecHash.size()); REQUIRE(g2MessageVector == g2MessageBytes); G1Element g1_1 = pk1.GetG1Element(); @@ -997,29 +1141,41 @@ TEST_CASE("Advanced") { G1Element g1_3 = pk3.GetG1Element(); G2Element g2BasicSignVector1 = BasicSchemeMPL().Sign(pk1, vecHash); - G2Element g2BasicSignBytes1 = BasicSchemeMPL().Sign(pk1, Bytes(vecHash)); + G2Element g2BasicSignBytes1 = + BasicSchemeMPL().Sign(pk1, Bytes(vecHash)); REQUIRE(g2BasicSignVector1 == g2BasicSignBytes1); G2Element g2BasicSign2 = BasicSchemeMPL().Sign(pk2, Bytes(vecHash)); - G2Element g2BasicSign3 = BasicSchemeMPL().Sign(pk3, Bytes(vecG2Element)); + G2Element g2BasicSign3 = + BasicSchemeMPL().Sign(pk3, Bytes(vecG2Element)); REQUIRE(g2BasicSignVector1 != g2BasicSign2); - REQUIRE(BasicSchemeMPL().Verify(Bytes(g1_1.Serialize()), Bytes(vecHash), Bytes(g2BasicSignVector1.Serialize()))); - REQUIRE(BasicSchemeMPL().Verify(g1_1, Bytes(vecHash), g2BasicSignVector1)); + REQUIRE(BasicSchemeMPL().Verify( + Bytes(g1_1.Serialize()), + Bytes(vecHash), + Bytes(g2BasicSignVector1.Serialize()))); + REQUIRE( + BasicSchemeMPL().Verify(g1_1, Bytes(vecHash), g2BasicSignVector1)); - vector> vecG1Vector = {g1_1.Serialize(), g1_3.Serialize()}; - vector> vecG2Vector = {g2BasicSignVector1.Serialize(), g2BasicSign3.Serialize()}; + vector> vecG1Vector = { + g1_1.Serialize(), g1_3.Serialize()}; + vector> vecG2Vector = { + g2BasicSignVector1.Serialize(), g2BasicSign3.Serialize()}; vector> vecHashes = {vecHash, vecG2Element}; auto aggVector = BasicSchemeMPL().Aggregate(vecG2Vector); - auto aggBytes = BasicSchemeMPL().Aggregate(vector{vecG2Vector.begin(), vecG2Vector.end()}); + auto aggBytes = BasicSchemeMPL().Aggregate( + vector{vecG2Vector.begin(), vecG2Vector.end()}); REQUIRE(aggVector == aggBytes); - REQUIRE(BasicSchemeMPL().AggregateVerify(vector{vecG1Vector.begin(), vecG1Vector.end()}, - vector{vecHashes.begin(), vecHashes.end()}, - Bytes(aggVector))); - REQUIRE(BasicSchemeMPL().AggregateVerify({g1_1, g1_3}, - vector{vecHashes.begin(), vecHashes.end()}, - G2Element::FromBytes(aggVector))); + + REQUIRE(BasicSchemeMPL().AggregateVerify( + vector{vecG1Vector.begin(), vecG1Vector.end()}, + vector{vecHashes.begin(), vecHashes.end()}, + Bytes(aggVector))); + REQUIRE(BasicSchemeMPL().AggregateVerify( + {g1_1, g1_3}, + vector{vecHashes.begin(), vecHashes.end()}, + G2Element::FromBytes(aggVector))); G2Element g2AugSignVector1 = AugSchemeMPL().Sign(pk1, vecHash); G2Element g2AugSignBytes1 = AugSchemeMPL().Sign(pk1, Bytes(vecHash)); @@ -1027,40 +1183,53 @@ TEST_CASE("Advanced") { REQUIRE(g2AugSignVector1 == g2AugSignBytes1); REQUIRE(g2AugSignVector1 != g2AugSign2); - REQUIRE(AugSchemeMPL().Verify(Bytes(g1_1.Serialize()), Bytes(vecHash), Bytes(g2AugSignVector1.Serialize()))); + REQUIRE(AugSchemeMPL().Verify( + Bytes(g1_1.Serialize()), + Bytes(vecHash), + Bytes(g2AugSignVector1.Serialize()))); REQUIRE(AugSchemeMPL().Verify(g1_1, Bytes(vecHash), g2AugSignVector1)); - vector> vecG1AugVector = {g1_1.Serialize(), g1_2.Serialize()}; - vector> vecG2AugVector = {g2AugSignVector1.Serialize(), g2AugSign2.Serialize()}; + vector> vecG1AugVector = { + g1_1.Serialize(), g1_2.Serialize()}; + vector> vecG2AugVector = { + g2AugSignVector1.Serialize(), g2AugSign2.Serialize()}; auto aggAugVector = AugSchemeMPL().Aggregate(vecG2AugVector); - auto aggAugBytes = AugSchemeMPL().Aggregate(vector{vecG2AugVector.begin(), vecG2AugVector.end()}); + auto aggAugBytes = AugSchemeMPL().Aggregate( + vector{vecG2AugVector.begin(), vecG2AugVector.end()}); REQUIRE(aggAugVector == aggAugBytes); - REQUIRE(AugSchemeMPL().AggregateVerify(vector{vecG1AugVector.begin(), vecG1AugVector.end()}, - vector{vecHashes.begin(), vecHashes.end()}, - Bytes(aggAugVector))); - REQUIRE(AugSchemeMPL().AggregateVerify({g1_1, g1_2}, - vector{vecHashes.begin(), vecHashes.end()}, - G2Element::FromBytes(aggAugVector))); + REQUIRE(AugSchemeMPL().AggregateVerify( + vector{vecG1AugVector.begin(), vecG1AugVector.end()}, + vector{vecHashes.begin(), vecHashes.end()}, + Bytes(aggAugVector))); + REQUIRE(AugSchemeMPL().AggregateVerify( + {g1_1, g1_2}, + vector{vecHashes.begin(), vecHashes.end()}, + G2Element::FromBytes(aggAugVector))); G2Element proof = PopSchemeMPL().PopProve(pk1); REQUIRE(PopSchemeMPL().PopVerify(g1_1, proof)); - REQUIRE(PopSchemeMPL().PopVerify(Bytes(g1_1.Serialize()), Bytes(proof.Serialize()))); + REQUIRE(PopSchemeMPL().PopVerify( + Bytes(g1_1.Serialize()), Bytes(proof.Serialize()))); G2Element g2Pop1 = PopSchemeMPL().Sign(pk1, vecHash); G2Element g2Pop2 = PopSchemeMPL().Sign(pk2, vecHash); G2Element g2PopAgg = PopSchemeMPL().Aggregate({g2Pop1, g2Pop2}); vecG1Vector = {g1_1.Serialize(), g1_2.Serialize()}; - REQUIRE(PopSchemeMPL().FastAggregateVerify({g1_1, g1_2}, Bytes(vecHash), g2PopAgg)); - REQUIRE(PopSchemeMPL().FastAggregateVerify(vector{vecG1Vector.begin(), vecG1Vector.end()}, - Bytes(vecHash), Bytes(g2PopAgg.Serialize()))); + REQUIRE(PopSchemeMPL().FastAggregateVerify( + {g1_1, g1_2}, Bytes(vecHash), g2PopAgg)); + REQUIRE(PopSchemeMPL().FastAggregateVerify( + vector{vecG1Vector.begin(), vecG1Vector.end()}, + Bytes(vecHash), + Bytes(g2PopAgg.Serialize()))); } } - -TEST_CASE("Schemes") { - SECTION("Basic Scheme") { +TEST_CASE("Schemes") +{ + SECTION("Basic Scheme") + { vector seed1(32, 0x04); vector seed2(32, 0x05); std::array msg1 = {7, 8, 9}; @@ -1073,7 +1242,6 @@ TEST_CASE("Schemes") { G2Element sig1 = BasicSchemeMPL().Sign(sk1, msg1); vector sig1v = BasicSchemeMPL().Sign(sk1, msg1).Serialize(); - REQUIRE(BasicSchemeMPL().Verify(pk1v, msg1, sig1v)); PrivateKey sk2 = BasicSchemeMPL().KeyGen(seed2); @@ -1093,7 +1261,8 @@ TEST_CASE("Schemes") { REQUIRE(BasicSchemeMPL().Verify(pk2v, msg1, sig1v) == false); G2Element aggsig = BasicSchemeMPL().Aggregate({sig1, sig2}); - auto aggsigv = BasicSchemeMPL().Aggregate(vector>{sig1v, sig2v}); + auto aggsigv = + BasicSchemeMPL().Aggregate(vector>{sig1v, sig2v}); REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk2}, msgs, aggsig)); REQUIRE(BasicSchemeMPL().AggregateVerify({pk1v, pk2v}, msgs, aggsigv)); } @@ -1132,7 +1301,8 @@ TEST_CASE("Schemes") { REQUIRE(AugSchemeMPL().Verify(pk2v, msg1, sig1v) == false); G2Element aggsig = AugSchemeMPL().Aggregate({sig1, sig2}); - auto aggsigv = AugSchemeMPL().Aggregate(vector>{sig1v, sig2v}); + auto aggsigv = + AugSchemeMPL().Aggregate(vector>{sig1v, sig2v}); REQUIRE(AugSchemeMPL().AggregateVerify({pk1, pk2}, msgs, aggsig)); REQUIRE(AugSchemeMPL().AggregateVerify({pk1v, pk2v}, msgs, Bytes(aggsigv.data(), aggsigv.size()))); } @@ -1171,7 +1341,8 @@ TEST_CASE("Schemes") { REQUIRE(PopSchemeMPL().Verify(pk2v, msg1, sig1v) == false); G2Element aggsig = PopSchemeMPL().Aggregate({sig1, sig2}); - auto aggsigv = PopSchemeMPL().Aggregate(vector>{sig1v, sig2v}); + auto aggsigv = + PopSchemeMPL().Aggregate(vector>{sig1v, sig2v}); REQUIRE(PopSchemeMPL().AggregateVerify({pk1, pk2}, msgs, aggsig)); REQUIRE(PopSchemeMPL().AggregateVerify({pk1v, pk2v}, msgs, Bytes(aggsigv.data(), aggsigv.size()))); @@ -1186,8 +1357,8 @@ TEST_CASE("Schemes") { G2Element sig2_same = PopSchemeMPL().Sign(sk2, msg1); vector sig2v_same = PopSchemeMPL().Sign(sk2, msg1).Serialize(); G2Element aggsig_same = PopSchemeMPL().Aggregate({sig1, sig2_same}); - auto aggsigv_same = - PopSchemeMPL().Aggregate(vector>{sig1v, sig2v_same}); + auto aggsigv_same = PopSchemeMPL().Aggregate( + vector>{sig1v, sig2v_same}); REQUIRE( PopSchemeMPL().FastAggregateVerify({pk1, pk2}, msg1, aggsig_same)); REQUIRE(PopSchemeMPL().FastAggregateVerify( @@ -1245,8 +1416,7 @@ TEST_CASE("Schemes") { legacySigs.push_back(legacyScheme.Sign(sk, message)); } - G2Element legacySecureAggSig; - REQUIRE_NOTHROW(legacySecureAggSig = legacyScheme.AggregateSecure(legacyPks, legacySigs, message)); + G2Element legacySecureAggSig = legacyScheme.AggregateSecure(legacyPks, legacySigs, message); REQUIRE(legacyScheme.VerifySecure(legacyPks, legacySecureAggSig, message)); } @@ -1368,9 +1538,11 @@ TEST_CASE("Legacy HD keys") { .GetPublicKey(); REQUIRE(sk3.GetG1Element() == pk4); - G2Element sig = LegacySchemeMPL().Sign(sk3, Bytes(seed)); + // the legacy scheme signs 32-byte message hashes + std::vector hash(32, 0x42); + G2Element sig = LegacySchemeMPL().Sign(sk3, Bytes(hash)); - REQUIRE(LegacySchemeMPL().Verify(sk3.GetG1Element(), Bytes(seed), sig)); + REQUIRE(LegacySchemeMPL().Verify(sk3.GetG1Element(), Bytes(hash), sig)); } SECTION("Should prevent hardened pk derivation") { @@ -1402,7 +1574,8 @@ TEST_CASE("Legacy HD keys") { cout << epk.GetPublicKey() << endl; cout << epk.GetChainCode() << endl; - G2Element sig1 = LegacySchemeMPL().Sign(esk.GetPrivateKey(), Bytes(seed)); + std::vector hash(32, 0x42); + G2Element sig1 = LegacySchemeMPL().Sign(esk.GetPrivateKey(), Bytes(hash)); cout << sig1 << endl; } @@ -1518,7 +1691,8 @@ TEST_CASE("Threshold Signatures") { TEST_CASE("CheckValid") { - SECTION("Valid points should succeed") { + SECTION("Valid points should succeed") + { vector seed(32, 0x05); vector msg1 = {10, 11, 12}; @@ -1540,37 +1714,464 @@ TEST_CASE("CheckValid") G1Element::FromBytes(Bytes(Util::HexToBytes(badPointHex)))); // FromBytesUnchecked does not throw - G1Element pk = + G1Element bad_pk = G1Element::FromBytesUnchecked(Bytes(Util::HexToBytes(badPointHex))); - REQUIRE(pk.IsValid() == false); - REQUIRE_THROWS(pk.CheckValid()); + REQUIRE(bad_pk.IsValid() == false); + REQUIRE_THROWS(bad_pk.CheckValid()); vector seed(32, 0x05); vector msg1 = {10, 11, 12}; PrivateKey sk1 = BasicSchemeMPL().KeyGen(seed); - G1Element pk1 = BasicSchemeMPL().SkToG1(sk1); + G1Element good_pk = BasicSchemeMPL().SkToG1(sk1); + REQUIRE(good_pk.IsValid() == true); G2Element sig1 = AugSchemeMPL().Sign(sk1, msg1); - REQUIRE(AugSchemeMPL().Verify(pk, msg1, sig1) == false); + REQUIRE(AugSchemeMPL().Verify(bad_pk, msg1, sig1) == false); + REQUIRE(AugSchemeMPL().Verify(good_pk, msg1, sig1) == true); } - SECTION("Invalid G2 points should not succeed") { - g2_t point_native; - g2_set_infty(point_native); - fp2_rand(point_native->x); - fp2_rand(point_native->y); - fp2_rand(point_native->z); + SECTION("Invalid G2 points should not succeed") + { + blst_p2 point_native; + memset(&point_native, 0, sizeof(blst_p2)); + + // fixed garbage coordinates: not on the curve and not infinity + memset(&(point_native.x), 0x11, sizeof(point_native.x)); + memset(&(point_native.y), 0x22, sizeof(point_native.y)); + memset(&(point_native.z), 0x33, sizeof(point_native.z)); G2Element point = G2Element::FromNative(point_native); REQUIRE(point.IsValid() == false); REQUIRE_THROWS(point.CheckValid()); auto badSer = point.Serialize(); - std::cout < pks = {G1Element()}; + vector msgs = {Bytes(msg)}; + REQUIRE(LegacySchemeMPL().AggregateVerify(pks, msgs, sig) == false); + } + + SECTION("AggregateVerify rejects identity signature with non-empty pubkeys") + { + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto msg = getRandomSeed(); + vector pks = {pk}; + vector msgs = {Bytes(msg)}; + REQUIRE(LegacySchemeMPL().AggregateVerify(pks, msgs, G2Element()) == false); + } + + SECTION("Verify rejects malformed non-identity pubkey") + { + string badPointHex = + "8d5d0fb73b9c92df4eab4216e48c3e358578b4cc30f82c268bd6fef3bd34b558628daf1afef798d4c3b0fcd8b28c8973"; + G1Element badPk = G1Element::FromBytesUnchecked(Bytes(Util::HexToBytes(badPointHex))); + REQUIRE(badPk.IsValid() == false); + + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = LegacySchemeMPL().Sign(sk, Bytes(msg)); + REQUIRE(LegacySchemeMPL().Verify(badPk, Bytes(msg), sig) == false); + } + + SECTION("Verify rejects malformed non-identity signature") + { + // Build an invalid G2 element from native coordinates: + // (-x, y) of the generator: not on the curve + blst_p2 point_native = *blst_p2_generator(); + blst_fp2_cneg(&point_native.x, &point_native.x, true); + G2Element badSig = G2Element::FromNative(point_native); + REQUIRE(badSig.IsValid() == false); + + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto msg = getRandomSeed(); + REQUIRE(LegacySchemeMPL().Verify(pk, Bytes(msg), badSig) == false); + } + + SECTION("AggregateVerify rejects malformed non-identity pubkey") + { + string badPointHex = + "8d5d0fb73b9c92df4eab4216e48c3e358578b4cc30f82c268bd6fef3bd34b558628daf1afef798d4c3b0fcd8b28c8973"; + G1Element badPk = G1Element::FromBytesUnchecked(Bytes(Util::HexToBytes(badPointHex))); + + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = LegacySchemeMPL().Sign(sk, Bytes(msg)); + vector pks = {badPk}; + vector msgs = {Bytes(msg)}; + REQUIRE(LegacySchemeMPL().AggregateVerify(pks, msgs, sig) == false); + } +} + +TEST_CASE("VerifySecure calls CoreMPL::AggregateVerify directly") +{ + SECTION("BasicSchemeMPL VerifySecure round-trips correctly") + { + auto sk1 = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto sk2 = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto pk1 = sk1.GetG1Element(); + auto pk2 = sk2.GetG1Element(); + auto msg = getRandomSeed(); + + auto sig1 = BasicSchemeMPL().Sign(sk1, msg); + auto sig2 = BasicSchemeMPL().Sign(sk2, msg); + + vector pks = {pk1, pk2}; + vector sigs = {sig1, sig2}; + auto aggSig = BasicSchemeMPL().AggregateSecure(pks, sigs, Bytes(msg)); + + REQUIRE(BasicSchemeMPL().VerifySecure(pks, aggSig, Bytes(msg))); + } + + SECTION("AugSchemeMPL VerifySecure round-trips correctly") + { + auto sk1 = AugSchemeMPL().KeyGen(getRandomSeed()); + auto sk2 = AugSchemeMPL().KeyGen(getRandomSeed()); + auto pk1 = sk1.GetG1Element(); + auto pk2 = sk2.GetG1Element(); + auto msg = getRandomSeed(); + + auto sig1 = AugSchemeMPL().Sign(sk1, msg); + auto sig2 = AugSchemeMPL().Sign(sk2, msg); + + vector pks = {pk1, pk2}; + vector sigs = {sig1, sig2}; + auto aggSig = AugSchemeMPL().AggregateSecure(pks, sigs, Bytes(msg)); + + REQUIRE(AugSchemeMPL().VerifySecure(pks, aggSig, Bytes(msg))); + } + + SECTION("BasicSchemeMPL VerifySecure rejects identity pubkey") + { + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = BasicSchemeMPL().Sign(sk, msg); + + vector pks = {G1Element()}; + REQUIRE(BasicSchemeMPL().VerifySecure(pks, sig, Bytes(msg)) == false); + } + + SECTION("BasicSchemeMPL VerifySecure rejects identity signature") + { + auto sk1 = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto sk2 = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + + vector pks = {sk1.GetG1Element(), sk2.GetG1Element()}; + REQUIRE(BasicSchemeMPL().VerifySecure(pks, G2Element(), Bytes(msg)) == false); + } + + SECTION("AugSchemeMPL VerifySecure rejects identity pubkey") + { + auto sk = AugSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = AugSchemeMPL().Sign(sk, msg); + + vector pks = {G1Element()}; + REQUIRE(AugSchemeMPL().VerifySecure(pks, sig, Bytes(msg)) == false); + } + + SECTION("AugSchemeMPL VerifySecure rejects identity signature") + { + auto sk1 = AugSchemeMPL().KeyGen(getRandomSeed()); + auto sk2 = AugSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + + vector pks = {sk1.GetG1Element(), sk2.GetG1Element()}; + REQUIRE(AugSchemeMPL().VerifySecure(pks, G2Element(), Bytes(msg)) == false); + } +} + +TEST_CASE("PopSchemeMPL::PopVerify bytes overload consistent error handling") +{ + SECTION("Malformed pubkey bytes returns false instead of throwing") + { + vector badPk(G1Element::SIZE, 0xff); + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto pop = PopSchemeMPL().PopProve(sk); + auto popBytes = pop.Serialize(); + REQUIRE_NOTHROW(PopSchemeMPL().PopVerify(Bytes(badPk), Bytes(popBytes))); + REQUIRE(PopSchemeMPL().PopVerify(Bytes(badPk), Bytes(popBytes)) == false); + } + + SECTION("Malformed proof bytes returns false instead of throwing") + { + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto pkBytes = pk.Serialize(); + vector badProof(G2Element::SIZE, 0xff); + REQUIRE_NOTHROW(PopSchemeMPL().PopVerify(Bytes(pkBytes), Bytes(badProof))); + REQUIRE(PopSchemeMPL().PopVerify(Bytes(pkBytes), Bytes(badProof)) == false); + } + + SECTION("Valid proof still verifies through bytes overload") + { + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto pop = PopSchemeMPL().PopProve(sk); + auto pkBytes = pk.Serialize(); + auto popBytes = pop.Serialize(); + REQUIRE(PopSchemeMPL().PopVerify(Bytes(pkBytes), Bytes(popBytes))); + } +} + +TEST_CASE("Bytes overloads return false on malformed input instead of throwing") +{ + SECTION("CoreMPL::Verify with malformed pubkey bytes") + { + vector badPk(G1Element::SIZE, 0xff); + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = BasicSchemeMPL().Sign(sk, msg); + auto sigBytes = sig.Serialize(); + REQUIRE_NOTHROW(BasicSchemeMPL().Verify(Bytes(badPk), Bytes(msg), Bytes(sigBytes))); + REQUIRE(BasicSchemeMPL().Verify(Bytes(badPk), Bytes(msg), Bytes(sigBytes)) == false); + } + + SECTION("CoreMPL::Verify with malformed signature bytes") + { + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto pkBytes = pk.Serialize(); + auto msg = getRandomSeed(); + vector badSig(G2Element::SIZE, 0xff); + REQUIRE_NOTHROW(BasicSchemeMPL().Verify(Bytes(pkBytes), Bytes(msg), Bytes(badSig))); + REQUIRE(BasicSchemeMPL().Verify(Bytes(pkBytes), Bytes(msg), Bytes(badSig)) == false); + } + + SECTION("CoreMPL::AggregateVerify with malformed pubkey bytes") + { + vector badPk(G1Element::SIZE, 0xff); + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = BasicSchemeMPL().Sign(sk, msg); + auto sigBytes = sig.Serialize(); + vector pks = {Bytes(badPk)}; + vector msgs = {Bytes(msg)}; + REQUIRE_NOTHROW(BasicSchemeMPL().AggregateVerify(pks, msgs, Bytes(sigBytes))); + REQUIRE(BasicSchemeMPL().AggregateVerify(pks, msgs, Bytes(sigBytes)) == false); + } + + SECTION("CoreMPL::AggregateVerify with malformed signature bytes") + { + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto pkBytes = pk.Serialize(); + auto msg = getRandomSeed(); + vector badSig(G2Element::SIZE, 0xff); + vector pks = {Bytes(pkBytes)}; + vector msgs = {Bytes(msg)}; + REQUIRE_NOTHROW(BasicSchemeMPL().AggregateVerify(pks, msgs, Bytes(badSig))); + REQUIRE(BasicSchemeMPL().AggregateVerify(pks, msgs, Bytes(badSig)) == false); + } + + SECTION("FastAggregateVerify with malformed pubkey bytes") + { + vector badPk(G1Element::SIZE, 0xff); + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = PopSchemeMPL().Sign(sk, msg); + auto sigBytes = sig.Serialize(); + vector pks = {Bytes(badPk)}; + REQUIRE_NOTHROW(PopSchemeMPL().FastAggregateVerify(pks, Bytes(msg), Bytes(sigBytes))); + REQUIRE(PopSchemeMPL().FastAggregateVerify(pks, Bytes(msg), Bytes(sigBytes)) == false); + } + + SECTION("AugSchemeMPL::AggregateVerify with malformed signature bytes") + { + auto sk = AugSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto pkBytes = pk.Serialize(); + auto msg = getRandomSeed(); + vector badSig(G2Element::SIZE, 0xff); + vector pks = {Bytes(pkBytes)}; + vector msgs = {Bytes(msg)}; + REQUIRE_NOTHROW(AugSchemeMPL().AggregateVerify(pks, msgs, Bytes(badSig))); + REQUIRE(AugSchemeMPL().AggregateVerify(pks, msgs, Bytes(badSig)) == false); + } +} + +TEST_CASE("PopSchemeMPL::PopVerify rejects identity elements") +{ + SECTION("PopVerify rejects identity pubkey") + { + REQUIRE(PopSchemeMPL().PopVerify(G1Element(), G2Element()) == false); + } + + SECTION("PopVerify rejects identity proof with valid pubkey") + { + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + REQUIRE(PopSchemeMPL().PopVerify(pk, G2Element()) == false); + } +} + +TEST_CASE("FastAggregateVerify rejects identity elements") +{ + SECTION("Identity pubkey in list is rejected") + { + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto msg = getRandomSeed(); + auto sig = PopSchemeMPL().Sign(sk, msg); + vector pks = {pk, G1Element()}; + REQUIRE(PopSchemeMPL().FastAggregateVerify(pks, Bytes(msg), sig) == false); + } + + SECTION("All identity pubkeys rejected") + { + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = PopSchemeMPL().Sign(sk, msg); + vector pks = {G1Element()}; + REQUIRE(PopSchemeMPL().FastAggregateVerify(pks, Bytes(msg), sig) == false); + } + + SECTION("Identity signature rejected") + { + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto msg = getRandomSeed(); + vector pks = {pk}; + REQUIRE(PopSchemeMPL().FastAggregateVerify(pks, Bytes(msg), G2Element()) == false); + } + + SECTION("Malformed non-identity signature rejected") + { + // (-x, y) of the generator: not on the curve + blst_p2 point_native = *blst_p2_generator(); + blst_fp2_cneg(&point_native.x, &point_native.x, true); + G2Element badSig = G2Element::FromNative(point_native); + REQUIRE(badSig.IsValid() == false); + + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto msg = getRandomSeed(); + vector pks = {pk}; + REQUIRE(PopSchemeMPL().FastAggregateVerify(pks, Bytes(msg), badSig) == false); + } +} + +TEST_CASE("G1 zeros-only check masks the flag bits of the first byte") +{ + // 0x85 || 47 zero bytes encodes x = 5 * 2^376, not an all-zero payload. + // relic decompressed it to an on-curve point outside the subgroup, so the + // unchecked decoder must do the same and the checked one must reject it + // for that reason, as the G2 decoder already does. + std::vector in(48, 0); + in[0] = 0x85; + G1Element u = G1Element::FromBytesUnchecked(Bytes(in)); + REQUIRE(!u.IsValid()); + REQUIRE(u.Serialize() == in); + REQUIRE_THROWS(G1Element::FromBytes(Bytes(in))); +} + +TEST_CASE("IsValid rejects points off the curve") +{ + // (4x, 8y, z) of the generator is not on the curve but passes blst's + // subgroup test, which assumes a curve point + uint8_t be[48] = {0}; + blst_fp four, eight; + be[47] = 4; + blst_fp_from_bendian(&four, be); + be[47] = 8; + blst_fp_from_bendian(&eight, be); + + blst_p1 off1 = *blst_p1_generator(); + blst_fp_mul(&off1.x, &off1.x, &four); + blst_fp_mul(&off1.y, &off1.y, &eight); + REQUIRE(!G1Element::FromNative(off1).IsValid()); + + blst_p2 off2 = *blst_p2_generator(); + blst_fp2 four2, eight2; + memset(&four2, 0, sizeof(four2)); + memset(&eight2, 0, sizeof(eight2)); + four2.fp[0] = four; + eight2.fp[0] = eight; + blst_fp2_mul(&off2.x, &off2.x, &four2); + blst_fp2_mul(&off2.y, &off2.y, &eight2); + REQUIRE(!G2Element::FromNative(off2).IsValid()); +} + +TEST_CASE("Degenerate legacy signatures do not verify") +{ + // A legacy G2 decode of x = (0, 0) with no square root leaves the point + // (0, 0, 1): not infinity, but (0, 0) in affine form. IsValid() rejects + // it before the pairing product. + std::vector h(32, 0x11); + G1Element g = G1Element::Generator(); + std::vector pp(96, 0); // c0 = p, c1 = p, both read as zero + const std::vector p = Util::HexToBytes( + "1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab"); + std::copy(p.begin(), p.end(), pp.begin()); + std::copy(p.begin(), p.end(), pp.begin() + 48); + for (const std::vector& in : {std::vector(96, 0), pp}) { + G2Element bad = G2Element::FromBytes(Bytes(in), true); + REQUIRE(!LegacySchemeMPL().Verify(G1Element(), Bytes(h), bad)); + REQUIRE(!LegacySchemeMPL().Verify(g, Bytes(h), bad)); + std::vector pks{g, g.Negate()}; + std::vector msgs{Bytes(h), Bytes(h)}; + REQUIRE(!LegacySchemeMPL().AggregateVerify(pks, msgs, bad)); + } +} + +TEST_CASE("Legacy verification rejects messages that are not 32 bytes") +{ + PrivateKey sk = BasicSchemeMPL().KeyGen(std::vector(32, 0x55)); + std::vector h(32, 0x11); + G2Element sig = LegacySchemeMPL().Sign(sk, Bytes(h)); + REQUIRE(LegacySchemeMPL().Verify(sk.GetG1Element(), Bytes(h), sig)); + std::vector h31(31, 0x11), h33(33, 0x11); + REQUIRE(!LegacySchemeMPL().Verify(sk.GetG1Element(), Bytes(h31), sig)); + REQUIRE(!LegacySchemeMPL().Verify(sk.GetG1Element(), Bytes(h33), sig)); + REQUIRE_THROWS(LegacySchemeMPL().Sign(sk, Bytes(h31))); +} + +TEST_CASE("Secure aggregation rejects an infinity public key") +{ + BasicSchemeMPL basic; + vector seed1(32, 0x11); + vector seed2(32, 0x22); + vector msg(32, 0x33); + PrivateKey sk1 = basic.KeyGen(seed1); + PrivateKey sk2 = basic.KeyGen(seed2); + vector pks = {sk1.GetG1Element(), sk2.GetG1Element()}; + vector sigs = {basic.Sign(sk1, msg), basic.Sign(sk2, msg)}; + + // positive control first, then only the second key changes + G2Element agg = basic.AggregateSecure(pks, sigs, Bytes(msg)); + REQUIRE(basic.VerifySecure(pks, agg, Bytes(msg))); + pks[1] = G1Element(); + REQUIRE(!basic.VerifySecure(pks, agg, Bytes(msg))); +} + TEST_CASE("CheckValid for Legacy") { SECTION("Invalid G1 points should throw in CheckValid but not in FromBytes") @@ -1620,6 +2221,114 @@ TEST_CASE("CheckValid for Legacy") } } +// Locates test-vectors/reference.txt: an environment variable overrides +// the path the build system compiled in; source-tree-relative paths cover +// running the binary by hand. +static std::string ReferenceVectorsPath() +{ + std::vector candidates; + if (const char* env = std::getenv("DASHBLS_REFERENCE_VECTORS")) { + candidates.push_back(env); + } +#ifdef DASHBLS_REFERENCE_VECTORS + candidates.push_back(DASHBLS_REFERENCE_VECTORS); +#endif + candidates.push_back("test-vectors/reference.txt"); + candidates.push_back("../test-vectors/reference.txt"); + candidates.push_back("../../test-vectors/reference.txt"); + for (const auto& c : candidates) { + if (std::ifstream(c).good()) return c; + } + std::string tried; + for (const auto& c : candidates) tried += "\n " + c; + FAIL("reference vectors not found; tried:" << tried); + return ""; +} + +TEST_CASE("Reference vectors") +{ + // Every consensus-visible behavior of the library, compared line by line + // against the output of the relic-based implementation. + const std::string path = ReferenceVectorsPath(); + INFO("reference file: " << path); + + std::vector expected; + std::ifstream in(path); + for (std::string line; std::getline(in, line);) { + if (line.empty() || line[0] == '#') continue; + expected.push_back(line); + } + REQUIRE(expected.size() > 300); + + std::vector actual; + for (const auto& line : bls_test_vectors::GenerateReferenceVectors()) { + if (line.empty() || line[0] == '#') continue; + actual.push_back(line); + } + + REQUIRE(actual.size() == expected.size()); + for (size_t i = 0; i < expected.size(); i++) { + INFO("vector " << i + 1 << " of " << expected.size()); + REQUIRE(actual[i] == expected[i]); + } +} + +TEST_CASE("GTElement") +{ + SECTION("GTElement serialization") + { + vector seed(32, 0x05); + blst_p1_affine p1_affine; + + PrivateKey sk1 = BasicSchemeMPL().KeyGen(seed); + G1Element pk1 = BasicSchemeMPL().SkToG1(sk1); + pk1.CheckValid(); + pk1.ToAffine(&p1_affine); + GTElement gt1 = GTElement::FromAffine(p1_affine); + + auto outbuf = gt1.Serialize(); + + auto gt2 = GTElement::FromBytesUnchecked(outbuf); + + REQUIRE(gt1 == gt2); + } + + SECTION("GTElement pairing") + { + vector seed(32, 0x05), seed2(32, 0x06); + vector msg1 = {7, 8, 9}; + vector msg2 = {10, 11, 12}; + + auto sk1 = BasicSchemeMPL().KeyGen(seed); + auto sk2 = BasicSchemeMPL().KeyGen(seed2); + + auto pk1 = sk1.GetG1Element(); + auto pk2 = sk2.GetG1Element(); + + auto sig1 = BasicSchemeMPL().Sign(sk1, msg1); + auto sig2 = BasicSchemeMPL().Sign(sk2, msg2); + + auto aggsig = BasicSchemeMPL().Aggregate({sig1, sig2}); + + REQUIRE(BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{msg1, msg2}, aggsig)); + + auto pair1 = pk1.Pair(G2Element::FromMessage( + msg1, + (const uint8_t*)BasicSchemeMPL::CIPHERSUITE_ID.c_str(), + BasicSchemeMPL::CIPHERSUITE_ID.length())); + auto pair2 = pk2.Pair(G2Element::FromMessage( + msg2, + (const uint8_t*)BasicSchemeMPL::CIPHERSUITE_ID.c_str(), + BasicSchemeMPL::CIPHERSUITE_ID.length())); + auto pair = pair1 * pair2; + + auto agg_sig_pair = G1Element::Generator().Pair(aggsig); + + REQUIRE(pair == agg_sig_pair); + } +} + int main(int argc, char* argv[]) { int result = Catch::Session().run(argc, argv); diff --git a/src/dashbls/src/threshold.cpp b/src/dashbls/src/threshold.cpp index 4561dccdc3a6..8526832b7718 100644 --- a/src/dashbls/src/threshold.cpp +++ b/src/dashbls/src/threshold.cpp @@ -7,75 +7,9 @@ #include "threshold.hpp" #include "schemes.hpp" -#include "bn_helpers.hpp" static std::unique_ptr pThresholdScheme(new bls::LegacySchemeMPL); -/** - * Inverts a prime field element using the Euclidean Extended Algorithm, - * using bns and a custom prime modulus. - * - * @param[out] c - the result. - * @param[in] a - the prime field element to invert. - * @param[in] p - the custom prime modulus. - */ -static void fp_inv_exgcd_bn(bn_t c, const bn_t u_in, const bn_t p) { - bn_t u, v, g1, g2, q, r; - - bn_null(u); - bn_null(v); - bn_null(g1); - bn_null(g2); - bn_null(q); - bn_null(r); - - RLC_TRY { - bn_new(u); - bn_new(v); - bn_new(g1); - bn_new(g2); - bn_new(q); - bn_new(r); - - /* u = a, v = p, g1 = 1, g2 = 0. */ - bn_copy(u, u_in); - bn_copy(v, p); - bn_set_dig(g1, 1); - bn_zero(g2); - - /* While (u != 1. */ - while (bn_cmp_dig(u, 1) != RLC_EQ) { - /* q = [v/u], r = v mod u. */ - bn_div_rem(q, r, v, u); - /* v = u, u = r. */ - bn_copy(v, u); - bn_copy(u, r); - /* r = g2 - q * g1. */ - bn_mul(r, q, g1); - bn_sub(r, g2, r); - /* g2 = g1, g1 = r. */ - bn_copy(g2, g1); - bn_copy(g1, r); - } - - if (bn_sign(g1) == RLC_NEG) { - bn_add(g1, g1, p); - } - bn_copy(c, g1); - } - RLC_CATCH_ANY { - RLC_THROW(ERR_CAUGHT); - } - RLC_FINALLY { - bn_free(u); - bn_free(v); - bn_free(g1); - bn_free(g2); - bn_free(q); - bn_free(r); - }; -} - namespace bls { namespace Poly { @@ -90,43 +24,32 @@ namespace bls { } // end namespace Poly struct PolyOpsBase { - bn_t order; - bn_t iv; - - PolyOpsBase() { - bn_new(order); - gt_get_ord(order); - bn_new(iv); + static bool IsZero(const blst_scalar& a) { + std::array zero{}; + return memcmp(&a, &zero, sizeof(blst_scalar)) == 0; } - ~PolyOpsBase() { - bn_free(iv); - bn_free(order); + void MulFP(blst_scalar& r, const blst_scalar& a, const blst_scalar& b) { + blst_sk_mul_n_check(&r, &a, &b); } - void MulFP(bn_t& r, const bn_t& a, const bn_t& b) { - bn_mul(r, a, b); - ModOrder(r); + void AddFP(blst_scalar& r, const blst_scalar& a, const blst_scalar& b) { + blst_sk_add_n_check(&r, &a, &b); } - void AddFP(bn_t& r, const bn_t& a, const bn_t& b) { - bn_add(r, a, b); - ModOrder(r); + void SubFP(blst_scalar& r, const blst_scalar& a, const blst_scalar& b) { + blst_sk_sub_n_check(&r, &a, &b); } - void SubFP(bn_t& r, const bn_t& a, const bn_t& b) { - bn_sub(r, a, b); - ModOrder(r); + void DivFP(blst_scalar& r, const blst_scalar& a, const blst_scalar& b) { + blst_scalar iv; + blst_sk_inverse(&iv, &b); + blst_sk_mul_n_check(&r, &a, &iv); } - void DivFP(bn_t& r, const bn_t& a, const bn_t& b) { - fp_inv_exgcd_bn(iv, b, order); - bn_mul(r, a, iv); - ModOrder(r); - } - - void ModOrder(bn_t& r) { - bn_mod(r, r, order); + void ScalarFromBytes(blst_scalar& r, const uint8_t* bytes) { + // reduces mod the group order, like bn_read_bin + bn_mod + blst_scalar_from_be_bytes(&r, bytes, Poly::nIdSize); } }; @@ -139,7 +62,7 @@ namespace bls { return PrivateKey::Aggregate({a, b}); } - PrivateKey Mul(const PrivateKey& a, const bn_t& b) { + PrivateKey Mul(const PrivateKey& a, const blst_scalar& b) { return a * b; } }; @@ -150,7 +73,7 @@ namespace bls { return a + b; } - G1Element Mul(const G1Element& a, const bn_t& b) { + G1Element Mul(const G1Element& a, const blst_scalar& b) { return a * b; } }; @@ -161,7 +84,7 @@ namespace bls { return a + b; } - G2Element Mul(const G2Element& a, bn_t& b) { + G2Element Mul(const G2Element& a, const blst_scalar& b) { return a * b; } }; @@ -174,13 +97,12 @@ namespace bls { throw std::length_error("At least 2 coefficients required"); } - BnGuard x; - bn_read_bin(x.val, id.begin(), Poly::nIdSize); - ops.ModOrder(x.val); + blst_scalar x; + ops.ScalarFromBytes(x, id.begin()); BLSType y = vecIn.back(); for (int i = (int) vecIn.size() - 2; i >= 0; i--) { - y = ops.Mul(y, x.val); + y = ops.Mul(y, x); y = ops.Add(y, vecIn[i]); } @@ -205,35 +127,34 @@ namespace bls { */ const size_t k = vec.size(); - BnArrayGuard delta(k); - BnArrayGuard ids2(k); + std::vector delta(k); + std::vector ids2(k); for (size_t i = 0; i < k; i++) { - bn_read_bin(ids2[i], ids[i].begin(), Poly::nIdSize); - ops.ModOrder(ids2[i]); + ops.ScalarFromBytes(ids2[i], ids[i].begin()); } - BnGuard a, b, v; + blst_scalar a, b, v; - bn_copy(a.val, ids2[0]); + a = ids2[0]; for (size_t i = 1; i < k; i++) { - ops.MulFP(a.val, a.val, ids2[i]); + ops.MulFP(a, a, ids2[i]); } - if (bn_is_zero(a.val)) { + if (PolyOpsBase::IsZero(a)) { throw std::invalid_argument("Zero id"); } for (size_t i = 0; i < k; i++) { - bn_copy(b.val, ids2[i]); + b = ids2[i]; for (size_t j = 0; j < k; j++) { if (j != i) { - ops.SubFP(v.val, ids2[j], ids2[i]); - if (bn_is_zero(v.val)) { + ops.SubFP(v, ids2[j], ids2[i]); + if (PolyOpsBase::IsZero(v)) { throw std::invalid_argument("Duplicate id"); } - ops.MulFP(b.val, b.val, v.val); + ops.MulFP(b, b, v); } } - ops.DivFP(delta[i], a.val, b.val); + ops.DivFP(delta[i], a, b); } /* @@ -270,7 +191,7 @@ namespace bls { G2Element Threshold::SignatureRecover(const std::vector& sigs, const std::vector& ids) { return Poly::LagrangeInterpolate(sigs, ids); } - + G2Element Threshold::Sign(const PrivateKey& privateKey, const Bytes& vecMessage) { return pThresholdScheme->Sign(privateKey, vecMessage); } diff --git a/src/dashbls/test-vectors/reference.txt b/src/dashbls/test-vectors/reference.txt new file mode 100644 index 000000000000..3494cfe385e5 --- /dev/null +++ b/src/dashbls/test-vectors/reference.txt @@ -0,0 +1,324 @@ +# dashbls reference vectors v1 +A.sk.0=542b7d7900f6335cba45d5d7a53d59d73f26f230905bfcd6ad91ebb85eaa008a +A.pk.basic.0=9331005927ff67f0bd41be6037dcc07feea679be922e915c9be2a229c38fe5d178527877a6a66126ef4a8619277c58f0 +A.pk.legacy.0=1331005927ff67f0bd41be6037dcc07feea679be922e915c9be2a229c38fe5d178527877a6a66126ef4a8619277c58f0 +A.fp.basic.0=d4ddc775 +A.fp.legacy.0=ca704224 +A.skG2.basic.0=9131d5ad87990f02258898a22680b72d1762a084fd23f793b94477473deb23dbaf5e3a0635aa8bd373136c0bf84d4dbd03d21a5719c4b680b72be4649635262df36794ceeea24865dd55705e4370ef96346efe7795b37f27eb8ae49f134fcad0 +A.skG2.legacy.0=03d21a5719c4b680b72be4649635262df36794ceeea24865dd55705e4370ef96346efe7795b37f27eb8ae49f134fcad01131d5ad87990f02258898a22680b72d1762a084fd23f793b94477473deb23dbaf5e3a0635aa8bd373136c0bf84d4dbd +A.pk.rt.legacy.0=1331005927ff67f0bd41be6037dcc07feea679be922e915c9be2a229c38fe5d178527877a6a66126ef4a8619277c58f0 +A.pk.rt.basic.0=9331005927ff67f0bd41be6037dcc07feea679be922e915c9be2a229c38fe5d178527877a6a66126ef4a8619277c58f0 +B.lsig.legacy.0=8a3b9450bb7620dc07ff10a553ad8e55805aaf1270de68bda5c3ef581945748a3732d0bf6c44e277a92f077b53fb0cc8091006a639d501de9236351b8e6e60da58281ec4a1edab1b26b698e7150c89952ced7dec9d2a95dc492d31f68b6c47ea +B.lsig.basic.0=a91006a639d501de9236351b8e6e60da58281ec4a1edab1b26b698e7150c89952ced7dec9d2a95dc492d31f68b6c47ea0a3b9450bb7620dc07ff10a553ad8e55805aaf1270de68bda5c3ef581945748a3732d0bf6c44e277a92f077b53fb0cc8 +B.lverify.0=1 +B.lverify.bad.0=0 +B.lsig.rt.0=8a3b9450bb7620dc07ff10a553ad8e55805aaf1270de68bda5c3ef581945748a3732d0bf6c44e277a92f077b53fb0cc8091006a639d501de9236351b8e6e60da58281ec4a1edab1b26b698e7150c89952ced7dec9d2a95dc492d31f68b6c47ea +B.bsig.basic.0=8d3631d71a4f57c50f8108adb0cada2be41fba7bb1eced6e2b1757204f4103bbe41b0205cddd12a0c1f723633751eef517dc82561728b2b3482e74a4bbac58ac8851dad5247d11ad9b549690805fd078e02f39a6688e7db82f3a077c2f7dd4ab +B.bsig.legacy.0=17dc82561728b2b3482e74a4bbac58ac8851dad5247d11ad9b549690805fd078e02f39a6688e7db82f3a077c2f7dd4ab0d3631d71a4f57c50f8108adb0cada2be41fba7bb1eced6e2b1757204f4103bbe41b0205cddd12a0c1f723633751eef5 +B.bverify.0=1 +A.child.hard.0=13673dc18365d4d8d67005749ed2fba3c92dac9a259f3dac769288177d2de1ac +A.child.soft.0=43f1ad49de1fac8a337f01f27c48720cf0e453cb48cd8112c4c6aecf191c393b +A.sk.1=0d80059486148cf5dd43d6c2b42d41378e0e2cc354e328089fd5cc1eafb20549 +A.pk.basic.1=b4c69e82f075931025ea1ff15c340a0a0887f8611b7c85d02b9a1e4bcdcb22673d10a26fd3d6018e99777a302a345626 +A.pk.legacy.1=94c69e82f075931025ea1ff15c340a0a0887f8611b7c85d02b9a1e4bcdcb22673d10a26fd3d6018e99777a302a345626 +A.fp.basic.1=68f69bbe +A.fp.legacy.1=00eeb456 +A.skG2.basic.1=91005feee5588ac7887cbd365aff07a2e255cddfaff09016669f7993d68cd9a63793dcade435c0d12e875a683b3cd69a170cff1dd1e7a4e7ce4f7a3538ee76cef7b555524c2e302e4eb8ac2c759b1fa0631395df06e6eae95ca0c3aa82731576 +A.skG2.legacy.1=170cff1dd1e7a4e7ce4f7a3538ee76cef7b555524c2e302e4eb8ac2c759b1fa0631395df06e6eae95ca0c3aa8273157611005feee5588ac7887cbd365aff07a2e255cddfaff09016669f7993d68cd9a63793dcade435c0d12e875a683b3cd69a +A.pk.rt.legacy.1=94c69e82f075931025ea1ff15c340a0a0887f8611b7c85d02b9a1e4bcdcb22673d10a26fd3d6018e99777a302a345626 +A.pk.rt.basic.1=b4c69e82f075931025ea1ff15c340a0a0887f8611b7c85d02b9a1e4bcdcb22673d10a26fd3d6018e99777a302a345626 +B.lsig.legacy.1=103edb2bcadfc658095e04ccbaf682d075612fb86e2be06366fef0d1245a9ff7f87c1c8a3bc8b89a88585d9c568389ea043ae22ef8777d79719cff2cc0c777fcb16277c9f5b3a4ed782b045ecc41421b6302941ee7cfd769e645ecaea359f457 +B.lsig.basic.1=843ae22ef8777d79719cff2cc0c777fcb16277c9f5b3a4ed782b045ecc41421b6302941ee7cfd769e645ecaea359f457103edb2bcadfc658095e04ccbaf682d075612fb86e2be06366fef0d1245a9ff7f87c1c8a3bc8b89a88585d9c568389ea +B.lverify.1=1 +B.lverify.bad.1=0 +B.lsig.rt.1=103edb2bcadfc658095e04ccbaf682d075612fb86e2be06366fef0d1245a9ff7f87c1c8a3bc8b89a88585d9c568389ea043ae22ef8777d79719cff2cc0c777fcb16277c9f5b3a4ed782b045ecc41421b6302941ee7cfd769e645ecaea359f457 +B.bsig.basic.1=80f49f1b340f745c84ab7b51bbb742a6f82fbc04204398683dbcc861ed1f87fa45180c6ba9d5950347fc8d14cae6bc8f105a6d4978bf6c4333b489c656ad1eb3668f7584430a8f9c24349e6199e791e64627bde51a6af2f2905b58c12b121fb6 +B.bsig.legacy.1=105a6d4978bf6c4333b489c656ad1eb3668f7584430a8f9c24349e6199e791e64627bde51a6af2f2905b58c12b121fb600f49f1b340f745c84ab7b51bbb742a6f82fbc04204398683dbcc861ed1f87fa45180c6ba9d5950347fc8d14cae6bc8f +B.bverify.1=1 +A.child.hard.1=35bf9c36f494622db64c5173493cff599df5e765d687742cb6533b1d8c6d886d +A.child.soft.1=39827c4c7749881f819a8e5c1f4d9669d7c25c18166a71d15b633c2f89daf7e8 +A.sk.2=604f88a4ee4198b3668dc38ae604dedeb45464df19e941b57d5957a5372085d1 +A.pk.basic.2=b11bd93b3fa94ee47b60c7628a52f7731005c92dadb73f9421de7fc5ca67e816106f26d121539fbf131545c8242a8d0f +A.pk.legacy.2=911bd93b3fa94ee47b60c7628a52f7731005c92dadb73f9421de7fc5ca67e816106f26d121539fbf131545c8242a8d0f +A.fp.basic.2=919d796a +A.fp.legacy.2=0ef6fc3e +A.skG2.basic.2=835092be4610e6a7e5e131f10f58a53444c0f89fbc37250bf19157e28f0a34f211cfea8022ade9a4b8b53ae090129cf503245c6bb1356ca13f772291319fc284c1a76b396fa469bd6f32d3eccdc549ba6f95e4ca08fb3777087e006cf2caa524 +A.skG2.legacy.2=03245c6bb1356ca13f772291319fc284c1a76b396fa469bd6f32d3eccdc549ba6f95e4ca08fb3777087e006cf2caa524035092be4610e6a7e5e131f10f58a53444c0f89fbc37250bf19157e28f0a34f211cfea8022ade9a4b8b53ae090129cf5 +A.pk.rt.legacy.2=911bd93b3fa94ee47b60c7628a52f7731005c92dadb73f9421de7fc5ca67e816106f26d121539fbf131545c8242a8d0f +A.pk.rt.basic.2=b11bd93b3fa94ee47b60c7628a52f7731005c92dadb73f9421de7fc5ca67e816106f26d121539fbf131545c8242a8d0f +B.lsig.legacy.2=0c5af10db2238f74776e094771cf2d4ee5e78ac8af94a618d106b7702c0b369012e327c943f23346ca461764f48351510726329193ae51b7c98e5c215f1e79d4328d9a107d7449d9a37bc504225d0dd952cc317c36b2ff4e6e270be58583148b +B.lsig.basic.2=8726329193ae51b7c98e5c215f1e79d4328d9a107d7449d9a37bc504225d0dd952cc317c36b2ff4e6e270be58583148b0c5af10db2238f74776e094771cf2d4ee5e78ac8af94a618d106b7702c0b369012e327c943f23346ca461764f4835151 +B.lverify.2=1 +B.lverify.bad.2=0 +B.lsig.rt.2=0c5af10db2238f74776e094771cf2d4ee5e78ac8af94a618d106b7702c0b369012e327c943f23346ca461764f48351510726329193ae51b7c98e5c215f1e79d4328d9a107d7449d9a37bc504225d0dd952cc317c36b2ff4e6e270be58583148b +B.bsig.basic.2=b5a4aaf5174fc68468b7bab3b182ea6e55fb55843d17b1950383f934710cdaa6a77c4494e79ec674dfc3167bfc1d944216d3e13e435a0509da3e670ebc5aeef151f32558891e00b9e8560e47601662a8e4ea893ab20cc5e909640e33bbf41fd3 +B.bsig.legacy.2=96d3e13e435a0509da3e670ebc5aeef151f32558891e00b9e8560e47601662a8e4ea893ab20cc5e909640e33bbf41fd315a4aaf5174fc68468b7bab3b182ea6e55fb55843d17b1950383f934710cdaa6a77c4494e79ec674dfc3167bfc1d9442 +B.bverify.2=1 +A.child.hard.2=140053409896043b8b7434dc29f14d132b3cbbd139677ff397a1c10f8f364616 +A.child.soft.2=525eb8eba7332727e1b0ff22bdf6320eb401d3d5e1caebdd72b0fa8aa2f0e942 +A.sk.3=21160cba355200250e9fad6bca96ed116930dc632dce23081636fedeb106c83b +A.pk.basic.3=982f6be34861d32d8d3e5aae0395ea80bff4e25b46052f41d6453754f51cd1721d44dd9f5fb62a35ca6d367e36218d4b +A.pk.legacy.3=182f6be34861d32d8d3e5aae0395ea80bff4e25b46052f41d6453754f51cd1721d44dd9f5fb62a35ca6d367e36218d4b +A.fp.basic.3=b7fea396 +A.fp.legacy.3=f71bdf44 +A.skG2.basic.3=a9a60b869403189f7abc1abf476d8afc27e4a8502f9a4949227f03393b793050a5a16c9b89d084452ff79741fc684925188c8776bc0b799fff488f0214a3b875d543b626c18a9ac0c8b6447de08c82aa735728727458305f69f77882b9d2098a +A.skG2.legacy.3=988c8776bc0b799fff488f0214a3b875d543b626c18a9ac0c8b6447de08c82aa735728727458305f69f77882b9d2098a09a60b869403189f7abc1abf476d8afc27e4a8502f9a4949227f03393b793050a5a16c9b89d084452ff79741fc684925 +A.pk.rt.legacy.3=182f6be34861d32d8d3e5aae0395ea80bff4e25b46052f41d6453754f51cd1721d44dd9f5fb62a35ca6d367e36218d4b +A.pk.rt.basic.3=982f6be34861d32d8d3e5aae0395ea80bff4e25b46052f41d6453754f51cd1721d44dd9f5fb62a35ca6d367e36218d4b +B.lsig.legacy.3=0d58f53ad17f3877f23884799c7f8dd866e7e6feaba63da933f01e447d39b7c48d941ecab58ff845cd51aa6f1d6ce57207acf6cc920e3310dcfbc3694d8483333e2e78a578be78b645aa1cd037608bb78d05f6a8de4377c5bfa52e7f6e01bdfa +B.lsig.basic.3=87acf6cc920e3310dcfbc3694d8483333e2e78a578be78b645aa1cd037608bb78d05f6a8de4377c5bfa52e7f6e01bdfa0d58f53ad17f3877f23884799c7f8dd866e7e6feaba63da933f01e447d39b7c48d941ecab58ff845cd51aa6f1d6ce572 +B.lverify.3=1 +B.lverify.bad.3=0 +B.lsig.rt.3=0d58f53ad17f3877f23884799c7f8dd866e7e6feaba63da933f01e447d39b7c48d941ecab58ff845cd51aa6f1d6ce57207acf6cc920e3310dcfbc3694d8483333e2e78a578be78b645aa1cd037608bb78d05f6a8de4377c5bfa52e7f6e01bdfa +B.bsig.basic.3=8300e9d700c1d263e5d9caec9a3302aa8984b515bd961f25b913de852168ecc0e0dcea0913a7359bee57071208895ea812bd1ae92601ba7f2e8d6d6809330ef06dde1c8ff633cff5db38a63b5aec867d43a6e3e9bafac7aec876d6625666a5cd +B.bsig.legacy.3=12bd1ae92601ba7f2e8d6d6809330ef06dde1c8ff633cff5db38a63b5aec867d43a6e3e9bafac7aec876d6625666a5cd0300e9d700c1d263e5d9caec9a3302aa8984b515bd961f25b913de852168ecc0e0dcea0913a7359bee57071208895ea8 +B.bverify.3=1 +A.child.hard.3=58a543b659628491544fc0f85d4938820dc19d5591d53f49c8b9d950d433aff7 +A.child.soft.3=0c9bd3c62871a9e36c947f7a7ab764a69b1fdb41f9625b30bd3a5bd91484f5b6 +A.sk.4=0b23c79ec3331dd7a2d4a8708b21263330b9a9d8891a81360744a2a483ea884a +A.pk.basic.4=8564f4d30abe512e9ef8c36f903436b927feebef83329f88f50d4621d6d9b59f16316f859fe5659024cce812d9f91852 +A.pk.legacy.4=0564f4d30abe512e9ef8c36f903436b927feebef83329f88f50d4621d6d9b59f16316f859fe5659024cce812d9f91852 +A.fp.basic.4=228139d6 +A.fp.legacy.4=8710d0bc +A.skG2.basic.4=833682df2e6ae024e5d9bfb5c5dc15cb855d55e945693979abfb2078aed37421438782b7d6b17345bdac09f86563327b04f35a0374e59bc64ef3ee948dc4cd4689c4f55f298c6a5ad9703e823f853d07c958b87aa151a066d31a95cfec1da928 +A.skG2.legacy.4=04f35a0374e59bc64ef3ee948dc4cd4689c4f55f298c6a5ad9703e823f853d07c958b87aa151a066d31a95cfec1da928033682df2e6ae024e5d9bfb5c5dc15cb855d55e945693979abfb2078aed37421438782b7d6b17345bdac09f86563327b +A.pk.rt.legacy.4=0564f4d30abe512e9ef8c36f903436b927feebef83329f88f50d4621d6d9b59f16316f859fe5659024cce812d9f91852 +A.pk.rt.basic.4=8564f4d30abe512e9ef8c36f903436b927feebef83329f88f50d4621d6d9b59f16316f859fe5659024cce812d9f91852 +B.lsig.legacy.4=11fbebe8bab5c35042663c60a32b7fcc3350f2a7a0cff79cb17185def6674c1233e6915545ad43e3043ba9517c283d20198fe3bbba59fc4ed6dc89b7432a7f5188caa47ec7b08631bfe2d3d2a3a745c0ad7bca351bfbdf74e49b2f46532c99f1 +B.lsig.basic.4=998fe3bbba59fc4ed6dc89b7432a7f5188caa47ec7b08631bfe2d3d2a3a745c0ad7bca351bfbdf74e49b2f46532c99f111fbebe8bab5c35042663c60a32b7fcc3350f2a7a0cff79cb17185def6674c1233e6915545ad43e3043ba9517c283d20 +B.lverify.4=1 +B.lverify.bad.4=0 +B.lsig.rt.4=11fbebe8bab5c35042663c60a32b7fcc3350f2a7a0cff79cb17185def6674c1233e6915545ad43e3043ba9517c283d20198fe3bbba59fc4ed6dc89b7432a7f5188caa47ec7b08631bfe2d3d2a3a745c0ad7bca351bfbdf74e49b2f46532c99f1 +B.bsig.basic.4=a57f7ec0d09676c12b4fb525a1d359b7c29cc0f010682905f0a44bafc8764998c85fb885f9affeb2e256cfb3f5558c61180da06bedd87410c1f842ddcf467b04aeed09b4cb8c2eb4dbf5f502cea4683e6c35cf2475208fa3dcd852e5d290faf2 +B.bsig.legacy.4=980da06bedd87410c1f842ddcf467b04aeed09b4cb8c2eb4dbf5f502cea4683e6c35cf2475208fa3dcd852e5d290faf2057f7ec0d09676c12b4fb525a1d359b7c29cc0f010682905f0a44bafc8764998c85fb885f9affeb2e256cfb3f5558c61 +B.bverify.4=1 +A.child.hard.4=1422752ec6e3f867f5f80020bec1d84e6ade884bf4093f4d337f503417e00fdd +A.child.soft.4=10b37a4b07fa1a78786efbe3f116dfd462ba0ce94e7afa742f5a87234c3a868f +A.sk.5=0535569670f3c8c0379aea8c93b3bedf5ef16672417c281da18b957f41398d13 +A.pk.basic.5=b14d33ec70e47c7d9c7895bc4bb6d9979d81118354bb84571aed49b1dd8560a9ddbf71660d6c567bf7f391c51e0e5c45 +A.pk.legacy.5=914d33ec70e47c7d9c7895bc4bb6d9979d81118354bb84571aed49b1dd8560a9ddbf71660d6c567bf7f391c51e0e5c45 +A.fp.basic.5=1c9dbfe5 +A.fp.legacy.5=708cb0c8 +A.skG2.basic.5=8af786a3d660b1305eee25239d7c8f225fa604b23f96287745b9caee6a039ff21733bbe644df10daaf79c0ddc187bf4811d3f20781f42de6cb8fae96a560ed9f42aff7d3fee427f7bb44967dbbaff01e3efdad10b83a33076246b5819d1ef755 +A.skG2.legacy.5=11d3f20781f42de6cb8fae96a560ed9f42aff7d3fee427f7bb44967dbbaff01e3efdad10b83a33076246b5819d1ef7550af786a3d660b1305eee25239d7c8f225fa604b23f96287745b9caee6a039ff21733bbe644df10daaf79c0ddc187bf48 +A.pk.rt.legacy.5=914d33ec70e47c7d9c7895bc4bb6d9979d81118354bb84571aed49b1dd8560a9ddbf71660d6c567bf7f391c51e0e5c45 +A.pk.rt.basic.5=b14d33ec70e47c7d9c7895bc4bb6d9979d81118354bb84571aed49b1dd8560a9ddbf71660d6c567bf7f391c51e0e5c45 +B.lsig.legacy.5=116b3ec371691cdf6b75db98148553ffa14ee11df0ebced3a2e7dfe9e7fb1e4da4f322d1df36d03bf3b75ed60cc6aadc07c0606f8cd2196e6d9a8c146a6c6f2d9d78898110da264e79291c5bf2d5d0567e741bca297c7b3d001cf202185411b5 +B.lsig.basic.5=87c0606f8cd2196e6d9a8c146a6c6f2d9d78898110da264e79291c5bf2d5d0567e741bca297c7b3d001cf202185411b5116b3ec371691cdf6b75db98148553ffa14ee11df0ebced3a2e7dfe9e7fb1e4da4f322d1df36d03bf3b75ed60cc6aadc +B.lverify.5=1 +B.lverify.bad.5=0 +B.lsig.rt.5=116b3ec371691cdf6b75db98148553ffa14ee11df0ebced3a2e7dfe9e7fb1e4da4f322d1df36d03bf3b75ed60cc6aadc07c0606f8cd2196e6d9a8c146a6c6f2d9d78898110da264e79291c5bf2d5d0567e741bca297c7b3d001cf202185411b5 +B.bsig.basic.5=98e09cacf9f860bc131c401c6dc20a96cba00c581a2abf576a58ae4e0edd96d82764f95e1b0a00d6e6ad52db83adb92b16349f9b0675e0b6ffe90ec64203fce107813ae36cfb3a4c98b40580b362d22b27595d57e1f02ab67534b96b186ee2fe +B.bsig.legacy.5=16349f9b0675e0b6ffe90ec64203fce107813ae36cfb3a4c98b40580b362d22b27595d57e1f02ab67534b96b186ee2fe18e09cacf9f860bc131c401c6dc20a96cba00c581a2abf576a58ae4e0edd96d82764f95e1b0a00d6e6ad52db83adb92b +B.bverify.5=1 +A.child.hard.5=186953b6ebeb46b7d6d17f4eb6b55738a8910468d8c7a12773fa4ece4d396e33 +A.child.soft.5=36aae8999b8d557746cb7310a2291c8facd190430c6f769f60193610a5e7f570 +A.sk.6=3e54ca602df6ef98b894e98a87eddca31b87fd052cfcab698477b3ad19c84dfb +A.pk.basic.6=925b01d07a6e175a0b38f66c5bb2263f13f9800f2becbff87a73548c3ec188e08505a3bc17f046f0610b84e3c487ec3f +A.pk.legacy.6=125b01d07a6e175a0b38f66c5bb2263f13f9800f2becbff87a73548c3ec188e08505a3bc17f046f0610b84e3c487ec3f +A.fp.basic.6=910eddce +A.fp.legacy.6=08462c2f +A.skG2.basic.6=ab3a64185b1e43943f8645682b86e13882653beeee52343ced9b87556c6eb39f2b87cd0fffe68276470a4c4afc21445413753b7fee41fa154a0b76495935a97243279fd70a0baff73cd8ae88c2b387ccd358cac5d7c34af4cc7e348c0fea602d +A.skG2.legacy.6=93753b7fee41fa154a0b76495935a97243279fd70a0baff73cd8ae88c2b387ccd358cac5d7c34af4cc7e348c0fea602d0b3a64185b1e43943f8645682b86e13882653beeee52343ced9b87556c6eb39f2b87cd0fffe68276470a4c4afc214454 +A.pk.rt.legacy.6=125b01d07a6e175a0b38f66c5bb2263f13f9800f2becbff87a73548c3ec188e08505a3bc17f046f0610b84e3c487ec3f +A.pk.rt.basic.6=925b01d07a6e175a0b38f66c5bb2263f13f9800f2becbff87a73548c3ec188e08505a3bc17f046f0610b84e3c487ec3f +B.lsig.legacy.6=825a6eb2146a57893682066d783509b342fc5869ae0559330e11cb10ec3a132e9cde762c6869e67c9b83d0de2646ebac09aa2a4d7a08831cab78b6b7a57f57fad48cd1dbe3c3da0d996db69ff13fc060af2626a14bf69092def390acf6320f4d +B.lsig.basic.6=a9aa2a4d7a08831cab78b6b7a57f57fad48cd1dbe3c3da0d996db69ff13fc060af2626a14bf69092def390acf6320f4d025a6eb2146a57893682066d783509b342fc5869ae0559330e11cb10ec3a132e9cde762c6869e67c9b83d0de2646ebac +B.lverify.6=1 +B.lverify.bad.6=0 +B.lsig.rt.6=825a6eb2146a57893682066d783509b342fc5869ae0559330e11cb10ec3a132e9cde762c6869e67c9b83d0de2646ebac09aa2a4d7a08831cab78b6b7a57f57fad48cd1dbe3c3da0d996db69ff13fc060af2626a14bf69092def390acf6320f4d +B.bsig.basic.6=b8801cf2113e290828ae4c2ef629d8cb3d3a34d3b8de7dcd0170f6a070f0787941ca2ed97d561c1b069b688945efb525033f27242eace77e730ce5c0a1200b05be002b47b2a7664445537f0ad10dbf24bbf0cc0f60ccd6992df41f3030f71c2a +B.bsig.legacy.6=833f27242eace77e730ce5c0a1200b05be002b47b2a7664445537f0ad10dbf24bbf0cc0f60ccd6992df41f3030f71c2a18801cf2113e290828ae4c2ef629d8cb3d3a34d3b8de7dcd0170f6a070f0787941ca2ed97d561c1b069b688945efb525 +B.bverify.6=1 +A.child.hard.6=5cec6bb344ecd98a133343f77b84fe620d46b1468a4579c83963cc0d32be15fc +A.child.soft.6=49f50d890fa3b2d475a6ce1bb2c56f9508fe8d2662659146e3434390ddc0e94d +A.sk.7=0e3c506a5cc9be55237397674e0fe32f61e4ecb6e2c761493d89c7a17a6dcc0d +A.pk.basic.7=9661920ea04d278794e28c0767591a11bb1f4678e765354e257887bf5c8e38ad3aaa258d22ac826ecb1f2b31a23a7415 +A.pk.legacy.7=1661920ea04d278794e28c0767591a11bb1f4678e765354e257887bf5c8e38ad3aaa258d22ac826ecb1f2b31a23a7415 +A.fp.basic.7=e141846a +A.fp.legacy.7=c4d6d99d +A.skG2.basic.7=86d69b68a97adf54d024ce7fef27dbc0b3f08b993daec1434b5b8f77b0f09614e0ff35c5e24b4e3b57c378e5370e2f3715847268902520804e69b0c74f7744ccefed304bbf4f06103874fba5468add684faf46d5719fdb2570e398cef37e64cb +A.skG2.legacy.7=15847268902520804e69b0c74f7744ccefed304bbf4f06103874fba5468add684faf46d5719fdb2570e398cef37e64cb06d69b68a97adf54d024ce7fef27dbc0b3f08b993daec1434b5b8f77b0f09614e0ff35c5e24b4e3b57c378e5370e2f37 +A.pk.rt.legacy.7=1661920ea04d278794e28c0767591a11bb1f4678e765354e257887bf5c8e38ad3aaa258d22ac826ecb1f2b31a23a7415 +A.pk.rt.basic.7=9661920ea04d278794e28c0767591a11bb1f4678e765354e257887bf5c8e38ad3aaa258d22ac826ecb1f2b31a23a7415 +B.lsig.legacy.7=946ba1386b9b458466890d857082710507ec67a1e055caa977799a92278fda373155e0b9fefb4fb40ede46112c1ccdf70035ec9fabb85bc7e8493fbc4f892d0cd9ef73ef86656a000bc95eaf980ec76a0db375c4165016bf7fc72a96dcd6ac0f +B.lsig.basic.7=a035ec9fabb85bc7e8493fbc4f892d0cd9ef73ef86656a000bc95eaf980ec76a0db375c4165016bf7fc72a96dcd6ac0f146ba1386b9b458466890d857082710507ec67a1e055caa977799a92278fda373155e0b9fefb4fb40ede46112c1ccdf7 +B.lverify.7=1 +B.lverify.bad.7=0 +B.lsig.rt.7=946ba1386b9b458466890d857082710507ec67a1e055caa977799a92278fda373155e0b9fefb4fb40ede46112c1ccdf70035ec9fabb85bc7e8493fbc4f892d0cd9ef73ef86656a000bc95eaf980ec76a0db375c4165016bf7fc72a96dcd6ac0f +B.bsig.basic.7=ae7378473f2e89255e78676f4ee798ea8e169551dfcc8b78cd564dbdf5d1495c0145e95c7e5d0df191c955a40ba033b805363357f176bd8b84063ae47bf7e3a273a2644ba437a9c496a66761a0693305b3249f588dd1e45feef9d33e1030c076 +B.bsig.legacy.7=85363357f176bd8b84063ae47bf7e3a273a2644ba437a9c496a66761a0693305b3249f588dd1e45feef9d33e1030c0760e7378473f2e89255e78676f4ee798ea8e169551dfcc8b78cd564dbdf5d1495c0145e95c7e5d0df191c955a40ba033b8 +B.bverify.7=1 +A.child.hard.7=6be06280ee13d42a1d9f12b5d3e9b429641ede55b3bad11a27948123e89d8913 +A.child.soft.7=1605a13324f75c0755fe03bfb1a9e9478586c12a54332de98ec4658dc233ce14 +C.aggsec.legacy.1=17b20ce50a20f09a4d807d4c0db622d13be8902380e908a9304d21d03520cb9712e8fb478bd4eb35477298c05ad5069610688edde3431521fa64f24c6e6fad0b38fd77ae2edd71871948273c6a17efad03b2f908fa9717935fc7ae68ca7421ec +C.versec.legacy.1=1 +C.aggsec.basic.1=98103b71225c000a8e08507ac38248bc97ff96c4ef0a0ecb610ba97798df58f741421304b46dbe709d891640bdc797d316e5b1fe117273391a37e981838677ce2185afe88e4f29a51ceb6d7c9a7f22062e8d4029345f2f37a473b2a8055ed848 +C.versec.basic.1=1 +C.versec.legacy.bad.1=0 +C.agg.G2.1=a941eab017de217c825e0724f3ec1bfbfd90ce7628f5d3bbf0806e0efdfa806fa746c178da66fb2a8d9a587ef0bab4c91774469f443f513972a0c59ae55278c32e1caf9c66d52e708e53ef2828c48f5c4b830d256c2ff1b155730588dfc9adeb +C.agg.G1.1=9503c392ceae7db1e2f247fb6148b4211708a74491989916daeec3c34bdd2803a98fc3a43976daaab00903211b1d1c46 +C.agg.sk.1=51542fee7895e4987de3b93ff52af9bb129dc076f0dcb8afe5d93460f2a6c1b7 +C.aggsec.legacy.2=0ca923fd169db16838c09804d7150f2bdde930d17040bc39c553baf9336527b15cbe83aa841b9f902a203521e7bc60220a9c9e1ddf0677564be73f7b8f9ce2a52c28c910eac2baba3ef3310fad7eaa8baf9465bfc9104f0ac08cd9da8b41b70e +C.versec.legacy.2=1 +C.aggsec.basic.2=a165590855562a1437e0d5fce7dfb1373a07fe09bdb33cf5f82b2e8d3b809ce7a8e9ae47eb0602181d474866958d51641816952a467643164dab9aa92567dac5449943f8464d0760740fcbb54bd758cc80e232032f56f3df269460d2cd7b807c +C.versec.basic.2=1 +C.versec.legacy.bad.2=0 +C.agg.G2.2=ab45f84e0c325239430f0584bf220bbabcff667d308d39c1fcd827f8c7f105e8210c20ca619ad9084984914e35fc0d1f082b5675dcfd07041f6ee1564de37b678a4b68ee51db8977bdc79f4ba1c9d49cccef35b1de0b7e8494c9cc5fa233edd0 +C.agg.G1.2=a5425f1689e33cd676a112efdd5aa80df7b137fad1db3c690bb2213745dd9a25c51d35fce39de1eaf5e268ccfdcb9163 +C.agg.sk.2=4e1643205fe0ed6f883f3d803c4742a2db0b7826aa523e5bc62a18c766d698df +C.aggsec.legacy.3=87b142eb28bb97ed9839900dbcefe90a992b4cd63468dd13d3dc8bcef394f0e77715f8da3fd62d3847ab845b2035a880193d116414b1a51a43edce8b2ccc4ee08f4492d35e19f9c35fe76cf73598afc085e62af9a6e52927c8f4d8544f9887f4 +C.versec.legacy.3=1 +C.aggsec.basic.3=8959bdf6c216c1c50eee30aa5ccd21196c058e3e28069cc70d86f4dc1608bbf9b791db866fb23ee816acd9b8ed3d3964174a16f05c9afc9cdc51790e8bf7a4ea0b4aef4645119a041ff97fa8500d6167c0db4743aba27f454853451f7229a287 +C.versec.basic.3=1 +C.versec.legacy.bad.3=0 +C.agg.G2.3=85b735e626a9322824cdb16d704db491330aa37239153a833c212f5404a1028f97d8339d437d7cdf06749330639c6ea21437d0bc3b3e6e1d411ed606e1943576c462abf6d572c9eccabdaec263073748421f84497f775a93631ccb51364f528f +C.agg.G1.3=b45111e7f20ff82bbfce790f2abeefebb885844423ed1fd37b43904b7b47454ff3c30ac47d4969c615af7316b1f41ffb +C.agg.sk.3=1d3b4ed79d0c0001f1bb2ded98523121bedbeaa37ac4fceb0f0bfdf4d8963849 +C.aggsec.legacy.10=0eab90239c026690d3ba0ac74c69f28420931128800ff1cfa7c64668600b99e7f60853e0f2d22b4d6cf07d97428cd0411256b05ad14e7ecae1372673d5c00db1880874016ea8a2ed6eb34655297e7883e6e023f28a6aa206e0fd0294bff532fa +C.versec.legacy.10=1 +C.aggsec.basic.10=a0368e7182619f7569d087c364199db4c5c20ba3e090706a3767ceb5dc054afe66fb4835b487eb17f67f36972b5e2d660c207b224abf7b30bb7db3bd16ebe0d1a87fac41370d82656af3e907293e954a884411765caf76708008ed2dd9b25622 +C.versec.basic.10=1 +C.versec.legacy.bad.10=0 +C.agg.G2.10=82974b5dafcc908dd00b725f120e9fa3ba1ec265019145a898b6ab3ddebb6f0b1a8c02827e04ee33dca6f098799ba76710b0cb5bf3b125ccd295abf5f3eca6fa272be6d727a591b32208b33618212368a15035b7e97edd2e29112e91bf61b651 +C.agg.G1.10=86689658c56d1d945a480cc1a11cb77ec19bce8fd3f8f6f5dbb1db20330aac73e78268a66e512b5ddd98fffc20bc7bbc +C.agg.sk.10=4972fe548df20e3ede53ebe27f0ab0c1bfe742903357d88d48301c6b7c9a77b6 +D.lagg=8acadc114967f7a21953644c19dc9ecbfdbdb0233d484862e2816ef3e6cc94177c85d26a3d8bc10a79ba7fced80226530f01ee9e0f441c83c8b50bf5e03be1f1dbfcc7d660d6d968c738693574f144dc1c5001a221bdf16d7127cb828e58003b +D.laggverify=1 +D.laggverify.bad=0 +E.mastersig=99a667d463e60f2e2b3feecb2a04061692faa66c543bd4eb36c5077794b2bfe24200aa1709fa72408a40a8dfe8a00d8c0d6d35dbce43924eba4354c109b6370a722f67bed82b4d1d984572d7817797477cd34aa415d20c996d573d5ed6043574 +E.masterverify=1 +E.skshare.0=2fe9aa3dc24ee2b902c2632305e5e9f9b667cb721239b1eeaec32775235696ce +E.pkshare.0=93ac3b88ca6f2a31eb5929c590692f415b3e9cb4dabb70bf9493a6858e1fe86d89ed2363f2098d0888e3fc601947fda0 +E.sharematch.0=1 +E.sigshare.poly.0=8c2810b9171817b12be33be0d8caa159785f05c30695aacba1cfac14bd4b6c4a6879ebc91a471c1605f608e2e223ce62044251375a33a8c918177fc950496fbfd4832d22f8ba8c4b391b74113703e82828d60eb468be93e150eee50bf0a0927e +E.sigshare.sign.0=8c2810b9171817b12be33be0d8caa159785f05c30695aacba1cfac14bd4b6c4a6879ebc91a471c1605f608e2e223ce62044251375a33a8c918177fc950496fbfd4832d22f8ba8c4b391b74113703e82828d60eb468be93e150eee50bf0a0927e +E.skshare.1=6d7a99964fe9909c9a713f88392b32af635db3daec83b4538c6fc3228ecdf513 +E.pkshare.1=8e333381aedd9b63aaf2e019e197e6983ca3749b8561e21485bc6b7a4bef92d0ecd50481bf95832d87d3b2bd37d3a141 +E.sharematch.1=1 +E.sigshare.poly.1=860e104d01a3d7c3af84995bdd1574c4292ea7e5373d22ccd590ac33acaa91d2f8d119fb2f4980ca4fee9ec66179f9f10f053bd123ec34abdd0e181d76bbb795459f65c1b1404904aa6d76593561b67b2c3f29d0e965533161a43e1683e4d1ea +E.sigshare.sign.1=860e104d01a3d7c3af84995bdd1574c4292ea7e5373d22ccd590ac33acaa91d2f8d119fb2f4980ca4fee9ec66179f9f10f053bd123ec34abdd0e181d76bbb795459f65c1b1404904aa6d76593561b67b2c3f29d0e965533161a43e1683e4d1ea +E.skshare.2=4a691d73ddb6e5236c82bab66d69ba08c340e25aad705836792c66a8b8b2391f +E.pkshare.2=83ad1776d2dfec1bde34672dd518bd59c3861e92f374fd34e11bfc454a29d7c92536bd0e4c48288ab704211f5053c1c5 +E.sharematch.2=1 +E.sigshare.poly.2=12e5310660dfc34e159a5910db2b2b517936acde9eadd3c954c572c3f7814a07a0350ca68f56cc4277fd9784d78182bd04588688bd1c842992e941f30939f2bc4325237ebf4b30a490473878636f72e7cca9036895141d01ccef721da90fa3ff +E.sigshare.sign.2=12e5310660dfc34e159a5910db2b2b517936acde9eadd3c954c572c3f7814a07a0350ca68f56cc4277fd9784d78182bd04588688bd1c842992e941f30939f2bc4325237ebf4b30a490473878636f72e7cca9036895141d01ccef721da90fa3ff +E.skshare.3=296fdf7a3c8e8d9a1d80009e1e54c95ce84bc381e63236e500729d4a6a5f0d0f +E.pkshare.3=893bbd2c6b4d595cdac30778e438a1b95d16eb1909b8bcc28148848507d07e98793d4c0368d328d45a5355df1f2253da +E.sharematch.3=1 +E.sigshare.poly.3=039b5d75dfad13ce4392deaa7d207a12e0a658dd5f34f66098453e60b07b38fbc7b3271d14697e6bfd56d6053a697237069259997fd43f322cb917f7fed360cbacbe2a8582358c954c5381cdc442f8323394cab23d4ce0c2745ca6e45aa99c8b +E.sigshare.sign.3=039b5d75dfad13ce4392deaa7d207a12e0a658dd5f34f66098453e60b07b38fbc7b3271d14697e6bfd56d6053a697237069259997fd43f322cb917f7fed360cbacbe2a8582358c954c5381cdc442f8323394cab23d4ce0c2745ca6e45aa99c8b +E.skshare.4=57230fd28ec31c1a4c4a5e378c6fa748d6e68772fe83d35477bb6539876fab15 +E.pkshare.4=91edd2ed20fa5ef43bf796785e0ca8ab1d6cdb4ae63aba67ffccc0f6911c1214f81a62e23175f46b767681cf92cb25f1 +E.sharematch.4=1 +E.sigshare.poly.4=97c77544f1db5118e955e892c45d1895724b77e99efd420615f54f4d4d5b7b57f668926fa45be02190d269a2354cfaf30d55b722c035e19354e593015ccf0bd71d2c7e4c35e4cfb951bd6ff5f88008014f877a44f5f9d95d01fd1b1e570a3b15 +E.sigshare.sign.4=97c77544f1db5118e955e892c45d1895724b77e99efd420615f54f4d4d5b7b57f668926fa45be02190d269a2354cfaf30d55b722c035e19354e593015ccf0bd71d2c7e4c35e4cfb951bd6ff5f88008014f877a44f5f9d95d01fd1b1e570a3b15 +E.skrecover=6c04e5af86f2ddeaf6d1d4f8bbd4a1217b29abd4517d4619dada7ec087ed6f6f +E.skrecover.match=1 +E.pkrecover=8d713f7f50fe5d3e2c0335c3d3c0ceb2a1689eb3c2a4436c3a11898b8b797818aae1316825542790d1b0b2cafffb9150 +E.sigrecover=99a667d463e60f2e2b3feecb2a04061692faa66c543bd4eb36c5077794b2bfe24200aa1709fa72408a40a8dfe8a00d8c0d6d35dbce43924eba4354c109b6370a722f67bed82b4d1d984572d7817797477cd34aa415d20c996d573d5ed6043574 +E.sigrecover.verify=1 +E.sigrecover.same=1 +F.esk=000000010000000000000000004c3b08d7413ef3f4d39922793c4b20c0bcfb26db531c9e32a505cf763c2794953757b1115e7110046606404b38e4654adc4c2a52a5337deca0794080d3f92921 +F.esk.pk.legacy=89efc5280e56a745dcfd4571d1e9b06edf0441c5fd8640f5efdf5554bcdcb07e7d1d35e09bf9ebaabe6faad282c838d4 +F.esk.pk.basic=a9efc5280e56a745dcfd4571d1e9b06edf0441c5fd8640f5efdf5554bcdcb07e7d1d35e09bf9ebaabe6faad282c838d4 +F.esk.chaincode=4c3b08d7413ef3f4d39922793c4b20c0bcfb26db531c9e32a505cf763c279495 +F.child.legacy=00000001023e497ad38000002aff185013e7118856e4bcb6e2dc9608cab5219747c8037a889789b1be76feb6df1250aa4f4cb5f7e58f7b5f942eb2f2b99b36eacb3e6e65c4766ce956e628e62a +F.child.legacy.sk=1250aa4f4cb5f7e58f7b5f942eb2f2b99b36eacb3e6e65c4766ce956e628e62a +F.child.basic=000000010203f3628b8000002a447c89f7c80822b8661513be9c7fdf172a91faf71300f68fa39cfdea0ae3740f625c4936e02f4abcee9cfbd59e403428b9937f94bd0908cf676c3f63bc7713e0 +F.child.basic.sk=625c4936e02f4abcee9cfbd59e403428b9937f94bd0908cf676c3f63bc7713e0 +F.epk.legacy=000000010000000000000000004c3b08d7413ef3f4d39922793c4b20c0bcfb26db531c9e32a505cf763c27949589efc5280e56a745dcfd4571d1e9b06edf0441c5fd8640f5efdf5554bcdcb07e7d1d35e09bf9ebaabe6faad282c838d4 +F.epk.basic=000000010000000000000000004c3b08d7413ef3f4d39922793c4b20c0bcfb26db531c9e32a505cf763c279495a9efc5280e56a745dcfd4571d1e9b06edf0441c5fd8640f5efdf5554bcdcb07e7d1d35e09bf9ebaabe6faad282c838d4 +F.epk.child.legacy=00000001010b9a9e8000000001d84919fa70508fefd47576f19b437b3bb2049039740d83de455742dae48c96ab8a9f848f28b295903845d5f860c9031899e4f1a6d092edacdaec28f64a7fd9b94679b3faaf0ecf6b09f70b1d3ed5555f +F.epk.child.basic=00000001010b9a9e80000000012428f63e5f4b2e25871336f34ecebbd6e0e648d8b4a02ec033b575a391dc6b598cf85b6e8d78a797985402debeb2a1b823ab7c98ae20ae1609aaadd70309a4d40ef5cad6a6f93cb9af0ec2045dba96cf +F.pubpriv.match.legacy=1 +F.esk.rt=000000010000000000000000004c3b08d7413ef3f4d39922793c4b20c0bcfb26db531c9e32a505cf763c2794953757b1115e7110046606404b38e4654adc4c2a52a5337deca0794080d3f92921 +F.epk.rt.legacy=000000010000000000000000004c3b08d7413ef3f4d39922793c4b20c0bcfb26db531c9e32a505cf763c27949589efc5280e56a745dcfd4571d1e9b06edf0441c5fd8640f5efdf5554bcdcb07e7d1d35e09bf9ebaabe6faad282c838d4 +G.inrange.mod0=57c1d1f8ef9ad067fef7d0056bdfec87f51c28b65dd56fa3cbcc0f1afc984725 +G.inrange.mod1=57c1d1f8ef9ad067fef7d0056bdfec87f51c28b65dd56fa3cbcc0f1afc984725 +G.big.mod1=1824b159acc5056f998c4fefecbc4ff55884b7fa0003480200000001fffffffd +G.big.mod0=EXC +G.order.mod1=0000000000000000000000000000000000000000000000000000000000000000 +G.order.mod0=73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 +G.orderm1.mod0=73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000 +G.zero.sk=0000000000000000000000000000000000000000000000000000000000000000 +G.zero.pk=c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +G.bip32seed=193afdb206c666de5cfba5d5a235477d269b1634ec36cfa1a3167cb47727bf25 +G.dh=a11d215631668626a3396afbfd38d850a2c18ffa90bd589714e40112b2592064c581eb8205fdc7bcd860e23b15e487cf +G.dh.sym=1 +H.g1.inf.basic.ser=c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g1.inf.basic.valid=1 +H.g1.inf.legacy.ser=c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g1.inf.legacy.valid=1 +H.g2.inf.basic.ser=c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.inf.basic.valid=1 +H.g2.inf.legacy=EXC +H.g1.badinf.basic=EXC +H.g1.badinf.legacy=EXC +H.g2.badinf.basic=EXC +H.g2.badinf.legacy=EXC +H.g1.zeros.basic=EXC +H.g1.zeros.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g1.zeros.legacy.valid=0 +H.g2.zeros.basic=EXC +H.g2.zeros.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.zeros.legacy.valid=0 +H.g1.zeros.legacy.unchk.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g1.zeros.legacy.unchk.valid=0 +H.g2.zeros.legacy.unchk.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.zeros.legacy.unchk.valid=0 +H.g1.ff.basic=EXC +H.g1.ff.legacy=EXC +H.g2.ff.basic=EXC +H.g2.ff.legacy=EXC +H.g1.fflow.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g1.fflow.legacy.valid=0 +H.g1.legacyAsBasic=EXC +H.g1.basicAsLegacy.ser=98138bb3b9cb34f03c9deac8e0928385873a8fe418a5f371f10cba0b6988a7854d0b48c1ffc50314bddea964b90b6be3 +H.g1.basicAsLegacy.valid=1 +H.g2.legacyAsBasic=EXC +H.g2.basicAsLegacy.ser=801627cb11cf0498af70b04e84ec07a615c01219b0693be59fb93e403f7937ddf26efe486c4b8edffdea8f136203b99e15240cfb56882628ef6d4b2cad852cbe23b882b2aab625f0e82f355ce1a4fe129b589d97ca3e17c5a36e514f93cfff32 +H.g2.basicAsLegacy.valid=0 +H.g1.negated.legacy.ser=98138bb3b9cb34f03c9deac8e0928385873a8fe418a5f371f10cba0b6988a7854d0b48c1ffc50314bddea964b90b6be3 +H.g1.negated.legacy.valid=1 +H.g1.negated.basic.ser=b8138bb3b9cb34f03c9deac8e0928385873a8fe418a5f371f10cba0b6988a7854d0b48c1ffc50314bddea964b90b6be3 +H.g1.negated.basic.valid=1 +H.g1.nonsub.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 +H.g1.nonsub.legacy.valid=0 +H.g1.nonsub.legacy.unchk.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 +H.g1.nonsub.legacy.unchk.valid=0 +H.g1.nonsub.basic=EXC +H.g1.nonsub.basic.unchk.ser=800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 +H.g1.nonsub.basic.unchk.valid=0 +H.g2.nonsub.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.nonsub.legacy.valid=0 +H.g2.nonsub.legacy.unchk.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.nonsub.legacy.unchk.valid=0 +H.g2.nonsub.basic=EXC +H.g2.nonsub.basic.unchk=EXC +H.g1.nocurve.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +H.g1.nocurve.legacy.valid=0 +H.g1.nocurve.basic=EXC +H.g2.flag48.basic=EXC +H.len47=EXC +H.g1.nocurve.sign.legacy.ser=800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +H.g1.nocurve.sign.legacy.valid=0 +H.g1.overp.sign.legacy.ser=800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g1.overp.sign.legacy.valid=0 +H.g2.x2.sign.legacy.ser=800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.x2.sign.legacy.valid=0 +H.g2.x3.sign.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.x3.sign.legacy.valid=0 +H.g2.x2.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.x2.legacy.valid=0 +H.g2.overp.sign.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.overp.sign.legacy.valid=0 +I.basic.verify.infinf=0 +I.legacy.verify.infinf=0 +I.basic.verify.infpk=0 +I.basic.verify.infsig=0 +I.aggver.empty.infsig=1 +I.aggver.empty.realsig=0 +I.aggver.mismatch=0 +I.versec.withinf=0 +# end diff --git a/src/dashbls/tools/fuzzgen.cpp b/src/dashbls/tools/fuzzgen.cpp new file mode 100644 index 000000000000..28a6bbebde60 --- /dev/null +++ b/src/dashbls/tools/fuzzgen.cpp @@ -0,0 +1,165 @@ +// Differential fuzz driver for the relic -> blst migration. +// +// Uses only the public dashbls API; compile the same source against the old +// and new libraries, run with the same arguments, and diff the output. +// +// fuzzgen +// +// Covers: random byte-string decoding in every mode (the dominant +// consensus-facing attack surface), decode/re-encode round trips, and +// legacy + basic sign/verify/aggregate cycles on derived keys. + +#include +#include +#include +#include +#include +#include + +#include + +using namespace bls; +using std::vector; + +// xorshift128+ so both builds see identical byte streams with no libc +// dependency +static uint64_t s0, s1; +static uint64_t rng() +{ + uint64_t x = s0; + const uint64_t y = s1; + s0 = y; + x ^= x << 23; + s1 = x ^ y ^ (x >> 17) ^ (y >> 26); + return s1 + y; +} + +static void fill(vector& v) +{ + for (size_t i = 0; i < v.size(); i += 8) { + const uint64_t r = rng(); + for (size_t j = 0; j < 8 && i + j < v.size(); j++) + v[i + j] = (uint8_t)(r >> (8 * j)); + } +} + +static void dump(const vector& v) +{ + for (auto b : v) printf("%02x", b); +} + +static void probeG1(const vector& in, bool fLegacy) +{ + try { + G1Element e = G1Element::FromBytes(Bytes(in), fLegacy); + dump(e.Serialize(fLegacy)); + printf(" v%d", (int)e.IsValid()); + } catch (const std::exception&) { + printf("EXC"); + } + printf(";"); +} + +static void probeG2(const vector& in, bool fLegacy) +{ + try { + G2Element e = G2Element::FromBytes(Bytes(in), fLegacy); + dump(e.Serialize(fLegacy)); + printf(" v%d", (int)e.IsValid()); + } catch (const std::exception&) { + printf("EXC"); + } + printf(";"); +} + +int main(int argc, char** argv) +{ + if (argc != 3) { + fprintf(stderr, "usage: fuzzgen \n"); + return 2; + } + s0 = strtoull(argv[1], nullptr, 0) * 0x9E3779B97F4A7C15ULL + 1; + s1 = s0 ^ 0xD1B54A32D192ED03ULL; + char* end = nullptr; + errno = 0; + const long iters = strtol(argv[2], &end, 0); + if (errno != 0 || end == argv[2] || *end != '\0' || iters <= 0) { + fprintf(stderr, "fuzzgen: the iteration count must be a positive number\n"); + return 2; + } + + LegacySchemeMPL legacy; + BasicSchemeMPL basic; + + for (long i = 0; i < iters; i++) { + printf("i%ld: ", i); + + // 1. random decodes: fully random, and "plausible" (top bits biased + // into the interesting flag space) + vector b48(48), b96(96); + fill(b48); + fill(b96); + switch (i % 4) { + case 0: break; + case 1: b48[0] &= 0x1f; b96[0] &= 0x1f; break; // no flags + case 2: b48[0] |= 0x80; b96[0] |= 0x80; break; // sign/compress + case 3: b48[0] = (uint8_t)(rng() & 0xe0); b96[0] = b48[0]; break; + } + probeG1(b48, false); + probeG1(b48, true); + probeG2(b96, false); + probeG2(b96, true); + + // 2. valid-point cross-mode round trips + vector seed(32); + fill(seed); + PrivateKey sk = basic.KeyGen(seed); + G1Element pk = sk.GetG1Element(); + probeG1(pk.Serialize(true), true); + probeG1(pk.Serialize(false), true); // modern bytes into legacy codec + + // 3. legacy + basic signing over a random 32-byte hash + vector h(32); + fill(h); + G2Element lsig = legacy.Sign(sk, Bytes(h)); + dump(lsig.Serialize(true)); + printf(" %d", (int)legacy.Verify(pk, Bytes(h), lsig)); + printf(";"); + G2Element bsig = basic.Sign(sk, Bytes(h)); + dump(bsig.Serialize(false)); + printf(" %d", (int)basic.Verify(pk, Bytes(h), bsig)); + printf(";"); + + // 4. secure aggregation with 3 keys + vector sks; + vector pks; + vector lsigs; + for (int k = 0; k < 3; k++) { + vector s2(32); + fill(s2); + sks.push_back(basic.KeyGen(s2)); + pks.push_back(sks.back().GetG1Element()); + lsigs.push_back(legacy.Sign(sks.back(), Bytes(h))); + } + G2Element agg = legacy.AggregateSecure(pks, lsigs, Bytes(h)); + dump(agg.Serialize(true)); + printf(" %d", (int)legacy.VerifySecure(pks, agg, Bytes(h))); + printf(";"); + + // 5. threshold 2-of-3 recovery + vector ids; + vector> idStore(3, vector(32)); + for (auto& id : idStore) fill(id); + PrivateKey sh0 = Threshold::PrivateKeyShare({sks[0], sks[1]}, Bytes(idStore[0])); + PrivateKey sh1 = Threshold::PrivateKeyShare({sks[0], sks[1]}, Bytes(idStore[1])); + try { + PrivateKey rec = Threshold::PrivateKeyRecover( + {sh0, sh1}, {Bytes(idStore[0]), Bytes(idStore[1])}); + dump(rec.Serialize()); + } catch (const std::exception&) { + printf("EXC"); + } + printf("\n"); + } + return 0; +} diff --git a/src/dashbls/tools/vectorgen.cpp b/src/dashbls/tools/vectorgen.cpp new file mode 100644 index 000000000000..ff38ae4a5211 --- /dev/null +++ b/src/dashbls/tools/vectorgen.cpp @@ -0,0 +1,22 @@ +// Regenerates test-vectors/reference.txt. +// +// Build against the library whose behavior is to become the reference (the +// checked-in file was produced by the relic-based implementation) and +// redirect the output: +// +// ./build/src/vectorgen > test-vectors/reference.txt +// +// runtest compares the current library against the file; this tool only +// generates data. + +#include + +#include "test-vectors.hpp" + +int main() +{ + for (const std::string& line : bls_test_vectors::GenerateReferenceVectors()) { + printf("%s\n", line.c_str()); + } + return 0; +} From b2efb31c48477500f985477396f67a8c33e33406 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Wed, 4 Nov 2026 14:49:18 +0700 Subject: [PATCH 3/4] Squashed 'src/dashbls/' changes from dbd61e6a4e..77c8da5a53 77c8da5a53 Merge pull request #132 from knst/bump-chia-2.0 eef98c6f85 build: drop the relic leftovers from Python packaging 1d0724ea28 build: apply -fno-builtin to blst's server.c only 3c92123613 build: use blst's portable C code on 64-bit targets without assembly e3fa624af2 ci: drop the relic backend matrix and the GMP installs 36b2a1379f fix: relic's zeros-only check for basic G1 decoding a9cc2d33a0 refactor: pass the message length to blst hash-to-group as size_t 32de4b2d41 test: fixed invalid point, secure-aggregation case; fuzzgen argument check d26e546a84 fix: GTElement::Unity() returned a default element 1d142fddd2 fix: keep md_hmac's key-derived buffers in secure memory 1079b7f7f7 fix: legacy signing and verification require a 32-byte message hash d59a4148d8 build: link vectorgen with emmalloc under Emscripten 45ad338054 binds: build the Apple Rust dependencies with CMake 48307a8f39 binds: build the Go and Rust bindings against blst 6f3d09f0bd binds: restore G1Element/G2Element multiplication by PrivateKey in Python 3c521b35a1 build: include blst headers as "blst.h" 49450c5100 test: extra blst boundary checks tests d48d45fe5b perf: serialize PrivateKey without blst's temporary limb conversion e2d734fe53 fix: keep relic's verification semantics instead of blst_core_verify c42c4dd32a fix: scalar byte order in point multiplication 18a9a6b85e fix: adopt schemes.hpp/cpp for blst library a021900bd7 fix: adopt util.hpp for blst library usages 330f75bf81 fix: adopt privatekey.cpp for blst library usage 81e22c0363 fix: blst's validation assumes a point on the curve while relic's is-valid checks both ecbb1dc6e1 fix: adopt elements.cpp for blst library usages 4f8b4e5bbd fix: adopt legacy signing for blst library [ep2_map_legacy] 6cb99c42cc fix: adopt extendedprivatekey extendendpublickey for blst's library 69cce7ec31 fix: adopt dash specific files chaincode, threshold for blst library e79d284117 no avx not for EMSCRIPTEN (#428) 73eb5bb860 catchup: into main from long_lived/blastwjb @ 95c2f65073c366a3621e304adc066b7e675cf907 (#409) f683a06f65 Adapt to the most recent version of emsdk. (#362) 7ecb9209ef test: order boundary tests, blst cross-check and the consensus vector harness 3a7f02795b doc: repair license header text mangled by the MPL-stripping sed 796a158b7b fix: silence -Wunused-parameter in LegacySchemeMPL stubs and AggregateSecure 158592f27a refactor: drop fLegacy flag from private's key serialization 43a953d783 refactor: removed helper PrivateKey::RandomPrivateKey because it used only in tests 57f7e16550 refactor: remove bn_helpers.hpp as workaround for gmp / relic datastructures deebfcbb35 Merge pull request #138 from knst/cleanup-build-deps 028dd09233 build: drop the libsodium secure allocator d7e8fd045e build: drop the Autotools build 6edb963dc8 Merge pull request #123 from UdjinM6/enf_bls_spec b2cfcdfe28 fix: add early signature validation to FastAggregateVerify 180a8cff15 fix: harden verification paths against malformed and identity inputs f5b4d361a0 fix: address CodeRabbit review feedback on test consistency 2bc43204af fix: correct AugSchemeMPL::VerifySecure to use per-signer augmented messages 7cf3191920 fix: add IsValid() checks to VerifySecure for defense-in-depth 3481d0eb90 fix: enforce BLS spec KeyValidate and normalize error handling git-subtree-dir: src/dashbls git-subtree-split: 77c8da5a53f389aa0a9e969e5d646ada046b0987 --- .github/workflows/binds-go.yml | 7 +- .github/workflows/binds-py.yml | 5 - .github/workflows/binds-rs.yml | 9 +- .github/workflows/build-test.yaml | 19 +- .github/workflows/stale-issue.yml | 0 .gitignore | 9 - CMakeLists.txt | 108 +- MANIFEST.in | 5 - Makefile.am | 39 - Makefile.bench.include | 22 - Makefile.bls.include | 66 - Makefile.mimalloc.include | 46 - Makefile.relic.include | 470 ------ Makefile.test.include | 27 - README.md | 12 +- apple.rust.deps.sh | 363 +---- autogen.sh | 13 - binds/python/CMakeLists.txt | 2 +- binds/python/pythonbindings.cpp | 1 - build-aux/m4/ax_check_compile_flag.m4 | 53 - build-aux/m4/ax_check_link_flag.m4 | 53 - build-aux/m4/ax_cxx_compile_stdcxx.m4 | 1005 ------------- build-aux/m4/ax_pthread.m4 | 522 ------- cmake_modules/Findgmp.cmake | 103 -- cmake_modules/Findsodium.cmake | 294 ---- configure.ac | 913 ----------- go-bindings/Makefile | 28 +- include/dashbls/bls.hpp | 2 - include/dashbls/chaincode.hpp | 14 +- include/dashbls/elements.hpp | 103 +- include/dashbls/extendedprivatekey.hpp | 8 - include/dashbls/extendedpublickey.hpp | 8 - include/dashbls/hdkeys.hpp | 145 +- include/dashbls/hkdf.hpp | 13 +- include/dashbls/legacy.hpp | 25 +- include/dashbls/privatekey.hpp | 19 +- include/dashbls/schemes.hpp | 286 ++-- include/dashbls/test-utils.hpp | 8 +- include/dashbls/util.hpp | 44 +- js-bindings/CMakeLists.txt | 2 - js-bindings/blsjs.d.ts | 9 - js-bindings/helpers.cpp | 27 - js-bindings/helpers.h | 9 - js-bindings/jsbindings.cpp | 6 - js-bindings/tests/test.js | 8 - js-bindings/wrappers/BignumWrapper.cpp | 48 - js-bindings/wrappers/BignumWrapper.h | 42 - js-bindings/wrappers/G1ElementWrapper.cpp | 10 - js-bindings/wrappers/G1ElementWrapper.h | 3 - js-bindings/wrappers/G2ElementWrapper.cpp | 10 - js-bindings/wrappers/G2ElementWrapper.h | 3 - pyproject.toml | 4 - rust-bindings/bls-dash-sys/build.rs | 54 +- .../bls-dash-sys/c-bindings/schemes.cpp | 9 +- rust-bindings/bls-signatures/src/schemes.rs | 76 +- setup.py | 1 - src/CMakeLists.txt | 100 +- src/bls.cpp | 45 - src/bn_helpers.hpp | 62 - src/chaincode.cpp | 16 +- src/elements.cpp | 690 ++++++--- src/extendedprivatekey.cpp | 21 +- src/extendedpublickey.cpp | 4 +- src/legacy.cpp | 602 +++----- src/privatekey.cpp | 197 ++- src/schemes.cpp | 662 +++++--- src/test-bench.cpp | 40 +- src/test-vectors.hpp | 575 +++++++ src/test.cpp | 1329 +++++++++++++---- src/threshold.cpp | 149 +- test-vectors/reference.txt | 324 ++++ tools/fuzzgen.cpp | 165 ++ tools/vectorgen.cpp | 22 + 73 files changed, 3943 insertions(+), 6250 deletions(-) mode change 100755 => 100644 .github/workflows/stale-issue.yml delete mode 100644 Makefile.am delete mode 100644 Makefile.bench.include delete mode 100644 Makefile.bls.include delete mode 100644 Makefile.mimalloc.include delete mode 100644 Makefile.relic.include delete mode 100644 Makefile.test.include delete mode 100755 autogen.sh delete mode 100644 build-aux/m4/ax_check_compile_flag.m4 delete mode 100644 build-aux/m4/ax_check_link_flag.m4 delete mode 100644 build-aux/m4/ax_cxx_compile_stdcxx.m4 delete mode 100644 build-aux/m4/ax_pthread.m4 delete mode 100644 cmake_modules/Findgmp.cmake delete mode 100644 cmake_modules/Findsodium.cmake delete mode 100644 configure.ac delete mode 100644 js-bindings/wrappers/BignumWrapper.cpp delete mode 100644 js-bindings/wrappers/BignumWrapper.h delete mode 100644 src/bn_helpers.hpp create mode 100644 src/test-vectors.hpp create mode 100644 test-vectors/reference.txt create mode 100644 tools/fuzzgen.cpp create mode 100644 tools/vectorgen.cpp diff --git a/.github/workflows/binds-go.yml b/.github/workflows/binds-go.yml index ccda3c190131..71a4ffe004dd 100644 --- a/.github/workflows/binds-go.yml +++ b/.github/workflows/binds-go.yml @@ -32,15 +32,10 @@ jobs: if: startsWith(matrix.os, 'ubuntu') run: | sudo apt-get update - sudo apt-get install -qq --yes valgrind libgmp-dev cmake + sudo apt-get install -qq --yes valgrind cmake hash -r cmake --version - - name: Prepare build system for macOS - if: startsWith(matrix.os, 'macos') - run: | - brew install gmp - - name: Build library using CMake run: | cores=$(getconf _NPROCESSORS_ONLN) diff --git a/.github/workflows/binds-py.yml b/.github/workflows/binds-py.yml index 803fb37fa4f2..b305a3fffe9b 100644 --- a/.github/workflows/binds-py.yml +++ b/.github/workflows/binds-py.yml @@ -92,11 +92,6 @@ jobs: - name: Build the sdist run: uv build --sdist --out-dir dist - - name: Prepare build system - run: | - sudo apt-get update - sudo apt-get install -qq --yes libgmp-dev - - name: Install from the sdist and run the unit tests run: | uv venv .venv-sdist diff --git a/.github/workflows/binds-rs.yml b/.github/workflows/binds-rs.yml index 8e3db323db12..5656b32272d0 100644 --- a/.github/workflows/binds-rs.yml +++ b/.github/workflows/binds-rs.yml @@ -27,15 +27,10 @@ jobs: if: startsWith(matrix.os, 'ubuntu') run: | sudo apt-get update - sudo apt-get install -qq --yes valgrind libgmp-dev cmake + sudo apt-get install -qq --yes valgrind cmake hash -r cmake --version - - name: Prepare build system for macOS - if: startsWith(matrix.os, 'macos') - run: | - brew install gmp - - name: Install Rust run: | rustup toolchain install ${{ matrix.rust }} @@ -47,3 +42,5 @@ jobs: run: | cd rust-bindings/bls-dash-sys cargo test + cd ../bls-signatures + cargo test diff --git a/.github/workflows/build-test.yaml b/.github/workflows/build-test.yaml index 90a550a5e4d2..8b253e05e7a8 100644 --- a/.github/workflows/build-test.yaml +++ b/.github/workflows/build-test.yaml @@ -17,19 +17,17 @@ concurrency: jobs: build: - name: ${{ matrix.os }}, ${{ matrix.builder }}, ${{ matrix.compiler.cc }}, ${{ matrix.backend }} backend + name: ${{ matrix.os }}, ${{ matrix.compiler.cc }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ macos-latest, ubuntu-latest ] - builder: [ cmake, autotools ] compiler: - cc: gcc cxx: g++ - cc: clang cxx: clang++ - backend: [ easy, gmp ] steps: - name: Checkout code uses: actions/checkout@v3 @@ -38,32 +36,23 @@ jobs: if: startsWith(matrix.os, 'ubuntu') run: | sudo apt-get update - sudo apt-get install -qq --yes valgrind libgmp-dev cmake + sudo apt-get install -qq --yes valgrind cmake hash -r cmake --version - name: Prepare build system for macOS if: startsWith(matrix.os, 'macos') run: | - ls -l export MACOSX_DEPLOYMENT_TARGET=10.14 - brew install autoconf automake gmp libtool pkg-config + brew install pkg-config - name: Build library using CMake - if: startsWith(matrix.builder, 'cmake') run: | mkdir -p build && cd build - CC=${{ matrix.compiler.cc }} CXX=${{ matrix.compiler.cxx }} cmake .. -DARITH=${{ matrix.backend }} -DBUILD_BLS_PYTHON_BINDINGS=0 -DCMAKE_BUILD_TYPE=Debug + CC=${{ matrix.compiler.cc }} CXX=${{ matrix.compiler.cxx }} cmake .. -DBUILD_BLS_PYTHON_BINDINGS=0 -DCMAKE_BUILD_TYPE=Debug cmake --build . -- -j 6 mv src/runtest .. - - name: Build library using GNU Autotools - if: startsWith(matrix.builder, 'autotools') - run: | - ./autogen.sh - CC=${{ matrix.compiler.cc }} CXX=${{ matrix.compiler.cxx }} ./configure --with-backend=${{ matrix.backend }} - make -j8 - - name: Run tests run: ./runtest diff --git a/.github/workflows/stale-issue.yml b/.github/workflows/stale-issue.yml old mode 100755 new mode 100644 diff --git a/.gitignore b/.gitignore index f968c1dbe44d..ec8e23435253 100644 --- a/.gitignore +++ b/.gitignore @@ -17,15 +17,6 @@ main .o obj/ src/*.o -depends/relic/CTestTestfile.cmake -depends/relic/bench/CTestTestfile.cmake -depends/relic/bin -depends/relic/include/relic_conf.h -depends/relic/include/relic_conf.h.in -depends/relic/include/relic_conf.h.old -depends/relic/include/stamp-h1 -depends/relic/test/CTestTestfile.cmake -contrib/gmp-6.1.2/ .idea .vscode diff --git a/CMakeLists.txt b/CMakeLists.txt index a224da20b626..b99a9f750f8a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,12 @@ endif() project(BLS) +if(MSVC) + enable_language(ASM_MASM) +else() + enable_language(ASM) +endif() + set(BUILD_BLS_JS_BINDINGS "1" CACHE STRING "") set(BUILD_BLS_PYTHON_BINDINGS "1" CACHE STRING "") set(BUILD_BLS_TESTS "1" CACHE STRING "") @@ -29,94 +35,27 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules ) -# Relic related options - -set(STBIN "off" CACHE STRING "Relic - Build static binaries") - -find_package(gmp) -if (GMP_FOUND) - message(STATUS "Found libgmp") - set(ARITH "gmp" CACHE STRING "") -else() - set(ARITH "easy" CACHE STRING "") -endif() - -if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(WSIZE "32" CACHE STRING "Relic - Processor word size") -else() - set(WSIZE "64" CACHE STRING "Relic - Processor word size") -endif() - -if(EMSCRIPTEN) - # emscripten needs arch set to be none since it can't compile assembly - set(ARCH "" CACHE STRING "") - # emscripten is a 32 bit compiler - set(WSIZE "32" CACHE STRING "Relic - Processor word size") -endif() - -if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - set(TIMER "ANSI" CACHE STRING "") - set(MULTI "OPENMP" CACHE STRING "") -else() - set(TIMER "CYCLE" CACHE STRING "") - set(MULTI "PTHREAD" CACHE STRING "") -endif() - -set(CHECK "off" CACHE STRING "") -set(VERBS "off" CACHE STRING "") -set(ALLOC "AUTO" CACHE STRING "") -set(SHLIB "off" CACHE STRING "") -set(DOCUM "off" CACHE STRING "") -set(FP_PRIME "381" CACHE STRING "Relic - Prime modulus size") - -if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(SEED "UDEV" CACHE STRING "") - set(FP_QNRES "off" CACHE STRING "") -elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") - set(SEED "WCGR" CACHE STRING "") - set(FP_QNRES "on" CACHE STRING "") -else() - set(SEED "UDEV" CACHE STRING "") - set(FP_QNRES "on" CACHE STRING "") -endif() - -set(FP_METHD "INTEG;INTEG;INTEG;MONTY;LOWER;SLIDE" CACHE STRING "") - -if(MSVC) - set(COMP_FLAGS "" CACHE STRING "") -else() - set(COMP_FLAGS "-O3 -funroll-loops -fomit-frame-pointer" CACHE STRING "") -endif() - -set(FP_PMERS "off" CACHE STRING "") -set(FPX_METHD "INTEG;INTEG;LAZYR" CACHE STRING "") -set(EP_PLAIN "off" CACHE STRING "") -set(EP_SUPER "off" CACHE STRING "") -# Disable relic tests and benchmarks -set(TESTS "0" CACHE STRING "Relic - Number of times each test is ran") -set(BENCH "0" CACHE STRING "Relic - Number of times each benchmark is ran") - -set(QUIET "on" CACHE STRING "Relic - Build with printing disabled") - -set(PP_EXT "LAZYR" CACHE STRING "") -set(PP_METHD "LAZYR;OATEP" CACHE STRING "") - # Disable mimalloc shared libraries and tests, enable secure mode set(MI_SECURE "on" CACHE STRING "") set(MI_BUILD_SHARED "off" CACHE STRING "") set(MI_BUILD_TESTS "off" CACHE STRING "") set(MI_OVERRIDE "off" CACHE STRING "") - -add_subdirectory(depends/relic) add_subdirectory(depends/mimalloc) -#message(STATUS "Patching Relic to make setjmp.h inclusion conditional") -# -#execute_process( -# COMMAND bash -c "git apply ${CMAKE_SOURCE_DIR}/setjmp_patch.diff" -# WORKING_DIRECTORY ${RELIC_SRC} -#) +include(FetchContent) + +set(BLST_GIT_TAG "a8cd361c9f671577aeab3f074098443af92a53fc") +set(BLST_REPOSITORY "https://github.com/supranational/blst") + +message(STATUS "blst will be built from: ${BLST_GIT_TAG} and repository ${BLST_REPOSITORY}") + +FetchContent_Declare( + blst + GIT_REPOSITORY ${BLST_REPOSITORY} + GIT_TAG ${BLST_GIT_TAG} +) +FetchContent_MakeAvailable(blst) add_subdirectory(src) @@ -128,14 +67,7 @@ endif() file(APPEND "${CMAKE_CURRENT_LIST_DIR}/build/include_paths.txt" "${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES};") -if(GMP_INCLUDES) - file(APPEND "${CMAKE_CURRENT_LIST_DIR}/build/include_paths.txt" "${GMP_INCLUDES};") -endif() - -# Write gmp library path for rust binding -if(GMP_LIBRARIES) - file(APPEND "${CMAKE_CURRENT_LIST_DIR}/build/gmp_libraries.txt" "${GMP_LIBRARIES}") -endif() +file(APPEND "${CMAKE_CURRENT_LIST_DIR}/build/include_paths.txt" "${blst_SOURCE_DIR}/bindings;") if(EMSCRIPTEN) if(BUILD_BLS_JS_BINDINGS) diff --git a/MANIFEST.in b/MANIFEST.in index 62cc22eaeea0..5ae9e0282fb1 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -25,11 +25,6 @@ prune depends/relic/preset prune depends/relic/test prune depends/relic/tools -# Autotools build -prune build-aux -prune autom4te.cache -exclude Makefile.am Makefile.*.include Makefile.in Makefile configure.ac aclocal.m4 autogen.sh - # dot{dir,file}s prune .github prune .vscode diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index 1c1e5d19d594..000000000000 --- a/Makefile.am +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2013-2016 The Bitcoin Core developers -# Copyright (c) 2022 The Dash Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING.MIT or http://www.opensource.org/licenses/mit-license.php. - -print-%: FORCE - @echo '$*'='$($*)' - -ACLOCAL_AMFLAGS = -I build-aux/m4 -.PHONY: deploy FORCE - -AM_LDFLAGS = $(HARDENED_LDFLAGS) $(CORE_LDFLAGS) $(GMP_LDFLAGS) -AM_CFLAGS = $(DEBUG_FLAGS) $(HARDENED_FLAGS) $(CORE_FLAGS) $(WARN_FLAGS) $(NOWARN_FLAGS) -AM_CPPFLAGS = $(CORE_CPPFLAGS) $(GMP_CPPFLAGS) -AM_CXXFLAGS = $(DEBUG_FLAGS) $(HARDENED_FLAGS) $(CORE_FLAGS) $(WARN_FLAGS) $(NOWARN_FLAGS) -PTHREAD_FLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) - -EXTRA_LIBRARIES = - -lib_LTLIBRARIES = -noinst_LTLIBRARIES = - -bin_PROGRAMS = -noinst_PROGRAMS = -EXTRA_DIST = - -CLEANFILES = - -include Makefile.bls.include - -CLEANFILES += $(LIBRELIC) $(LIBDASHBLS) $(LIBMIMALLOC) - -if USE_TESTS -CLEANFILES += $(DASHBLS_RUNTEST) -endif - -if USE_BENCH -CLEANFILES += $(DASHBLS_RUNBENCH) -endif diff --git a/Makefile.bench.include b/Makefile.bench.include deleted file mode 100644 index f584102a3294..000000000000 --- a/Makefile.bench.include +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2021 The PIVX developers -# Copyright (c) 2022 The Dash Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING.MIT or http://www.opensource.org/licenses/mit-license.php. - -DASHBLS_RUNBENCH = runbench - -runbench_SOURCES = \ - src/test-bench.cpp \ - src/test-utils.hpp - -runbench_SOURCES += \ - $(RELIC_H) \ - $(DASHBLS_H) - -runbench_CPPFLAGS = $(AM_CPPFLAGS) $(DASHBLS_INCLUDES) $(RELIC_INCLUDES) -runbench_CXXFLAGS = $(AM_CXXFLAGS) -runbench_LDFLAGS = -static $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS) - -runbench_LDADD = $(LIBDASHBLS) - -noinst_PROGRAMS += $(DASHBLS_RUNBENCH) diff --git a/Makefile.bls.include b/Makefile.bls.include deleted file mode 100644 index 7c35b3ced764..000000000000 --- a/Makefile.bls.include +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright (c) 2021 The PIVX developers -# Copyright (c) 2022 The Dash Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING.MIT or http://www.opensource.org/licenses/mit-license.php. - -LIBDASHBLS = libdashbls.la - -DASHBLS_CPPFLAGS = -DBLSALLOC_MIMALLOC=1 - -DASHBLS_INCLUDES = \ - -I$(builddir) \ - -I$(builddir)/obj \ - -I$(top_srcdir)/include/dashbls - -DASHBLS_H = \ - src/bls.hpp \ - src/chaincode.hpp \ - src/elements.hpp \ - src/extendedprivatekey.hpp \ - src/extendedpublickey.hpp \ - src/hdkeys.hpp \ - src/hkdf.hpp \ - src/legacy.hpp \ - src/privatekey.hpp \ - src/schemes.hpp \ - src/test-utils.hpp \ - src/threshold.hpp \ - src/util.hpp - -libdashbls_la_SOURCES = \ - src/bls.cpp \ - src/chaincode.cpp \ - src/elements.cpp \ - src/extendedprivatekey.cpp \ - src/extendedpublickey.cpp \ - src/legacy.cpp \ - src/privatekey.cpp \ - src/schemes.cpp \ - src/threshold.cpp - -libdashbls_la_SOURCES += \ - $(DASHBLS_H) \ - $(MIMALLOC_H) \ - $(RELIC_H) - -libdashbls_la_LIBADD = \ - $(LIBMIMALLOC) \ - $(LIBRELIC) \ - $(GMP_LIBS) - -libdashbls_la_CPPFLAGS = $(AM_CPPFLAGS) $(RELIC_INCLUDES) $(MIMALLOC_INCLUDES) $(DASHBLS_INCLUDES) $(DASHBLS_CPPFLAGS) -libdashbls_la_CXXFLAGS = $(AM_CXXFLAGS) -libdashbls_la_LDFLAGS = $(AM_LDFLAGS) - -include Makefile.mimalloc.include -include Makefile.relic.include - -if USE_TESTS -include Makefile.test.include -endif - -if USE_BENCH -include Makefile.bench.include -endif - -lib_LTLIBRARIES += $(LIBDASHBLS) diff --git a/Makefile.mimalloc.include b/Makefile.mimalloc.include deleted file mode 100644 index fada5fe32819..000000000000 --- a/Makefile.mimalloc.include +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2022-2025 The Dash Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING.MIT or http://www.opensource.org/licenses/mit-license.php. - -LIBMIMALLOC = libmimalloc-secure.la - -MIMALLOC_CPPFLAGS = \ - -DMI_SECURE=4 \ - -DNDEBUG - -MIMALLOC_INCLUDES = \ - -I$(top_srcdir)/depends/mimalloc/include \ - -I$(top_srcdir)/depends/mimalloc/src - -MIMALLOC_H = \ - depends/mimalloc/include/mimalloc-new-delete.h \ - depends/mimalloc/include/mimalloc-override.h \ - depends/mimalloc/include/mimalloc-stats.h \ - depends/mimalloc/include/mimalloc.h \ - depends/mimalloc/src/bitmap.h - -libmimalloc_secure_la_SOURCES = \ - $(MIMALLOC_H) \ - depends/mimalloc/src/alloc-aligned.c \ - depends/mimalloc/src/alloc-posix.c \ - depends/mimalloc/src/alloc.c \ - depends/mimalloc/src/arena-meta.c \ - depends/mimalloc/src/arena.c \ - depends/mimalloc/src/bitmap.c \ - depends/mimalloc/src/heap.c \ - depends/mimalloc/src/init.c \ - depends/mimalloc/src/libc.c \ - depends/mimalloc/src/options.c \ - depends/mimalloc/src/os.c \ - depends/mimalloc/src/page-map.c \ - depends/mimalloc/src/page.c \ - depends/mimalloc/src/random.c \ - depends/mimalloc/src/stats.c \ - depends/mimalloc/src/prim/prim.c - -libmimalloc_secure_la_CPPFLAGS = $(AM_CPPFLAGS) $(MIMALLOC_CPPFLAGS) $(MIMALLOC_INCLUDES) -libmimalloc_secure_la_CXXFLAGS = $(AM_CXXFLAGS) -libmimalloc_secure_la_CFLAGS = $(AM_CFLAGS) -libmimalloc_secure_la_LDFLAGS = $(AM_LDFLAGS) - -noinst_LTLIBRARIES += $(LIBMIMALLOC) diff --git a/Makefile.relic.include b/Makefile.relic.include deleted file mode 100644 index 92bd7c7e8f5b..000000000000 --- a/Makefile.relic.include +++ /dev/null @@ -1,470 +0,0 @@ -# Copyright (c) 2021 The PIVX developers -# Copyright (c) 2022 The Dash Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING.MIT or http://www.opensource.org/licenses/mit-license.php. - -LIBRELIC = librelic.la - -RELIC_INCLUDES = \ - -I$(top_srcdir)/depends/relic/include \ - -I$(top_srcdir)/depends/relic/include/low \ - -I$(top_srcdir)/depends/relic/src/tmpl - -RELIC_H = \ - depends/relic/include/relic.h \ - depends/relic/include/relic_alloc.h \ - depends/relic/include/relic_arch.h \ - depends/relic/include/relic_bc.h \ - depends/relic/include/relic_bench.h \ - depends/relic/include/relic_bn.h \ - depends/relic/include/relic_conf.h \ - depends/relic/include/relic_core.h \ - depends/relic/include/relic_cp.h \ - depends/relic/include/relic_dv.h \ - depends/relic/include/relic_eb.h \ - depends/relic/include/relic_ec.h \ - depends/relic/include/relic_ed.h \ - depends/relic/include/relic_ep.h \ - depends/relic/include/relic_epx.h \ - depends/relic/include/relic_err.h \ - depends/relic/include/relic_fb.h \ - depends/relic/include/relic_fbx.h \ - depends/relic/include/relic_fp.h \ - depends/relic/include/relic_fpx.h \ - depends/relic/include/relic_label.h \ - depends/relic/include/relic_md.h \ - depends/relic/include/relic_mpc.h \ - depends/relic/include/relic_multi.h \ - depends/relic/include/relic_pc.h \ - depends/relic/include/relic_pp.h \ - depends/relic/include/relic_rand.h \ - depends/relic/include/relic_test.h \ - depends/relic/include/relic_types.h \ - depends/relic/include/relic_util.h \ - depends/relic/include/low/relic_bn_low.h \ - depends/relic/include/low/relic_dv_low.h \ - depends/relic/include/low/relic_fb_low.h \ - depends/relic/include/low/relic_fp_low.h \ - depends/relic/include/low/relic_fpx_low.h \ - depends/relic/src/arch/lzcnt.inc \ - depends/relic/src/tmpl/relic_tmpl_map.h - -RELIC_SOURCES = \ - depends/relic/src/relic_err.c \ - depends/relic/src/relic_core.c \ - depends/relic/src/relic_conf.c \ - depends/relic/src/relic_util.c - -BN_SOURCES = \ - depends/relic/src/bn/relic_bn_add.c \ - depends/relic/src/bn/relic_bn_cmp.c \ - depends/relic/src/bn/relic_bn_div.c \ - depends/relic/src/bn/relic_bn_factor.c \ - depends/relic/src/bn/relic_bn_gcd.c \ - depends/relic/src/bn/relic_bn_inv.c \ - depends/relic/src/bn/relic_bn_lcm.c \ - depends/relic/src/bn/relic_bn_mem.c \ - depends/relic/src/bn/relic_bn_mod.c \ - depends/relic/src/bn/relic_bn_mul.c \ - depends/relic/src/bn/relic_bn_mxp.c \ - depends/relic/src/bn/relic_bn_prime.c \ - depends/relic/src/bn/relic_bn_rec.c \ - depends/relic/src/bn/relic_bn_shift.c \ - depends/relic/src/bn/relic_bn_smb.c \ - depends/relic/src/bn/relic_bn_sqr.c \ - depends/relic/src/bn/relic_bn_srt.c \ - depends/relic/src/bn/relic_bn_util.c - -FP_SOURCES = \ - depends/relic/src/fp/relic_fp_add.c \ - depends/relic/src/fp/relic_fp_cmp.c \ - depends/relic/src/fp/relic_fp_exp.c \ - depends/relic/src/fp/relic_fp_inv.c \ - depends/relic/src/fp/relic_fp_mul.c \ - depends/relic/src/fp/relic_fp_param.c \ - depends/relic/src/fp/relic_fp_prime.c \ - depends/relic/src/fp/relic_fp_rdc.c \ - depends/relic/src/fp/relic_fp_shift.c \ - depends/relic/src/fp/relic_fp_sqr.c \ - depends/relic/src/fp/relic_fp_srt.c \ - depends/relic/src/fp/relic_fp_util.c - -FPX_SOURCES = \ - depends/relic/src/fpx/relic_fp2_mul.c \ - depends/relic/src/fpx/relic_fp2_sqr.c \ - depends/relic/src/fpx/relic_fp3_mul.c \ - depends/relic/src/fpx/relic_fp3_sqr.c \ - depends/relic/src/fpx/relic_fp4_mul.c \ - depends/relic/src/fpx/relic_fp4_sqr.c \ - depends/relic/src/fpx/relic_fp6_mul.c \ - depends/relic/src/fpx/relic_fp6_sqr.c \ - depends/relic/src/fpx/relic_fp8_mul.c \ - depends/relic/src/fpx/relic_fp8_sqr.c \ - depends/relic/src/fpx/relic_fp9_mul.c \ - depends/relic/src/fpx/relic_fp9_sqr.c \ - depends/relic/src/fpx/relic_fp12_mul.c \ - depends/relic/src/fpx/relic_fp12_sqr.c \ - depends/relic/src/fpx/relic_fp18_mul.c \ - depends/relic/src/fpx/relic_fp18_sqr.c \ - depends/relic/src/fpx/relic_fp24_mul.c \ - depends/relic/src/fpx/relic_fp24_sqr.c \ - depends/relic/src/fpx/relic_fp48_mul.c \ - depends/relic/src/fpx/relic_fp48_sqr.c \ - depends/relic/src/fpx/relic_fp54_mul.c \ - depends/relic/src/fpx/relic_fp54_sqr.c \ - depends/relic/src/fpx/relic_fpx_add.c \ - depends/relic/src/fpx/relic_fpx_cmp.c \ - depends/relic/src/fpx/relic_fpx_cyc.c \ - depends/relic/src/fpx/relic_fpx_exp.c \ - depends/relic/src/fpx/relic_fpx_field.c \ - depends/relic/src/fpx/relic_fpx_frb.c \ - depends/relic/src/fpx/relic_fpx_inv.c \ - depends/relic/src/fpx/relic_fpx_pck.c \ - depends/relic/src/fpx/relic_fpx_rdc.c \ - depends/relic/src/fpx/relic_fpx_srt.c \ - depends/relic/src/fpx/relic_fpx_util.c - -FB_SOURCES = \ - depends/relic/src/fb/relic_fb_add.c \ - depends/relic/src/fb/relic_fb_cmp.c \ - depends/relic/src/fb/relic_fb_exp.c \ - depends/relic/src/fb/relic_fb_inv.c \ - depends/relic/src/fb/relic_fb_itr.c \ - depends/relic/src/fb/relic_fb_mul.c \ - depends/relic/src/fb/relic_fb_param.c \ - depends/relic/src/fb/relic_fb_poly.c \ - depends/relic/src/fb/relic_fb_rdc.c \ - depends/relic/src/fb/relic_fb_shift.c \ - depends/relic/src/fb/relic_fb_slv.c \ - depends/relic/src/fb/relic_fb_sqr.c \ - depends/relic/src/fb/relic_fb_srt.c \ - depends/relic/src/fb/relic_fb_trc.c \ - depends/relic/src/fb/relic_fb_util.c - -EP_SOURCES = \ - depends/relic/src/ep/relic_ep_add.c \ - depends/relic/src/ep/relic_ep_cmp.c \ - depends/relic/src/ep/relic_ep_curve.c \ - depends/relic/src/ep/relic_ep_dbl.c \ - depends/relic/src/ep/relic_ep_map.c \ - depends/relic/src/ep/relic_ep_mul.c \ - depends/relic/src/ep/relic_ep_mul_fix.c \ - depends/relic/src/ep/relic_ep_mul_sim.c \ - depends/relic/src/ep/relic_ep_neg.c \ - depends/relic/src/ep/relic_ep_norm.c \ - depends/relic/src/ep/relic_ep_param.c \ - depends/relic/src/ep/relic_ep_pck.c \ - depends/relic/src/ep/relic_ep_psi.c \ - depends/relic/src/ep/relic_ep_util.c - -EPX_SOURCES = \ - depends/relic/src/epx/relic_ep2_add.c \ - depends/relic/src/epx/relic_ep2_cmp.c \ - depends/relic/src/epx/relic_ep2_curve.c \ - depends/relic/src/epx/relic_ep2_dbl.c \ - depends/relic/src/epx/relic_ep2_frb.c \ - depends/relic/src/epx/relic_ep2_map.c \ - depends/relic/src/epx/relic_ep2_mul.c \ - depends/relic/src/epx/relic_ep2_mul_cof.c \ - depends/relic/src/epx/relic_ep2_mul_fix.c \ - depends/relic/src/epx/relic_ep2_mul_sim.c \ - depends/relic/src/epx/relic_ep2_neg.c \ - depends/relic/src/epx/relic_ep2_norm.c \ - depends/relic/src/epx/relic_ep2_pck.c \ - depends/relic/src/epx/relic_ep2_util.c \ - depends/relic/src/epx/relic_ep4_add.c \ - depends/relic/src/epx/relic_ep4_cmp.c \ - depends/relic/src/epx/relic_ep4_curve.c \ - depends/relic/src/epx/relic_ep4_dbl.c \ - depends/relic/src/epx/relic_ep4_frb.c \ - depends/relic/src/epx/relic_ep4_map.c \ - depends/relic/src/epx/relic_ep4_mul.c \ - depends/relic/src/epx/relic_ep4_mul_cof.c \ - depends/relic/src/epx/relic_ep4_mul_fix.c \ - depends/relic/src/epx/relic_ep4_mul_sim.c \ - depends/relic/src/epx/relic_ep4_neg.c \ - depends/relic/src/epx/relic_ep4_norm.c \ - depends/relic/src/epx/relic_ep4_util.c - -EB_SOURCES = \ - depends/relic/src/eb/relic_eb_add.c \ - depends/relic/src/eb/relic_eb_cmp.c \ - depends/relic/src/eb/relic_eb_curve.c \ - depends/relic/src/eb/relic_eb_dbl.c \ - depends/relic/src/eb/relic_eb_frb.c \ - depends/relic/src/eb/relic_eb_hlv.c \ - depends/relic/src/eb/relic_eb_map.c \ - depends/relic/src/eb/relic_eb_mul.c \ - depends/relic/src/eb/relic_eb_mul_fix.c \ - depends/relic/src/eb/relic_eb_mul_sim.c \ - depends/relic/src/eb/relic_eb_neg.c \ - depends/relic/src/eb/relic_eb_norm.c \ - depends/relic/src/eb/relic_eb_param.c \ - depends/relic/src/eb/relic_eb_pck.c \ - depends/relic/src/eb/relic_eb_util.c - -ED_SOURCES = \ - depends/relic/src/ed/relic_ed_add.c \ - depends/relic/src/ed/relic_ed_cmp.c \ - depends/relic/src/ed/relic_ed_curve.c \ - depends/relic/src/ed/relic_ed_dbl.c \ - depends/relic/src/ed/relic_ed_map.c \ - depends/relic/src/ed/relic_ed_mul.c \ - depends/relic/src/ed/relic_ed_mul_fix.c \ - depends/relic/src/ed/relic_ed_mul_sim.c \ - depends/relic/src/ed/relic_ed_neg.c \ - depends/relic/src/ed/relic_ed_norm.c \ - depends/relic/src/ed/relic_ed_param.c \ - depends/relic/src/ed/relic_ed_pck.c \ - depends/relic/src/ed/relic_ed_util.c - -PP_SOURCES = \ - depends/relic/src/pp/relic_pp_add_k2.c \ - depends/relic/src/pp/relic_pp_add_k8.c \ - depends/relic/src/pp/relic_pp_add_k12.c \ - depends/relic/src/pp/relic_pp_add_k24.c \ - depends/relic/src/pp/relic_pp_add_k48.c \ - depends/relic/src/pp/relic_pp_add_k54.c \ - depends/relic/src/pp/relic_pp_dbl_k2.c \ - depends/relic/src/pp/relic_pp_dbl_k8.c \ - depends/relic/src/pp/relic_pp_dbl_k12.c \ - depends/relic/src/pp/relic_pp_dbl_k24.c \ - depends/relic/src/pp/relic_pp_dbl_k48.c \ - depends/relic/src/pp/relic_pp_dbl_k54.c \ - depends/relic/src/pp/relic_pp_exp_k2.c \ - depends/relic/src/pp/relic_pp_exp_k8.c \ - depends/relic/src/pp/relic_pp_exp_k12.c \ - depends/relic/src/pp/relic_pp_exp_k24.c \ - depends/relic/src/pp/relic_pp_exp_k48.c \ - depends/relic/src/pp/relic_pp_exp_k54.c \ - depends/relic/src/pp/relic_pp_map.c \ - depends/relic/src/pp/relic_pp_map_k2.c \ - depends/relic/src/pp/relic_pp_map_k8.c \ - depends/relic/src/pp/relic_pp_map_k12.c \ - depends/relic/src/pp/relic_pp_map_k24.c \ - depends/relic/src/pp/relic_pp_map_k48.c \ - depends/relic/src/pp/relic_pp_map_k54.c \ - depends/relic/src/pp/relic_pp_norm.c - -PC_SOURCES = \ - depends/relic/src/pc/relic_pc_core.c \ - depends/relic/src/pc/relic_pc_exp.c \ - depends/relic/src/pc/relic_pc_util.c - -MD_SOURCES = \ - depends/relic/src/md/blake2.h \ - depends/relic/src/md/blake2-impl.h \ - depends/relic/src/md/blake2s-ref.c \ - depends/relic/src/md/relic_md_blake2s.c \ - depends/relic/src/md/relic_md_hmac.c \ - depends/relic/src/md/relic_md_kdf.c \ - depends/relic/src/md/relic_md_mgf.c \ - depends/relic/src/md/relic_md_sha224.c \ - depends/relic/src/md/relic_md_sha256.c \ - depends/relic/src/md/relic_md_sha384.c \ - depends/relic/src/md/relic_md_sha512.c \ - depends/relic/src/md/relic_md_xmd.c \ - depends/relic/src/md/sha.h \ - depends/relic/src/md/sha224-256.c \ - depends/relic/src/md/sha384-512.c \ - depends/relic/src/md/sha_private.h - -EXTRA_DIST += \ - depends/relic/src/arch/relic_arch_arm.c \ - depends/relic/src/arch/relic_arch_none.c \ - depends/relic/src/arch/relic_arch_x64.c \ - depends/relic/src/arch/relic_arch_x86.c - -RELIC_SOURCES += \ - depends/relic/src/arch/relic_arch_@CPU_ARCH@.c \ - depends/relic/src/rand/relic_rand_call.c \ - depends/relic/src/rand/relic_rand_core.c \ - depends/relic/src/rand/relic_rand_hashd.c \ - depends/relic/src/rand/relic_rand_udev.c - -if WITH_DV -RELIC_SOURCES += \ - depends/relic/src/dv/relic_dv_mem.c \ - depends/relic/src/dv/relic_dv_util.c -endif - -if ARITH_EASY -if WITH_BN -RELIC_SOURCES += $(BN_SOURCES) \ - depends/relic/src/low/easy/relic_bn_add_low.c \ - depends/relic/src/low/easy/relic_bn_div_low.c \ - depends/relic/src/low/easy/relic_bn_mod_low.c \ - depends/relic/src/low/easy/relic_bn_mul_low.c \ - depends/relic/src/low/easy/relic_bn_shift_low.c \ - depends/relic/src/low/easy/relic_bn_sqr_low.c -endif - -if WITH_FP -RELIC_SOURCES += $(FP_SOURCES) \ - depends/relic/src/low/easy/relic_fp_add_low.c \ - depends/relic/src/low/easy/relic_fp_inv_low.c \ - depends/relic/src/low/easy/relic_fp_mul_low.c \ - depends/relic/src/low/easy/relic_fp_rdc_low.c \ - depends/relic/src/low/easy/relic_fp_shift_low.c \ - depends/relic/src/low/easy/relic_fp_sqr_low.c -endif - -if WITH_FPX -RELIC_SOURCES += $(FPX_SOURCES) \ - depends/relic/src/low/easy/relic_fpx_add_low.c \ - depends/relic/src/low/easy/relic_fpx_mul_low.c \ - depends/relic/src/low/easy/relic_fpx_rdc_low.c \ - depends/relic/src/low/easy/relic_fpx_sqr_low.c -endif - -if WITH_FB -RELIC_SOURCES += $(FB_SOURCES) \ - depends/relic/src/low/easy/relic_fb_add_low.c \ - depends/relic/src/low/easy/relic_fb_inv_low.c \ - depends/relic/src/low/easy/relic_fb_itr_low.c \ - depends/relic/src/low/easy/relic_fb_mul_low.c \ - depends/relic/src/low/easy/relic_fb_rdc_low.c \ - depends/relic/src/low/easy/relic_fb_shift_low.c \ - depends/relic/src/low/easy/relic_fb_slv_low.c \ - depends/relic/src/low/easy/relic_fb_sqr_low.c \ - depends/relic/src/low/easy/relic_fb_srt_low.c \ - depends/relic/src/low/easy/relic_fb_trc_low.c -endif -endif - -if ARITH_GMP -if WITH_BN -RELIC_SOURCES += $(BN_SOURCES) \ - depends/relic/src/low/gmp/relic_bn_add_low.c \ - depends/relic/src/low/gmp/relic_bn_div_low.c \ - depends/relic/src/low/gmp/relic_bn_mod_low.c \ - depends/relic/src/low/gmp/relic_bn_mul_low.c \ - depends/relic/src/low/gmp/relic_bn_shift_low.c \ - depends/relic/src/low/gmp/relic_bn_sqr_low.c -endif - -if WITH_FP -RELIC_SOURCES += $(FP_SOURCES) \ - depends/relic/src/low/gmp/relic_fp_add_low.c \ - depends/relic/src/low/gmp/relic_fp_inv_low.c \ - depends/relic/src/low/gmp/relic_fp_mul_low.c \ - depends/relic/src/low/gmp/relic_fp_rdc_low.c \ - depends/relic/src/low/gmp/relic_fp_shift_low.c \ - depends/relic/src/low/gmp/relic_fp_sqr_low.c -endif - -if WITH_FPX -RELIC_SOURCES += $(FPX_SOURCES) \ - depends/relic/src/low/easy/relic_fpx_add_low.c \ - depends/relic/src/low/easy/relic_fpx_mul_low.c \ - depends/relic/src/low/easy/relic_fpx_rdc_low.c \ - depends/relic/src/low/easy/relic_fpx_sqr_low.c -endif - -if WITH_FB -RELIC_SOURCES += $(FB_SOURCES) \ - depends/relic/src/low/gmp/relic_fb_add_low.c \ - depends/relic/src/low/easy/relic_fb_inv_low.c \ - depends/relic/src/low/easy/relic_fb_itr_low.c \ - depends/relic/src/low/easy/relic_fb_mul_low.c \ - depends/relic/src/low/easy/relic_fb_rdc_low.c \ - depends/relic/src/low/gmp/relic_fb_shift_low.c \ - depends/relic/src/low/easy/relic_fb_slv_low.c \ - depends/relic/src/low/easy/relic_fb_sqr_low.c \ - depends/relic/src/low/easy/relic_fb_srt_low.c \ - depends/relic/src/low/easy/relic_fb_trc_low.c -endif -endif - -if WITH_FBX -RELIC_SOURCES += \ - depends/relic/src/fbx/relic_fb2_inv.c \ - depends/relic/src/fbx/relic_fb2_mul.c \ - depends/relic/src/fbx/relic_fb2_slv.c \ - depends/relic/src/fbx/relic_fb2_sqr.c -endif - -if WITH_EP -RELIC_SOURCES += $(EP_SOURCES) -endif - -if WITH_EPX -RELIC_SOURCES += $(EPX_SOURCES) -endif - -if WITH_EB -RELIC_SOURCES += $(EB_SOURCES) -endif - -if WITH_ED -RELIC_SOURCES += $(ED_SOURCES) -endif - -if WITH_PP -RELIC_SOURCES += $(PP_SOURCES) -endif - -if WITH_PC -RELIC_SOURCES += $(PC_SOURCES) -endif - -if WITH_CP -RELIC_SOURCES += \ - depends/relic/src/cp/relic_cp_bbs.c \ - depends/relic/src/cp/relic_cp_bdpe.c \ - depends/relic/src/cp/relic_cp_bgn.c \ - depends/relic/src/cp/relic_cp_bls.c \ - depends/relic/src/cp/relic_cp_cls.c \ - depends/relic/src/cp/relic_cp_cmlhs.c \ - depends/relic/src/cp/relic_cp_ecdh.c \ - depends/relic/src/cp/relic_cp_ecdsa.c \ - depends/relic/src/cp/relic_cp_ecies.c \ - depends/relic/src/cp/relic_cp_ecmqv.c \ - depends/relic/src/cp/relic_cp_ecss.c \ - depends/relic/src/cp/relic_cp_ers.c \ - depends/relic/src/cp/relic_cp_etrs.c \ - depends/relic/src/cp/relic_cp_ghpe.c \ - depends/relic/src/cp/relic_cp_ibe.c \ - depends/relic/src/cp/relic_cp_mklhs.c \ - depends/relic/src/cp/relic_cp_mpss.c \ - depends/relic/src/cp/relic_cp_pcdel.c \ - depends/relic/src/cp/relic_cp_phpe.c \ - depends/relic/src/cp/relic_cp_pok.c \ - depends/relic/src/cp/relic_cp_pss.c \ - depends/relic/src/cp/relic_cp_rabin.c \ - depends/relic/src/cp/relic_cp_rsa.c \ - depends/relic/src/cp/relic_cp_sok.c \ - depends/relic/src/cp/relic_cp_sokaka.c \ - depends/relic/src/cp/relic_cp_vbnn.c \ - depends/relic/src/cp/relic_cp_zss.c -endif - -if WITH_BC -RELIC_SOURCES += \ - depends/relic/src/bc/relic_bc_aes.c \ - depends/relic/src/bc/rijndael-alg-fst.c \ - depends/relic/src/bc/rijndael-alg-fst.h \ - depends/relic/src/bc/rijndael-api-fst.c \ - depends/relic/src/bc/rijndael-api-fst.h -endif - -if WITH_MD -RELIC_SOURCES += $(MD_SOURCES) -endif - -if WITH_MPC -RELIC_SOURCES += \ - depends/relic/src/mpc/relic_mt_mpc.c \ - depends/relic/src/mpc/relic_pc_mpc.c -endif - -librelic_la_SOURCES = \ - $(RELIC_SOURCES) \ - $(RELIC_H) - -librelic_la_CPPFLAGS = $(AM_CPPFLAGS) $(RELIC_CPPFLAGS) $(RELIC_INCLUDES) -librelic_la_CXXFLAGS = $(AM_CXXFLAGS) -librelic_la_CFLAGS = $(AM_CFLAGS) -librelic_la_LDFLAGS = $(AM_LDFLAGS) - -noinst_LTLIBRARIES += $(LIBRELIC) diff --git a/Makefile.test.include b/Makefile.test.include deleted file mode 100644 index a8ec86cb59d1..000000000000 --- a/Makefile.test.include +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2021 The PIVX developers -# Copyright (c) 2022 The Dash Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING.MIT or http://www.opensource.org/licenses/mit-license.php. - -DASHBLS_RUNTEST = runtest - -RUNTEST_INCLUDES = \ - -I$(top_srcdir)/depends/catch2/include - -RUNTEST_H = \ - depends/catch2/include/catch2/catch.hpp - -runtest_SOURCES = \ - $(DASHBLS_H) \ - $(RELIC_H) \ - $(RUNTEST_H) \ - src/test.cpp \ - src/test-utils.hpp - -runtest_CPPFLAGS = $(AM_CPPFLAGS) $(DASHBLS_INCLUDES) $(RELIC_INCLUDES) $(RUNTEST_INCLUDES) -runtest_CXXFLAGS = $(AM_CXXFLAGS) -runtest_LDFLAGS = -static $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS) - -runtest_LDADD = $(LIBDASHBLS) - -noinst_PROGRAMS += $(DASHBLS_RUNTEST) diff --git a/README.md b/README.md index 1d22cdfd4d66..d3292e46df68 100644 --- a/README.md +++ b/README.md @@ -11,20 +11,19 @@ > **This library has not undergone a formal security review.** `bls-signatures` is a cross-platform library implementing BLS12-381 primitives for Dash built on -the [`relic`](https://github.com/relic-toolkit/relic) toolkit with bindings available in +the [`blst library`](https://github.com/supranational/blst.git) toolkit with bindings available in [Python](./binds/python), [Rust](./rust-bindings/), [Go](./go-bindings/) and [Javascript](./js-bindings). ## Dependencies * A C++17 capable compiler (GCC 9, Clang 7 or higher) -* CMake 3.18 or higher (or Autoconf 2.71 or higher; with libtool and automake) -* [`libgmp`](https://gmplib.org/) (for fast arithmetic, **optional**) +* CMake 3.18 or higher Additionally, the following dependencies are supplied by the codebase * [`catch2`](https://github.com/catchorg/Catch2) (for tests) * [`mimalloc`](https://github.com/microsoft/mimalloc) (for secure memory operations) -* [`relic`](https://github.com/relic-toolkit/relic) (for cryptographic operations) +* [`blst`](https://github.com/supranational/blst.git) (for cryptographic operations) ## Build library @@ -100,6 +99,11 @@ uv run pytest -v binds/python/test_unit.py uv run pytest -v binds/python/test_bench.py --benchmark-only ``` +## BLST license + +BLST is used with the +[Apache 2.0 license](https://github.com/supranational/blst/blob/master/LICENSE) + ## License ```text diff --git a/apple.rust.deps.sh b/apple.rust.deps.sh index b2ebc41a4ff2..ad9f3b9809e9 100755 --- a/apple.rust.deps.sh +++ b/apple.rust.deps.sh @@ -1,337 +1,87 @@ -#!/bin/sh -set -x +#!/bin/bash +# +# Builds libdashbls (with the blst backend CMake fetches) for Apple platforms, +# for consumption by rust-bindings' "apple" feature. +# +# Usage: apple.rust.deps.sh +# +# Artefacts are placed in build/artefacts//: libdashbls.a and +# libmimalloc-secure.a. The former contains the blst objects; no external +# arithmetic library (the relic-era GMP dependency is gone). + set -e -# "x86_64-apple-ios" -# "aarch64-apple-ios" -# "aarch64-apple-ios-sim" -# "x86_64-apple-darwin" -# "aarch64-apple-darwin" -# TODO: it's probably needs to be optimized in order to increase better build velocity -# TODO: so we need to combine multiple targets + TARGET=$1 -git submodule update --init -MIN_IOS="13.0" -MIN_WATCHOS="5.0" -MIN_TVOS=$MIN_IOS -MIN_MACOS="10.15" -IPHONEOS=iphoneos -IPHONESIMULATOR=iphonesimulator -WATCHOS=watchos -WATCHSIMULATOR=watchsimulator -TVOS=appletvos -TVSIMULATOR=appletvsimulator -MACOS=macosx +MACOS="macosx" +IPHONEOS="iphoneos" +IPHONESIMULATOR="iphonesimulator" -LOGICALCPU_MAX=$(sysctl -n hw.logicalcpu_max) -BUILD=build - -version_min_flag() { - PLATFORM=$1 - FLAG="" - # shellcheck disable=SC2039 - # shellcheck disable=SC2053 - if [[ $PLATFORM = $IPHONEOS ]]; then - FLAG="-miphoneos-version-min=${MIN_IOS}" - elif [[ $PLATFORM = $IPHONESIMULATOR ]]; then - FLAG="-mios-simulator-version-min=${MIN_IOS}" - elif [[ $PLATFORM = $WATCHOS ]]; then - FLAG="-mwatchos-version-min=${MIN_WATCHOS}" - elif [[ $PLATFORM = $WATCHSIMULATOR ]]; then - FLAG="-mwatchos-simulator-version-min=${MIN_WATCHOS}" - elif [[ $PLATFORM = $TVOS ]]; then - FLAG="-mtvos-version-min=${MIN_TVOS}" - elif [[ $PLATFORM = $TVSIMULATOR ]]; then - FLAG="-mtvos-simulator-version-min=${MIN_TVOS}" - elif [[ $PLATFORM = $MACOS ]]; then - FLAG="-mmacosx-version-min=${MIN_MACOS}" - fi - echo $FLAG -} +BUILD="build" +LOGICALCPU_MAX=$(sysctl -n hw.logicalcpu_max) prepare() { - download_gmp() { - GMP_VERSION="6.3.0" - CURRENT_DIR=$(pwd) - echo "$CURRENT_DIR" - # shellcheck disable=SC2039,SC2164 - pushd ${BUILD} - mkdir -p "contrib" - if [ ! -s "contrib/gmp-${GMP_VERSION}.tar.bz2" ]; then - curl -L -o "contrib/gmp-${GMP_VERSION}.tar.bz2" https://ftp.gnu.org/gnu/gmp/gmp-${GMP_VERSION}.tar.bz2 - fi - rm -rf "contrib/gmp" - # shellcheck disable=SC2039,SC2164 - pushd contrib - tar xfj "gmp-${GMP_VERSION}.tar.bz2" - mv gmp-${GMP_VERSION} gmp - # shellcheck disable=SC2039,SC2164 - popd #contrib - # shellcheck disable=SC2039,SC2164 - popd #build - } + # shellcheck disable=SC2039,SC2164 + pushd ${BUILD} download_cmake_toolchain() { - if [ ! -s "${BUILD}/ios.toolchain.cmake" ]; then + if [ ! -s "ios.toolchain.cmake" ]; then SHA256_HASH="d02857ff6bd64f1d7109ca59c3e4f3b2f89d0663c412146e6977c679801b3243" - curl -o "${BUILD}/ios.toolchain.cmake" https://raw.githubusercontent.com/leetal/ios-cmake/c55677a4445b138c9ef2650d3c21f22cc78c2357/ios.toolchain.cmake - DOWNLOADED_HASH=$(shasum -a 256 ${BUILD}/ios.toolchain.cmake | cut -f 1 -d " ") - if [ $SHA256_HASH != "$DOWNLOADED_HASH" ]; then + echo "Downloading ios.toolchain.cmake" + curl -o "ios.toolchain.cmake" https://raw.githubusercontent.com/leetal/ios-cmake/c55677a4445b138c9ef2650d3c21f22cc78c2357/ios.toolchain.cmake + DOWNLOADED_HASH=$(shasum -a 256 ios.toolchain.cmake | cut -f 1 -d " ") + if [ "$SHA256_HASH" != "$DOWNLOADED_HASH" ]; then echo "Error: sha256 checksum of ios.toolchain.cmake mismatch" >&2 exit 1 fi fi } - download_relic() { - CURRENT_DIR=$(pwd) - echo "$CURRENT_DIR" - mkdir -p "${CURRENT_DIR}/${BUILD}/depends" - if [ ! -s "${CURRENT_DIR}/${BUILD}/depends/relic" ]; then - # shellcheck disable=SC2039,SC2164 - pushd "${CURRENT_DIR}/${BUILD}/depends" - git clone --depth 1 --branch "feat/ios-support" https://github.com/pankcuf/relic - # shellcheck disable=SC2039,SC2164 - pushd relic - git fetch --depth 1 origin 19fb6d79a77ade4ae8cd70d2b0ef7aab8720d1ae - git checkout 19fb6d79a77ade4ae8cd70d2b0ef7aab8720d1ae - # shellcheck disable=SC2039,SC2164 - popd #relic - # shellcheck disable=SC2039,SC2164 - popd #depends - fi - } - rm -rf ${BUILD} - mkdir -p ${BUILD} - download_relic - download_gmp download_cmake_toolchain -} -build_gmp_arch() { - PLATFORM=$1 - ARCH=$2 - PFX=${PLATFORM}-${ARCH} - # why this works with this host only? - HOST=aarch64-apple-darwin - # shellcheck disable=SC2039,SC2164 - pushd ${BUILD} - SDK=$(xcrun --sdk "$PLATFORM" --show-sdk-path) - PLATFORM_PATH=$(xcrun --sdk "$PLATFORM" --show-sdk-platform-path) - CLANG=$(xcrun --sdk "$PLATFORM" --find clang) - DEVELOPER=$(xcode-select --print-path) - CURRENT_DIR=$(pwd) - export PATH="${PLATFORM_PATH}/Developer/usr/bin:${DEVELOPER}/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin" - mkdir gmplib-"${PLATFORM}"-"${ARCH}" - CFLAGS="-Wno-unused-value -fembed-bitcode -arch ${ARCH} --sysroot=${SDK} $(version_min_flag "$PLATFORM")" - CONFIGURESCRIPT="gmp_configure_script.sh" - # shellcheck disable=SC2039,SC2164 - pushd contrib - # shellcheck disable=SC2039,SC2164 - pushd gmp - make clean || true - make distclean || true - echo "HOST: $HOST" - echo "PREFIX: ${CURRENT_DIR}/gmplib-${PFX}" - - cat >"$CONFIGURESCRIPT" << EOF -#!/bin/sh -./configure \ -CC="$CLANG" CFLAGS="$CFLAGS" CPPFLAGS="$CFLAGS" LDFLAGS="$CFLAGS" \ ---host=${HOST} --prefix="${CURRENT_DIR}/gmplib-${PFX}" \ ---disable-shared --enable-static --disable-assembly -v -EOF - - chmod a+x "$CONFIGURESCRIPT" - sh "$CONFIGURESCRIPT" - rm "$CONFIGURESCRIPT" - - # shellcheck disable=SC2039 - mkdir -p "${CURRENT_DIR}/log" - # shellcheck disable=SC2039 - make -j "$LOGICALCPU_MAX" &> "${CURRENT_DIR}"/log/gmplib-"${PFX}"-build.log - # shellcheck disable=SC2039 - make install &> "${CURRENT_DIR}"/log/gmplib-"${PFX}"-install.log - #make check - #exit 1 - # shellcheck disable=SC2039,SC2164 - popd # gmp - # shellcheck disable=SC2039,SC2164 - popd # contrib # shellcheck disable=SC2039,SC2164 popd # build } -build_relic_arch() { +# Maps (platform, arch) onto the leetal/ios-cmake PLATFORM value. +cmake_platform() { PLATFORM=$1 ARCH=$2 - PFX=${PLATFORM}-${ARCH} - - # shellcheck disable=SC2039,SC2164 - pushd ${BUILD} - - SDK=$(xcrun --sdk "$PLATFORM" --show-sdk-path) - - BUILDDIR=relic-"${PFX}" - TOOLCHAIN=$(pwd)/ios.toolchain.cmake - GMP_PFX=$(pwd)/gmplib-${PFX} - rm -rf "$BUILDDIR" - mkdir "$BUILDDIR" - # shellcheck disable=SC2039,SC2164 - pushd "$BUILDDIR" - - unset CC - # shellcheck disable=SC2155 - export CC=$(xcrun --sdk "${PLATFORM}" --find clang) - - WSIZE=0 - IOS_PLATFORM="" - OPTIMIZATIONFLAGS="" - DEPLOYMENT_TARGET="" - - # shellcheck disable=SC2039 - # shellcheck disable=SC2053 - if [[ $PLATFORM = $IPHONEOS ]]; then - if [[ $ARCH = "arm64" ]] || [[ $ARCH = "arm64e" ]]; then - IOS_PLATFORM=OS64 - DEPLOYMENT_TARGET=$MIN_IOS - WSIZE=64 - OPTIMIZATIONFLAGS=-fomit-frame-pointer - else - IOS_PLATFORM=OS - WSIZE=32 - fi - elif [[ $PLATFORM = $IPHONESIMULATOR ]]; then - if [[ $ARCH = "x86_64" ]]; then - IOS_PLATFORM=SIMULATOR64 - DEPLOYMENT_TARGET=$MIN_IOS - WSIZE=64 - OPTIMIZATIONFLAGS=-fomit-frame-pointer - elif [[ $ARCH = "arm64" ]]; then - IOS_PLATFORM=SIMULATORARM64 - DEPLOYMENT_TARGET=$MIN_IOS - WSIZE=64 - else - IOS_PLATFORM=SIMULATOR - WSIZE=32 - fi - elif [[ $PLATFORM = $WATCHOS ]]; then - IOS_PLATFORM=WATCHOS - DEPLOYMENT_TARGET=$MIN_WATCHOS - WSIZE=32 - elif [[ $PLATFORM = $WATCHSIMULATOR ]]; then - IOS_PLATFORM=SIMULATOR_WATCHOS - DEPLOYMENT_TARGET=$MIN_WATCHOS - WSIZE=32 - elif [[ $PLATFORM = $TVOS ]]; then - IOS_PLATFORM=TVOS - DEPLOYMENT_TARGET=$MIN_TVOS - WSIZE=64 - OPTIMIZATIONFLAGS=-fomit-frame-pointer - elif [[ $PLATFORM = $TVSIMULATOR ]]; then - IOS_PLATFORM=SIMULATOR_TVOS - #TODO - if [[ $ARCH = "arm64" ]] - then - IOS_PLATFORM=OS64 - fi - DEPLOYMENT_TARGET=$MIN_TVOS - WSIZE=64 - OPTIMIZATIONFLAGS=-fomit-frame-pointer - elif [[ $PLATFORM = $MACOS ]]; then - WSIZE=64 - IOS_PLATFORM=MAC - if [[ $ARCH = "arm64" ]] - then - IOS_PLATFORM=MAC_ARM64 - fi - DEPLOYMENT_TARGET=$MIN_MACOS - OPTIMIZATIONFLAGS=-fomit-frame-pointer + if [[ $PLATFORM = "$IPHONEOS" ]]; then + echo "OS64" + elif [[ $PLATFORM = "$IPHONESIMULATOR" && $ARCH = "x86_64" ]]; then + echo "SIMULATOR64" + elif [[ $PLATFORM = "$IPHONESIMULATOR" && $ARCH = "arm64" ]]; then + echo "SIMULATORARM64" + elif [[ $PLATFORM = "$MACOS" && $ARCH = "x86_64" ]]; then + echo "MAC" + elif [[ $PLATFORM = "$MACOS" && $ARCH = "arm64" ]]; then + echo "MAC_ARM64" fi - - COMPILER_ARGS="$(version_min_flag "$PLATFORM") -Wno-unused-functions" - - EXTRA_ARGS="-DOPSYS=NONE -DPLATFORM=$IOS_PLATFORM -DDEPLOYMENT_TARGET=$DEPLOYMENT_TARGET -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN" - - # shellcheck disable=SC2039 - if [[ $ARCH = "i386" ]]; then - EXTRA_ARGS+=" -DARCH=X86" - elif [[ $ARCH = "x86_64" ]]; then - EXTRA_ARGS+=" -DARCH=X64" - elif [[ $ARCH = "arm64" ]]; then - # Relic doesn't support aarch64 yet, "ARCH=ARM" is for ARM 32-bit architecture only - EXTRA_ARGS+=" -DIOS_ARCH=arm64 -DARCH=" - elif [[ $ARCH = "armv7s" ]]; then - EXTRA_ARGS+=" -DIOS_ARCH=armv7s -DARCH=ARM" - elif [[ $ARCH = "armv7k" ]]; then - EXTRA_ARGS+=" -DIOS_ARCH=armv7k -DARCH=ARM" - elif [[ $ARCH = "arm64_32" ]]; then - EXTRA_ARGS+=" -DIOS_ARCH=arm64_32 -DARCH=ARM" - fi - - CURRENT_DIR=$(pwd) - cmake -DCMAKE_PREFIX_PATH:PATH="${GMP_PFX}" -DTESTS=0 -DBENCH=0 -DBUILD_BLS_JS_BINDINGS=0 -DBUILD_BLS_PYTHON_BINDINGS=0 \ - -DBUILD_BLS_BENCHMARKS=0 -DBUILD_BLS_TESTS=0 -DCHECK=off -DARITH=gmp -DTIMER=HPROC -DFP_PRIME=381 -DMULTI=PTHREAD \ - -DFP_QNRES=on -DFP_METHD="INTEG;INTEG;INTEG;MONTY;EXGCD;SLIDE" -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" \ - -DCOMP_FLAGS="-pipe -std=c99 -O3 -funroll-loops $OPTIMIZATIONFLAGS -isysroot $SDK -arch $ARCH -fembed-bitcode ${COMPILER_ARGS}" \ - -DWSIZE=$WSIZE -DVERBS=off -DSHLIB=off -DALLOC="AUTO" -DEP_PLAIN=off -DEP_SUPER=off -DPP_EXT="LAZYR" \ - -DWITH="DV;BN;MD;FP;EP;FPX;EPX;PP;PC;CP" -DBN_METHD="COMBA;COMBA;MONTY;SLIDE;STEIN;BASIC" ${EXTRA_ARGS} ../../ - - make -j "$LOGICALCPU_MAX" - # shellcheck disable=SC2039,SC2164 - popd # "$BUILDDIR" - # shellcheck disable=SC2039,SC2164 - popd # depends/relic } build_bls_arch() { - # shellcheck disable=SC2039 - BLS_FILES=( "bls" "chaincode" "elements" "extendedprivatekey" "extendedpublickey" "legacy" "privatekey" "schemes" "threshold" ) - # shellcheck disable=SC2039 - ALL_BLS_OBJ_FILES=$(printf "%s.o " "${BLS_FILES[@]}") - PLATFORM=$1 ARCH=$2 PFX=${PLATFORM}-${ARCH} - SDK=$(xcrun --sdk "$PLATFORM" --show-sdk-path) - + CMAKE_PLATFORM=$(cmake_platform "$PLATFORM" "$ARCH") BUILDDIR=${BUILD}/bls-"${PFX}" - rm -rf "$BUILDDIR" - mkdir "$BUILDDIR" - # shellcheck disable=SC2039,SC2164 - pushd "$BUILDDIR" - - EXTRA_ARGS="$(version_min_flag "$PLATFORM")" - - CURRENT_DIR=$(pwd) - - # shellcheck disable=SC2039 - for F in "${BLS_FILES[@]}" - do - clang -I"../contrib/relic/include" \ - -I"../../depends/relic/include" \ - -I"../../include/dashbls" \ - -I"../relic-${PFX}/depends/relic/include" \ - -I"../../src/" \ - -I"../gmplib-${PFX}/include" \ - -x c++ -std=c++14 -stdlib=libc++ -fembed-bitcode -arch "${ARCH}" -isysroot "${SDK}" "${EXTRA_ARGS}" \ - -c "../../src/${F}.cpp" -o "${F}.o" - done - # shellcheck disable=SC2086 - xcrun -sdk "$PLATFORM" ar -cvq libbls.a $ALL_BLS_OBJ_FILES + rm -rf "$BUILDDIR" - # shellcheck disable=SC2039,SC2164 - popd # "$BUILDDIR" -} - -build_all_arch() { - PLATFORM=$1 - ARCH=$2 - build_gmp_arch "$PLATFORM" "$ARCH" - build_relic_arch "$PLATFORM" "$ARCH" - build_bls_arch "$PLATFORM" "$ARCH" + cmake -S . -B "$BUILDDIR" \ + -DCMAKE_TOOLCHAIN_FILE="$(pwd)/${BUILD}/ios.toolchain.cmake" \ + -DPLATFORM="${CMAKE_PLATFORM}" \ + -DDEPLOYMENT_TARGET=13.0 \ + -DENABLE_BITCODE=OFF \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_BLS_TESTS=0 \ + -DBUILD_BLS_BENCHMARKS=0 \ + -DBUILD_BLS_JS_BINDINGS=0 \ + -DBUILD_BLS_PYTHON_BINDINGS=0 + + cmake --build "$BUILDDIR" --parallel "$LOGICALCPU_MAX" --target dashbls } build_target() { @@ -356,19 +106,14 @@ build_target() { ARCH=arm64 PLATFORM=$MACOS fi - build_all_arch "$PLATFORM" "$ARCH" + build_bls_arch "$PLATFORM" "$ARCH" PFX="${PLATFORM}"-"${ARCH}" rm -rf "build/artefacts/${BUILD_IN}" mkdir -p "build/artefacts/${BUILD_IN}" - cp "build/gmplib-${PFX}/lib/libgmp.a" "build/artefacts/${BUILD_IN}" - cp "build/relic-${PFX}/depends/relic/lib/librelic_s.a" "build/artefacts/${BUILD_IN}" -# cp "build/relic-${PFX}/depends/sodium/libsodium.a" "build/artefacts/${BUILD_IN}" - cp "build/bls-${PFX}/libbls.a" "build/artefacts/${BUILD_IN}" -# cp -rf build/bls-"${PFX}"/*.o build/artefacts/"${BUILD_IN}"/include -# cp -rf src/*.hpp build/artefacts/"${BUILD_IN}"/include -# cp -rf build/gmplib-"${PFX}"/include/gmp.h build/artefacts/"${BUILD_IN}"/include -# cp -rf build/relic-"${PFX}"/_deps/relic-build/include/*.h build/artefacts/"${BUILD_IN}"/include + cp "build/bls-${PFX}/src/libdashbls.a" "build/artefacts/${BUILD_IN}" + cp "build/bls-${PFX}/depends/mimalloc/libmimalloc-secure.a" "build/artefacts/${BUILD_IN}" } +mkdir -p ${BUILD} prepare build_target "$TARGET" diff --git a/autogen.sh b/autogen.sh deleted file mode 100755 index f3e943e167db..000000000000 --- a/autogen.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -export LC_ALL=C -set -e -srcdir="$(dirname "$0")" -cd "$srcdir" -if [ -z "${LIBTOOLIZE}" ] && GLIBTOOLIZE="$(command -v glibtoolize)"; then - LIBTOOLIZE="${GLIBTOOLIZE}" - export LIBTOOLIZE -fi -command -v autoreconf >/dev/null || \ - (echo "configuration failed, please install autoconf first" && exit 1) -autoreconf --install --force --warnings=all -autoheader --force --replace-handwritten || autoheader --force diff --git a/binds/python/CMakeLists.txt b/binds/python/CMakeLists.txt index 98a776e4b19e..9117ade8f3cf 100644 --- a/binds/python/CMakeLists.txt +++ b/binds/python/CMakeLists.txt @@ -6,7 +6,7 @@ if(NOT pybind11_FOUND) FetchContent_Declare( pybind11 GIT_REPOSITORY https://github.com/pybind/pybind11.git - GIT_TAG v2.13.6 + GIT_TAG v2.13.6 ) FetchContent_MakeAvailable(pybind11) endif() diff --git a/binds/python/pythonbindings.cpp b/binds/python/pythonbindings.cpp index b037a74d6aa6..0723e2b1bb2f 100644 --- a/binds/python/pythonbindings.cpp +++ b/binds/python/pythonbindings.cpp @@ -657,7 +657,6 @@ PYBIND11_MODULE(dashbls, m) return other * self; }, py::is_operator()) - .def( "__repr__", [](const G2Element &ele) { diff --git a/build-aux/m4/ax_check_compile_flag.m4 b/build-aux/m4/ax_check_compile_flag.m4 deleted file mode 100644 index bd753b34d7dc..000000000000 --- a/build-aux/m4/ax_check_compile_flag.m4 +++ /dev/null @@ -1,53 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) -# -# DESCRIPTION -# -# Check whether the given FLAG works with the current language's compiler -# or gives an error. (Warnings, however, are ignored) -# -# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on -# success/failure. -# -# If EXTRA-FLAGS is defined, it is added to the current language's default -# flags (e.g. CFLAGS) when the check is done. The check is thus made with -# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to -# force the compiler to issue an error when a bad flag is given. -# -# INPUT gives an alternative input source to AC_COMPILE_IFELSE. -# -# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this -# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. -# -# LICENSE -# -# Copyright (c) 2008 Guido U. Draheim -# Copyright (c) 2011 Maarten Bosmans -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 6 - -AC_DEFUN([AX_CHECK_COMPILE_FLAG], -[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF -AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl -AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ - ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS - _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" - AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], - [AS_VAR_SET(CACHEVAR,[yes])], - [AS_VAR_SET(CACHEVAR,[no])]) - _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) -AS_VAR_IF(CACHEVAR,yes, - [m4_default([$2], :)], - [m4_default([$3], :)]) -AS_VAR_POPDEF([CACHEVAR])dnl -])dnl AX_CHECK_COMPILE_FLAGS diff --git a/build-aux/m4/ax_check_link_flag.m4 b/build-aux/m4/ax_check_link_flag.m4 deleted file mode 100644 index 03a30ce4c739..000000000000 --- a/build-aux/m4/ax_check_link_flag.m4 +++ /dev/null @@ -1,53 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) -# -# DESCRIPTION -# -# Check whether the given FLAG works with the linker or gives an error. -# (Warnings, however, are ignored) -# -# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on -# success/failure. -# -# If EXTRA-FLAGS is defined, it is added to the linker's default flags -# when the check is done. The check is thus made with the flags: "LDFLAGS -# EXTRA-FLAGS FLAG". This can for example be used to force the linker to -# issue an error when a bad flag is given. -# -# INPUT gives an alternative input source to AC_LINK_IFELSE. -# -# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this -# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. -# -# LICENSE -# -# Copyright (c) 2008 Guido U. Draheim -# Copyright (c) 2011 Maarten Bosmans -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 6 - -AC_DEFUN([AX_CHECK_LINK_FLAG], -[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF -AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl -AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ - ax_check_save_flags=$LDFLAGS - LDFLAGS="$LDFLAGS $4 $1" - AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], - [AS_VAR_SET(CACHEVAR,[yes])], - [AS_VAR_SET(CACHEVAR,[no])]) - LDFLAGS=$ax_check_save_flags]) -AS_VAR_IF(CACHEVAR,yes, - [m4_default([$2], :)], - [m4_default([$3], :)]) -AS_VAR_POPDEF([CACHEVAR])dnl -])dnl AX_CHECK_LINK_FLAGS diff --git a/build-aux/m4/ax_cxx_compile_stdcxx.m4 b/build-aux/m4/ax_cxx_compile_stdcxx.m4 deleted file mode 100644 index 51a35054d08c..000000000000 --- a/build-aux/m4/ax_cxx_compile_stdcxx.m4 +++ /dev/null @@ -1,1005 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) -# -# DESCRIPTION -# -# Check for baseline language coverage in the compiler for the specified -# version of the C++ standard. If necessary, add switches to CXX and -# CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for -# the respective C++ standard version. -# -# The second argument, if specified, indicates whether you insist on an -# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. -# -std=c++11). If neither is specified, you get whatever works, with -# preference for no added switch, and then for an extended mode. -# -# The third argument, if specified 'mandatory' or if left unspecified, -# indicates that baseline support for the specified C++ standard is -# required and that the macro should error out if no mode with that -# support is found. If specified 'optional', then configuration proceeds -# regardless, after defining HAVE_CXX${VERSION} if and only if a -# supporting mode is found. -# -# LICENSE -# -# Copyright (c) 2008 Benjamin Kosnik -# Copyright (c) 2012 Zack Weinberg -# Copyright (c) 2013 Roy Stogner -# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov -# Copyright (c) 2015 Paul Norman -# Copyright (c) 2015 Moritz Klammler -# Copyright (c) 2016, 2018 Krzesimir Nowak -# Copyright (c) 2019 Enji Cooper -# Copyright (c) 2020 Jason Merrill -# Copyright (c) 2021 Jörn Heusipp -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 14 - -dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro -dnl (serial version number 13). - -AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl - m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], - [$1], [14], [ax_cxx_compile_alternatives="14 1y"], - [$1], [17], [ax_cxx_compile_alternatives="17 1z"], - [$1], [20], [ax_cxx_compile_alternatives="20"], - [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl - m4_if([$2], [], [], - [$2], [ext], [], - [$2], [noext], [], - [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl - m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], - [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], - [$3], [optional], [ax_cxx_compile_cxx$1_required=false], - [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) - AC_LANG_PUSH([C++])dnl - ac_success=no - - m4_if([$2], [], [dnl - AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, - ax_cv_cxx_compile_cxx$1, - [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], - [ax_cv_cxx_compile_cxx$1=yes], - [ax_cv_cxx_compile_cxx$1=no])]) - if test x$ax_cv_cxx_compile_cxx$1 = xyes; then - ac_success=yes - fi]) - - m4_if([$2], [noext], [], [dnl - if test x$ac_success = xno; then - for alternative in ${ax_cxx_compile_alternatives}; do - switch="-std=gnu++${alternative}" - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, - $cachevar, - [ac_save_CXX="$CXX" - CXX="$CXX $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXX="$ac_save_CXX"]) - if eval test x\$$cachevar = xyes; then - CXX="$CXX $switch" - if test -n "$CXXCPP" ; then - CXXCPP="$CXXCPP $switch" - fi - ac_success=yes - break - fi - done - fi]) - - m4_if([$2], [ext], [], [dnl - if test x$ac_success = xno; then - dnl HP's aCC needs +std=c++11 according to: - dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf - dnl Cray's crayCC needs "-h std=c++11" - for alternative in ${ax_cxx_compile_alternatives}; do - for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, - $cachevar, - [ac_save_CXX="$CXX" - CXX="$CXX $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXX="$ac_save_CXX"]) - if eval test x\$$cachevar = xyes; then - CXX="$CXX $switch" - if test -n "$CXXCPP" ; then - CXXCPP="$CXXCPP $switch" - fi - ac_success=yes - break - fi - done - if test x$ac_success = xyes; then - break - fi - done - fi]) - AC_LANG_POP([C++]) - if test x$ax_cxx_compile_cxx$1_required = xtrue; then - if test x$ac_success = xno; then - AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) - fi - fi - if test x$ac_success = xno; then - HAVE_CXX$1=0 - AC_MSG_NOTICE([No compiler with C++$1 support was found]) - else - HAVE_CXX$1=1 - AC_DEFINE(HAVE_CXX$1,1, - [define if the compiler supports basic C++$1 syntax]) - fi - AC_SUBST(HAVE_CXX$1) -]) - - -dnl Test body for checking C++11 support - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 -) - -dnl Test body for checking C++14 support - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 -) - -dnl Test body for checking C++17 support - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 -) - -dnl Test body for checking C++20 support - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], - _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 - _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 -) - - -dnl Tests for new features in C++11 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ - -// If the compiler admits that it is not ready for C++11, why torture it? -// Hopefully, this will speed up the test. - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 201103L - -#error "This is not a C++11 compiler" - -#else - -namespace cxx11 -{ - - namespace test_static_assert - { - - template - struct check - { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); - }; - - } - - namespace test_final_override - { - - struct Base - { - virtual ~Base() {} - virtual void f() {} - }; - - struct Derived : public Base - { - virtual ~Derived() override {} - virtual void f() override {} - }; - - } - - namespace test_double_right_angle_brackets - { - - template < typename T > - struct check {}; - - typedef check single_type; - typedef check> double_type; - typedef check>> triple_type; - typedef check>>> quadruple_type; - - } - - namespace test_decltype - { - - int - f() - { - int a = 1; - decltype(a) b = 2; - return a + b; - } - - } - - namespace test_type_deduction - { - - template < typename T1, typename T2 > - struct is_same - { - static const bool value = false; - }; - - template < typename T > - struct is_same - { - static const bool value = true; - }; - - template < typename T1, typename T2 > - auto - add(T1 a1, T2 a2) -> decltype(a1 + a2) - { - return a1 + a2; - } - - int - test(const int c, volatile int v) - { - static_assert(is_same::value == true, ""); - static_assert(is_same::value == false, ""); - static_assert(is_same::value == false, ""); - auto ac = c; - auto av = v; - auto sumi = ac + av + 'x'; - auto sumf = ac + av + 1.0; - static_assert(is_same::value == true, ""); - static_assert(is_same::value == true, ""); - static_assert(is_same::value == true, ""); - static_assert(is_same::value == false, ""); - static_assert(is_same::value == true, ""); - return (sumf > 0.0) ? sumi : add(c, v); - } - - } - - namespace test_noexcept - { - - int f() { return 0; } - int g() noexcept { return 0; } - - static_assert(noexcept(f()) == false, ""); - static_assert(noexcept(g()) == true, ""); - - } - - namespace test_constexpr - { - - template < typename CharT > - unsigned long constexpr - strlen_c_r(const CharT *const s, const unsigned long acc) noexcept - { - return *s ? strlen_c_r(s + 1, acc + 1) : acc; - } - - template < typename CharT > - unsigned long constexpr - strlen_c(const CharT *const s) noexcept - { - return strlen_c_r(s, 0UL); - } - - static_assert(strlen_c("") == 0UL, ""); - static_assert(strlen_c("1") == 1UL, ""); - static_assert(strlen_c("example") == 7UL, ""); - static_assert(strlen_c("another\0example") == 7UL, ""); - - } - - namespace test_rvalue_references - { - - template < int N > - struct answer - { - static constexpr int value = N; - }; - - answer<1> f(int&) { return answer<1>(); } - answer<2> f(const int&) { return answer<2>(); } - answer<3> f(int&&) { return answer<3>(); } - - void - test() - { - int i = 0; - const int c = 0; - static_assert(decltype(f(i))::value == 1, ""); - static_assert(decltype(f(c))::value == 2, ""); - static_assert(decltype(f(0))::value == 3, ""); - } - - } - - namespace test_uniform_initialization - { - - struct test - { - static const int zero {}; - static const int one {1}; - }; - - static_assert(test::zero == 0, ""); - static_assert(test::one == 1, ""); - - } - - namespace test_lambdas - { - - void - test1() - { - auto lambda1 = [](){}; - auto lambda2 = lambda1; - lambda1(); - lambda2(); - } - - int - test2() - { - auto a = [](int i, int j){ return i + j; }(1, 2); - auto b = []() -> int { return '0'; }(); - auto c = [=](){ return a + b; }(); - auto d = [&](){ return c; }(); - auto e = [a, &b](int x) mutable { - const auto identity = [](int y){ return y; }; - for (auto i = 0; i < a; ++i) - a += b--; - return x + identity(a + b); - }(0); - return a + b + c + d + e; - } - - int - test3() - { - const auto nullary = [](){ return 0; }; - const auto unary = [](int x){ return x; }; - using nullary_t = decltype(nullary); - using unary_t = decltype(unary); - const auto higher1st = [](nullary_t f){ return f(); }; - const auto higher2nd = [unary](nullary_t f1){ - return [unary, f1](unary_t f2){ return f2(unary(f1())); }; - }; - return higher1st(nullary) + higher2nd(nullary)(unary); - } - - } - - namespace test_variadic_templates - { - - template - struct sum; - - template - struct sum - { - static constexpr auto value = N0 + sum::value; - }; - - template <> - struct sum<> - { - static constexpr auto value = 0; - }; - - static_assert(sum<>::value == 0, ""); - static_assert(sum<1>::value == 1, ""); - static_assert(sum<23>::value == 23, ""); - static_assert(sum<1, 2>::value == 3, ""); - static_assert(sum<5, 5, 11>::value == 21, ""); - static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); - - } - - // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae - // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function - // because of this. - namespace test_template_alias_sfinae - { - - struct foo {}; - - template - using member = typename T::member_type; - - template - void func(...) {} - - template - void func(member*) {} - - void test(); - - void test() { func(0); } - - } - -} // namespace cxx11 - -#endif // __cplusplus >= 201103L - -]]) - - -dnl Tests for new features in C++14 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ - -// If the compiler admits that it is not ready for C++14, why torture it? -// Hopefully, this will speed up the test. - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 201402L - -#error "This is not a C++14 compiler" - -#else - -namespace cxx14 -{ - - namespace test_polymorphic_lambdas - { - - int - test() - { - const auto lambda = [](auto&&... args){ - const auto istiny = [](auto x){ - return (sizeof(x) == 1UL) ? 1 : 0; - }; - const int aretiny[] = { istiny(args)... }; - return aretiny[0]; - }; - return lambda(1, 1L, 1.0f, '1'); - } - - } - - namespace test_binary_literals - { - - constexpr auto ivii = 0b0000000000101010; - static_assert(ivii == 42, "wrong value"); - - } - - namespace test_generalized_constexpr - { - - template < typename CharT > - constexpr unsigned long - strlen_c(const CharT *const s) noexcept - { - auto length = 0UL; - for (auto p = s; *p; ++p) - ++length; - return length; - } - - static_assert(strlen_c("") == 0UL, ""); - static_assert(strlen_c("x") == 1UL, ""); - static_assert(strlen_c("test") == 4UL, ""); - static_assert(strlen_c("another\0test") == 7UL, ""); - - } - - namespace test_lambda_init_capture - { - - int - test() - { - auto x = 0; - const auto lambda1 = [a = x](int b){ return a + b; }; - const auto lambda2 = [a = lambda1(x)](){ return a; }; - return lambda2(); - } - - } - - namespace test_digit_separators - { - - constexpr auto ten_million = 100'000'000; - static_assert(ten_million == 100000000, ""); - - } - - namespace test_return_type_deduction - { - - auto f(int& x) { return x; } - decltype(auto) g(int& x) { return x; } - - template < typename T1, typename T2 > - struct is_same - { - static constexpr auto value = false; - }; - - template < typename T > - struct is_same - { - static constexpr auto value = true; - }; - - int - test() - { - auto x = 0; - static_assert(is_same::value, ""); - static_assert(is_same::value, ""); - return x; - } - - } - -} // namespace cxx14 - -#endif // __cplusplus >= 201402L - -]]) - - -dnl Tests for new features in C++17 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ - -// If the compiler admits that it is not ready for C++17, why torture it? -// Hopefully, this will speed up the test. - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 201703L - -#error "This is not a C++17 compiler" - -#else - -#include -#include -#include - -namespace cxx17 -{ - - namespace test_constexpr_lambdas - { - - constexpr int foo = [](){return 42;}(); - - } - - namespace test::nested_namespace::definitions - { - - } - - namespace test_fold_expression - { - - template - int multiply(Args... args) - { - return (args * ... * 1); - } - - template - bool all(Args... args) - { - return (args && ...); - } - - } - - namespace test_extended_static_assert - { - - static_assert (true); - - } - - namespace test_auto_brace_init_list - { - - auto foo = {5}; - auto bar {5}; - - static_assert(std::is_same, decltype(foo)>::value); - static_assert(std::is_same::value); - } - - namespace test_typename_in_template_template_parameter - { - - template typename X> struct D; - - } - - namespace test_fallthrough_nodiscard_maybe_unused_attributes - { - - int f1() - { - return 42; - } - - [[nodiscard]] int f2() - { - [[maybe_unused]] auto unused = f1(); - - switch (f1()) - { - case 17: - f1(); - [[fallthrough]]; - case 42: - f1(); - } - return f1(); - } - - } - - namespace test_extended_aggregate_initialization - { - - struct base1 - { - int b1, b2 = 42; - }; - - struct base2 - { - base2() { - b3 = 42; - } - int b3; - }; - - struct derived : base1, base2 - { - int d; - }; - - derived d1 {{1, 2}, {}, 4}; // full initialization - derived d2 {{}, {}, 4}; // value-initialized bases - - } - - namespace test_general_range_based_for_loop - { - - struct iter - { - int i; - - int& operator* () - { - return i; - } - - const int& operator* () const - { - return i; - } - - iter& operator++() - { - ++i; - return *this; - } - }; - - struct sentinel - { - int i; - }; - - bool operator== (const iter& i, const sentinel& s) - { - return i.i == s.i; - } - - bool operator!= (const iter& i, const sentinel& s) - { - return !(i == s); - } - - struct range - { - iter begin() const - { - return {0}; - } - - sentinel end() const - { - return {5}; - } - }; - - void f() - { - range r {}; - - for (auto i : r) - { - [[maybe_unused]] auto v = i; - } - } - - } - - namespace test_lambda_capture_asterisk_this_by_value - { - - struct t - { - int i; - int foo() - { - return [*this]() - { - return i; - }(); - } - }; - - } - - namespace test_enum_class_construction - { - - enum class byte : unsigned char - {}; - - byte foo {42}; - - } - - namespace test_constexpr_if - { - - template - int f () - { - if constexpr(cond) - { - return 13; - } - else - { - return 42; - } - } - - } - - namespace test_selection_statement_with_initializer - { - - int f() - { - return 13; - } - - int f2() - { - if (auto i = f(); i > 0) - { - return 3; - } - - switch (auto i = f(); i + 4) - { - case 17: - return 2; - - default: - return 1; - } - } - - } - - namespace test_template_argument_deduction_for_class_templates - { - - template - struct pair - { - pair (T1 p1, T2 p2) - : m1 {p1}, - m2 {p2} - {} - - T1 m1; - T2 m2; - }; - - void f() - { - [[maybe_unused]] auto p = pair{13, 42u}; - } - - } - - namespace test_non_type_auto_template_parameters - { - - template - struct B - {}; - - B<5> b1; - B<'a'> b2; - - } - - namespace test_structured_bindings - { - - int arr[2] = { 1, 2 }; - std::pair pr = { 1, 2 }; - - auto f1() -> int(&)[2] - { - return arr; - } - - auto f2() -> std::pair& - { - return pr; - } - - struct S - { - int x1 : 2; - volatile double y1; - }; - - S f3() - { - return {}; - } - - auto [ x1, y1 ] = f1(); - auto& [ xr1, yr1 ] = f1(); - auto [ x2, y2 ] = f2(); - auto& [ xr2, yr2 ] = f2(); - const auto [ x3, y3 ] = f3(); - - } - - namespace test_exception_spec_type_system - { - - struct Good {}; - struct Bad {}; - - void g1() noexcept; - void g2(); - - template - Bad - f(T*, T*); - - template - Good - f(T1*, T2*); - - static_assert (std::is_same_v); - - } - - namespace test_inline_variables - { - - template void f(T) - {} - - template inline T g(T) - { - return T{}; - } - - template<> inline void f<>(int) - {} - - template<> int g<>(int) - { - return 5; - } - - } - -} // namespace cxx17 - -#endif // __cplusplus < 201703L - -]]) - - -dnl Tests for new features in C++20 - -m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ - -#ifndef __cplusplus - -#error "This is not a C++ compiler" - -#elif __cplusplus < 202002L - -#error "This is not a C++20 compiler" - -#else - -#include - -namespace cxx20 -{ - -// As C++20 supports feature test macros in the standard, there is no -// immediate need to actually test for feature availability on the -// Autoconf side. - -} // namespace cxx20 - -#endif // __cplusplus < 202002L - -]]) diff --git a/build-aux/m4/ax_pthread.m4 b/build-aux/m4/ax_pthread.m4 deleted file mode 100644 index 9f35d139149f..000000000000 --- a/build-aux/m4/ax_pthread.m4 +++ /dev/null @@ -1,522 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_pthread.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) -# -# DESCRIPTION -# -# This macro figures out how to build C programs using POSIX threads. It -# sets the PTHREAD_LIBS output variable to the threads library and linker -# flags, and the PTHREAD_CFLAGS output variable to any special C compiler -# flags that are needed. (The user can also force certain compiler -# flags/libs to be tested by setting these environment variables.) -# -# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is -# needed for multi-threaded programs (defaults to the value of CC -# respectively CXX otherwise). (This is necessary on e.g. AIX to use the -# special cc_r/CC_r compiler alias.) -# -# NOTE: You are assumed to not only compile your program with these flags, -# but also to link with them as well. For example, you might link with -# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS -# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS -# -# If you are only building threaded programs, you may wish to use these -# variables in your default LIBS, CFLAGS, and CC: -# -# LIBS="$PTHREAD_LIBS $LIBS" -# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" -# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" -# CC="$PTHREAD_CC" -# CXX="$PTHREAD_CXX" -# -# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant -# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to -# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). -# -# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the -# PTHREAD_PRIO_INHERIT symbol is defined when compiling with -# PTHREAD_CFLAGS. -# -# ACTION-IF-FOUND is a list of shell commands to run if a threads library -# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it -# is not found. If ACTION-IF-FOUND is not specified, the default action -# will define HAVE_PTHREAD. -# -# Please let the authors know if this macro fails on any platform, or if -# you have any other suggestions or comments. This macro was based on work -# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help -# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by -# Alejandro Forero Cuervo to the autoconf macro repository. We are also -# grateful for the helpful feedback of numerous users. -# -# Updated for Autoconf 2.68 by Daniel Richard G. -# -# LICENSE -# -# Copyright (c) 2008 Steven G. Johnson -# Copyright (c) 2011 Daniel Richard G. -# Copyright (c) 2019 Marc Stevens -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 31 - -AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) -AC_DEFUN([AX_PTHREAD], [ -AC_REQUIRE([AC_CANONICAL_HOST]) -AC_REQUIRE([AC_PROG_CC]) -AC_REQUIRE([AC_PROG_SED]) -AC_LANG_PUSH([C]) -ax_pthread_ok=no - -# We used to check for pthread.h first, but this fails if pthread.h -# requires special compiler flags (e.g. on Tru64 or Sequent). -# It gets checked for in the link test anyway. - -# First of all, check if the user has set any of the PTHREAD_LIBS, -# etcetera environment variables, and if threads linking works using -# them: -if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then - ax_pthread_save_CC="$CC" - ax_pthread_save_CFLAGS="$CFLAGS" - ax_pthread_save_LIBS="$LIBS" - AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) - AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"]) - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) - AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) - AC_MSG_RESULT([$ax_pthread_ok]) - if test "x$ax_pthread_ok" = "xno"; then - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" - fi - CC="$ax_pthread_save_CC" - CFLAGS="$ax_pthread_save_CFLAGS" - LIBS="$ax_pthread_save_LIBS" -fi - -# We must check for the threads library under a number of different -# names; the ordering is very important because some systems -# (e.g. DEC) have both -lpthread and -lpthreads, where one of the -# libraries is broken (non-POSIX). - -# Create a list of thread flags to try. Items with a "," contain both -# C compiler flags (before ",") and linker flags (after ","). Other items -# starting with a "-" are C compiler flags, and remaining items are -# library names, except for "none" which indicates that we try without -# any flags at all, and "pthread-config" which is a program returning -# the flags for the Pth emulation library. - -ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" - -# The ordering *is* (sometimes) important. Some notes on the -# individual items follow: - -# pthreads: AIX (must check this before -lpthread) -# none: in case threads are in libc; should be tried before -Kthread and -# other compiler flags to prevent continual compiler warnings -# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 -# (Note: HP C rejects this with "bad form for `-t' option") -# -pthreads: Solaris/gcc (Note: HP C also rejects) -# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads and -# -D_REENTRANT too), HP C (must be checked before -lpthread, which -# is present but should not be used directly; and before -mthreads, -# because the compiler interprets this as "-mt" + "-hreads") -# -mthreads: Mingw32/gcc, Lynx/gcc -# pthread: Linux, etcetera -# --thread-safe: KAI C++ -# pthread-config: use pthread-config program (for GNU Pth library) - -case $host_os in - - freebsd*) - - # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) - # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) - - ax_pthread_flags="-kthread lthread $ax_pthread_flags" - ;; - - hpux*) - - # From the cc(1) man page: "[-mt] Sets various -D flags to enable - # multi-threading and also sets -lpthread." - - ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" - ;; - - openedition*) - - # IBM z/OS requires a feature-test macro to be defined in order to - # enable POSIX threads at all, so give the user a hint if this is - # not set. (We don't define these ourselves, as they can affect - # other portions of the system API in unpredictable ways.) - - AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], - [ -# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) - AX_PTHREAD_ZOS_MISSING -# endif - ], - [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) - ;; - - solaris*) - - # On Solaris (at least, for some versions), libc contains stubbed - # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (N.B.: The stubs are missing - # pthread_cleanup_push, or rather a function called by this macro, - # so we could check for that, but who knows whether they'll stub - # that too in a future libc.) So we'll check first for the - # standard Solaris way of linking pthreads (-mt -lpthread). - - ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags" - ;; -esac - -# Are we compiling with Clang? - -AC_CACHE_CHECK([whether $CC is Clang], - [ax_cv_PTHREAD_CLANG], - [ax_cv_PTHREAD_CLANG=no - # Note that Autoconf sets GCC=yes for Clang as well as GCC - if test "x$GCC" = "xyes"; then - AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], - [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ -# if defined(__clang__) && defined(__llvm__) - AX_PTHREAD_CC_IS_CLANG -# endif - ], - [ax_cv_PTHREAD_CLANG=yes]) - fi - ]) -ax_pthread_clang="$ax_cv_PTHREAD_CLANG" - - -# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) - -# Note that for GCC and Clang -pthread generally implies -lpthread, -# except when -nostdlib is passed. -# This is problematic using libtool to build C++ shared libraries with pthread: -# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460 -# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333 -# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555 -# To solve this, first try -pthread together with -lpthread for GCC - -AS_IF([test "x$GCC" = "xyes"], - [ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"]) - -# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first - -AS_IF([test "x$ax_pthread_clang" = "xyes"], - [ax_pthread_flags="-pthread,-lpthread -pthread"]) - - -# The presence of a feature test macro requesting re-entrant function -# definitions is, on some systems, a strong hint that pthreads support is -# correctly enabled - -case $host_os in - darwin* | hpux* | linux* | osf* | solaris*) - ax_pthread_check_macro="_REENTRANT" - ;; - - aix*) - ax_pthread_check_macro="_THREAD_SAFE" - ;; - - *) - ax_pthread_check_macro="--" - ;; -esac -AS_IF([test "x$ax_pthread_check_macro" = "x--"], - [ax_pthread_check_cond=0], - [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) - - -if test "x$ax_pthread_ok" = "xno"; then -for ax_pthread_try_flag in $ax_pthread_flags; do - - case $ax_pthread_try_flag in - none) - AC_MSG_CHECKING([whether pthreads work without any flags]) - ;; - - *,*) - PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"` - PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"` - AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"]) - ;; - - -*) - AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) - PTHREAD_CFLAGS="$ax_pthread_try_flag" - ;; - - pthread-config) - AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) - AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) - PTHREAD_CFLAGS="`pthread-config --cflags`" - PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" - ;; - - *) - AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) - PTHREAD_LIBS="-l$ax_pthread_try_flag" - ;; - esac - - ax_pthread_save_CFLAGS="$CFLAGS" - ax_pthread_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - - # Check for various functions. We must include pthread.h, - # since some functions may be macros. (On the Sequent, we - # need a special flag -Kthread to make this header compile.) - # We check for pthread_join because it is in -lpthread on IRIX - # while pthread_create is in libc. We check for pthread_attr_init - # due to DEC craziness with -lpthreads. We check for - # pthread_cleanup_push because it is one of the few pthread - # functions on Solaris that doesn't have a non-functional libc stub. - # We try pthread_create on general principles. - - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include -# if $ax_pthread_check_cond -# error "$ax_pthread_check_macro must be defined" -# endif - static void *some_global = NULL; - static void routine(void *a) - { - /* To avoid any unused-parameter or - unused-but-set-parameter warning. */ - some_global = a; - } - static void *start_routine(void *a) { return a; }], - [pthread_t th; pthread_attr_t attr; - pthread_create(&th, 0, start_routine, 0); - pthread_join(th, 0); - pthread_attr_init(&attr); - pthread_cleanup_push(routine, 0); - pthread_cleanup_pop(0) /* ; */])], - [ax_pthread_ok=yes], - []) - - CFLAGS="$ax_pthread_save_CFLAGS" - LIBS="$ax_pthread_save_LIBS" - - AC_MSG_RESULT([$ax_pthread_ok]) - AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) - - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" -done -fi - - -# Clang needs special handling, because older versions handle the -pthread -# option in a rather... idiosyncratic way - -if test "x$ax_pthread_clang" = "xyes"; then - - # Clang takes -pthread; it has never supported any other flag - - # (Note 1: This will need to be revisited if a system that Clang - # supports has POSIX threads in a separate library. This tends not - # to be the way of modern systems, but it's conceivable.) - - # (Note 2: On some systems, notably Darwin, -pthread is not needed - # to get POSIX threads support; the API is always present and - # active. We could reasonably leave PTHREAD_CFLAGS empty. But - # -pthread does define _REENTRANT, and while the Darwin headers - # ignore this macro, third-party headers might not.) - - # However, older versions of Clang make a point of warning the user - # that, in an invocation where only linking and no compilation is - # taking place, the -pthread option has no effect ("argument unused - # during compilation"). They expect -pthread to be passed in only - # when source code is being compiled. - # - # Problem is, this is at odds with the way Automake and most other - # C build frameworks function, which is that the same flags used in - # compilation (CFLAGS) are also used in linking. Many systems - # supported by AX_PTHREAD require exactly this for POSIX threads - # support, and in fact it is often not straightforward to specify a - # flag that is used only in the compilation phase and not in - # linking. Such a scenario is extremely rare in practice. - # - # Even though use of the -pthread flag in linking would only print - # a warning, this can be a nuisance for well-run software projects - # that build with -Werror. So if the active version of Clang has - # this misfeature, we search for an option to squash it. - - AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], - [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], - [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown - # Create an alternate version of $ac_link that compiles and - # links in two steps (.c -> .o, .o -> exe) instead of one - # (.c -> exe), because the warning occurs only in the second - # step - ax_pthread_save_ac_link="$ac_link" - ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' - ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"` - ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" - ax_pthread_save_CFLAGS="$CFLAGS" - for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do - AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) - CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" - ac_link="$ax_pthread_save_ac_link" - AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], - [ac_link="$ax_pthread_2step_ac_link" - AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], - [break]) - ]) - done - ac_link="$ax_pthread_save_ac_link" - CFLAGS="$ax_pthread_save_CFLAGS" - AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) - ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" - ]) - - case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in - no | unknown) ;; - *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; - esac - -fi # $ax_pthread_clang = yes - - - -# Various other checks: -if test "x$ax_pthread_ok" = "xyes"; then - ax_pthread_save_CFLAGS="$CFLAGS" - ax_pthread_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - - # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. - AC_CACHE_CHECK([for joinable pthread attribute], - [ax_cv_PTHREAD_JOINABLE_ATTR], - [ax_cv_PTHREAD_JOINABLE_ATTR=unknown - for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], - [int attr = $ax_pthread_attr; return attr /* ; */])], - [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], - []) - done - ]) - AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ - test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ - test "x$ax_pthread_joinable_attr_defined" != "xyes"], - [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], - [$ax_cv_PTHREAD_JOINABLE_ATTR], - [Define to necessary symbol if this constant - uses a non-standard name on your system.]) - ax_pthread_joinable_attr_defined=yes - ]) - - AC_CACHE_CHECK([whether more special flags are required for pthreads], - [ax_cv_PTHREAD_SPECIAL_FLAGS], - [ax_cv_PTHREAD_SPECIAL_FLAGS=no - case $host_os in - solaris*) - ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" - ;; - esac - ]) - AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ - test "x$ax_pthread_special_flags_added" != "xyes"], - [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" - ax_pthread_special_flags_added=yes]) - - AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], - [ax_cv_PTHREAD_PRIO_INHERIT], - [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[int i = PTHREAD_PRIO_INHERIT; - return i;]])], - [ax_cv_PTHREAD_PRIO_INHERIT=yes], - [ax_cv_PTHREAD_PRIO_INHERIT=no]) - ]) - AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ - test "x$ax_pthread_prio_inherit_defined" != "xyes"], - [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) - ax_pthread_prio_inherit_defined=yes - ]) - - CFLAGS="$ax_pthread_save_CFLAGS" - LIBS="$ax_pthread_save_LIBS" - - # More AIX lossage: compile with *_r variant - if test "x$GCC" != "xyes"; then - case $host_os in - aix*) - AS_CASE(["x/$CC"], - [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], - [#handle absolute path differently from PATH based program lookup - AS_CASE(["x$CC"], - [x/*], - [ - AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"]) - AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])]) - ], - [ - AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC]) - AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])]) - ] - ) - ]) - ;; - esac - fi -fi - -test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" -test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX" - -AC_SUBST([PTHREAD_LIBS]) -AC_SUBST([PTHREAD_CFLAGS]) -AC_SUBST([PTHREAD_CC]) -AC_SUBST([PTHREAD_CXX]) - -# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test "x$ax_pthread_ok" = "xyes"; then - ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) - : -else - ax_pthread_ok=no - $2 -fi -AC_LANG_POP -])dnl AX_PTHREAD diff --git a/cmake_modules/Findgmp.cmake b/cmake_modules/Findgmp.cmake deleted file mode 100644 index 3e59ede0a4f3..000000000000 --- a/cmake_modules/Findgmp.cmake +++ /dev/null @@ -1,103 +0,0 @@ -# Try to find the GMP library -# https://gmplib.org/ -# -# This module supports requiring a minimum version, e.g. you can do -# find_package(GMP 6.0.0) -# to require version 6.0.0 to newer of GMP. -# -# Once done this will define -# -# GMP_FOUND - system has GMP lib with correct version -# GMP_INCLUDES - the GMP include directory -# GMP_LIBRARIES - the GMP library -# GMP_VERSION - GMP version -# -# Copyright (c) 2016 Jack Poulson, -# Redistribution and use is allowed according to the terms of the BSD license. - -include(BrewHelper) -find_brew_prefix(_GMP_BREW_HINT gmp) - -find_path(GMP_INCLUDES - NAMES - gmp.h - PATHS - $ENV{GMPDIR} ${INCLUDE_INSTALL_DIR} - PATH_SUFFIXES - include - HINTS - ${_GMP_BREW_HINT} -) - -# Set GMP_FIND_VERSION to 5.1.0 if no minimum version is specified -if(NOT GMP_FIND_VERSION) - if(NOT GMP_FIND_VERSION_MAJOR) - set(GMP_FIND_VERSION_MAJOR 5) - endif() - if(NOT GMP_FIND_VERSION_MINOR) - set(GMP_FIND_VERSION_MINOR 1) - endif() - if(NOT GMP_FIND_VERSION_PATCH) - set(GMP_FIND_VERSION_PATCH 0) - endif() - set(GMP_FIND_VERSION - "${GMP_FIND_VERSION_MAJOR}.${GMP_FIND_VERSION_MINOR}.${GMP_FIND_VERSION_PATCH}") -endif() - -message("GMP_INCLUDES=${GMP_INCLUDES}") -if(GMP_INCLUDES) - # Since the GMP version macros may be in a file included by gmp.h of the form - # gmp-.*[_]?.*.h (e.g., gmp-x86_64.h), we search each of them. - file(GLOB GMP_HEADERS "${GMP_INCLUDES}/gmp.h" "${GMP_INCLUDES}/gmp-*.h") - foreach(gmp_header_filename ${GMP_HEADERS}) - file(READ "${gmp_header_filename}" _gmp_version_header) - string(REGEX MATCH - "define[ \t]+__GNU_MP_VERSION[ \t]+([0-9]+)" _gmp_major_version_match - "${_gmp_version_header}") - if(_gmp_major_version_match) - set(GMP_MAJOR_VERSION "${CMAKE_MATCH_1}") - string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_MINOR[ \t]+([0-9]+)" - _gmp_minor_version_match "${_gmp_version_header}") - set(GMP_MINOR_VERSION "${CMAKE_MATCH_1}") - string(REGEX MATCH "define[ \t]+__GNU_MP_VERSION_PATCHLEVEL[ \t]+([0-9]+)" - _gmp_patchlevel_version_match "${_gmp_version_header}") - set(GMP_PATCHLEVEL_VERSION "${CMAKE_MATCH_1}") - set(GMP_VERSION - ${GMP_MAJOR_VERSION}.${GMP_MINOR_VERSION}.${GMP_PATCHLEVEL_VERSION}) - endif() - endforeach() - - # Check whether found version exists and exceeds the minimum requirement - if(NOT GMP_VERSION) - set(GMP_VERSION_OK FALSE) - message(STATUS "GMP version was not detected") - elseif(${GMP_VERSION} VERSION_LESS ${GMP_FIND_VERSION}) - set(GMP_VERSION_OK FALSE) - message(STATUS "GMP version ${GMP_VERSION} found in ${GMP_INCLUDES}, " - "but at least version ${GMP_FIND_VERSION} is required") - else() - set(GMP_VERSION_OK TRUE) - endif() -endif() - -if(STBIN) - set(_gmp_lib_name libgmp.a) -else() - set(_gmp_lib_name libgmp.so) -endif() - -find_library(GMP_LIBRARIES - NAMES - ${_gmp_lib_name} gmp.lib libgmp-10 libgmp gmp - HINTS - ${_GMP_BREW_HINT} - INCLUDE_DIRS - ${GMP_INCLUDES} - PATHS - $ENV{GMPDIR} ${LIB_INSTALL_DIR} -) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(gmp DEFAULT_MSG - GMP_INCLUDES GMP_LIBRARIES GMP_VERSION_OK) -mark_as_advanced(GMP_INCLUDES GMP_LIBRARIES) diff --git a/cmake_modules/Findsodium.cmake b/cmake_modules/Findsodium.cmake deleted file mode 100644 index 0350b67fce9b..000000000000 --- a/cmake_modules/Findsodium.cmake +++ /dev/null @@ -1,294 +0,0 @@ -# Written in 2016 by Henrik Steffen Gaßmann -# -# To the extent possible under law, the author(s) have dedicated all -# copyright and related and neighboring rights to this software to the -# public domain worldwide. This software is distributed without any warranty. -# -# You should have received a copy of the CC0 Public Domain Dedication -# along with this software. If not, see -# -# http://creativecommons.org/publicdomain/zero/1.0/ -# -######################################################################## -# Tries to find the local libsodium installation. -# -# On Windows the sodium_DIR environment variable is used as a default -# hint which can be overridden by setting the corresponding cmake variable. -# -# Once done the following variables will be defined: -# -# sodium_FOUND -# sodium_INCLUDE_DIR -# sodium_LIBRARY_DEBUG -# sodium_LIBRARY_RELEASE -# -# -# Furthermore an imported "sodium" target is created. -# - -if (CMAKE_C_COMPILER_ID STREQUAL "GNU" - OR CMAKE_C_COMPILER_ID STREQUAL "Clang") - set(_GCC_COMPATIBLE 1) -endif() - -# static library option -if (NOT DEFINED sodium_USE_STATIC_LIBS) - option(sodium_USE_STATIC_LIBS "enable to statically link against sodium" OFF) -endif() -if(NOT (sodium_USE_STATIC_LIBS EQUAL sodium_USE_STATIC_LIBS_LAST)) - unset(sodium_LIBRARY CACHE) - unset(sodium_LIBRARY_DEBUG CACHE) - unset(sodium_LIBRARY_RELEASE CACHE) - unset(sodium_DLL_DEBUG CACHE) - unset(sodium_DLL_RELEASE CACHE) - set(sodium_USE_STATIC_LIBS_LAST ${sodium_USE_STATIC_LIBS} CACHE INTERNAL "internal change tracking variable") -endif() - - -######################################################################## -# UNIX -if (UNIX) - # import pkg-config - find_package(PkgConfig QUIET) - if (PKG_CONFIG_FOUND) - pkg_check_modules(sodium_PKG QUIET libsodium) - endif() - - if(sodium_USE_STATIC_LIBS) - foreach(_libname ${sodium_PKG_STATIC_LIBRARIES}) - if (NOT _libname MATCHES "^lib.*\\.a$") # ignore strings already ending with .a - list(INSERT sodium_PKG_STATIC_LIBRARIES 0 "lib${_libname}.a") - endif() - endforeach() - list(REMOVE_DUPLICATES sodium_PKG_STATIC_LIBRARIES) - - # if pkgconfig for libsodium doesn't provide - # static lib info, then override PKG_STATIC here.. - if (NOT sodium_PKG_STATIC_FOUND) - set(sodium_PKG_STATIC_LIBRARIES libsodium.a) - endif() - - set(XPREFIX sodium_PKG_STATIC) - else() - if (NOT sodium_PKG_FOUND) - set(sodium_PKG_LIBRARIES sodium) - endif() - - set(XPREFIX sodium_PKG) - endif() - - find_path(sodium_INCLUDE_DIR sodium.h - HINTS ${${XPREFIX}_INCLUDE_DIRS} - ) - find_library(sodium_LIBRARY_DEBUG NAMES ${${XPREFIX}_LIBRARIES} - HINTS ${${XPREFIX}_LIBRARY_DIRS} - ) - find_library(sodium_LIBRARY_RELEASE NAMES ${${XPREFIX}_LIBRARIES} - HINTS ${${XPREFIX}_LIBRARY_DIRS} - ) - - -######################################################################## -# Windows -elseif (WIN32) - set(sodium_DIR "$ENV{sodium_DIR}" CACHE FILEPATH "sodium install directory") - mark_as_advanced(sodium_DIR) - - find_path(sodium_INCLUDE_DIR sodium.h - HINTS ${sodium_DIR} - PATH_SUFFIXES include - ) - - if (MSVC) - # detect target architecture - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/arch.cpp" [=[ - #if defined _M_IX86 - #error ARCH_VALUE x86_32 - #elif defined _M_X64 - #error ARCH_VALUE x86_64 - #endif - #error ARCH_VALUE unknown - ]=]) - try_compile(_UNUSED_VAR "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/arch.cpp" - OUTPUT_VARIABLE _COMPILATION_LOG - ) - string(REGEX REPLACE ".*ARCH_VALUE ([a-zA-Z0-9_]+).*" "\\1" _TARGET_ARCH "${_COMPILATION_LOG}") - - # construct library path - if (_TARGET_ARCH STREQUAL "x86_32") - string(APPEND _PLATFORM_PATH "Win32") - elseif(_TARGET_ARCH STREQUAL "x86_64") - string(APPEND _PLATFORM_PATH "x64") - else() - message(FATAL_ERROR "the ${_TARGET_ARCH} architecture is not supported by Findsodium.cmake.") - endif() - string(APPEND _PLATFORM_PATH "/$$CONFIG$$") - - if (MSVC_VERSION LESS 1900) - math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 60") - else() - math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 50") - endif() - string(APPEND _PLATFORM_PATH "/v${_VS_VERSION}") - - if (sodium_USE_STATIC_LIBS) - string(APPEND _PLATFORM_PATH "/static") - else() - string(APPEND _PLATFORM_PATH "/dynamic") - endif() - - string(REPLACE "$$CONFIG$$" "Debug" _DEBUG_PATH_SUFFIX "${_PLATFORM_PATH}") - string(REPLACE "$$CONFIG$$" "Release" _RELEASE_PATH_SUFFIX "${_PLATFORM_PATH}") - - find_library(sodium_LIBRARY_DEBUG libsodium.lib - HINTS ${sodium_DIR} - PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX} - ) - find_library(sodium_LIBRARY_RELEASE libsodium.lib - HINTS ${sodium_DIR} - PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX} - ) - if (NOT sodium_USE_STATIC_LIBS) - set(CMAKE_FIND_LIBRARY_SUFFIXES_BCK ${CMAKE_FIND_LIBRARY_SUFFIXES}) - set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll") - find_library(sodium_DLL_DEBUG libsodium - HINTS ${sodium_DIR} - PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX} - ) - find_library(sodium_DLL_RELEASE libsodium - HINTS ${sodium_DIR} - PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX} - ) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_BCK}) - endif() - - elseif(_GCC_COMPATIBLE) - if (sodium_USE_STATIC_LIBS) - find_library(sodium_LIBRARY_DEBUG libsodium.a - HINTS ${sodium_DIR} - PATH_SUFFIXES lib - ) - find_library(sodium_LIBRARY_RELEASE libsodium.a - HINTS ${sodium_DIR} - PATH_SUFFIXES lib - ) - else() - find_library(sodium_LIBRARY_DEBUG libsodium.dll.a - HINTS ${sodium_DIR} - PATH_SUFFIXES lib - ) - find_library(sodium_LIBRARY_RELEASE libsodium.dll.a - HINTS ${sodium_DIR} - PATH_SUFFIXES lib - ) - - file(GLOB _DLL - LIST_DIRECTORIES false - RELATIVE "${sodium_DIR}/bin" - "${sodium_DIR}/bin/libsodium*.dll" - ) - find_library(sodium_DLL_DEBUG ${_DLL} libsodium - HINTS ${sodium_DIR} - PATH_SUFFIXES bin - ) - find_library(sodium_DLL_RELEASE ${_DLL} libsodium - HINTS ${sodium_DIR} - PATH_SUFFIXES bin - ) - endif() - else() - message(FATAL_ERROR "this platform is not supported by FindSodium.cmake") - endif() - - -######################################################################## -# unsupported -else() - message(FATAL_ERROR "this platform is not supported by FindSodium.cmake") -endif() - - -######################################################################## -# common stuff - -# extract sodium version -if (sodium_INCLUDE_DIR) - set(_VERSION_HEADER "${_INCLUDE_DIR}/sodium/version.h") - if (EXISTS _VERSION_HEADER) - file(READ "${_VERSION_HEADER}" _VERSION_HEADER_CONTENT) - string(REGEX REPLACE ".*#[ \t]*define[ \t]*SODIUM_VERSION_STRING[ \t]*\"([^\n]*)\".*" "\\1" - sodium_VERSION "${_VERSION_HEADER_CONTENT}") - set(sodium_VERSION "${sodium_VERSION}" PARENT_SCOPE) - endif() -endif() - -# communicate results -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args( - sodium # The name must be either uppercase or match the filename case. - REQUIRED_VARS - sodium_LIBRARY_RELEASE - sodium_LIBRARY_DEBUG - sodium_INCLUDE_DIR - VERSION_VAR - sodium_VERSION -) - -if(Sodium_FOUND) - set(sodium_LIBRARIES - optimized ${sodium_LIBRARY_RELEASE} debug ${sodium_LIBRARY_DEBUG}) -endif() - -# mark file paths as advanced -mark_as_advanced(sodium_INCLUDE_DIR) -mark_as_advanced(sodium_LIBRARY_DEBUG) -mark_as_advanced(sodium_LIBRARY_RELEASE) -if (WIN32) - mark_as_advanced(sodium_DLL_DEBUG) - mark_as_advanced(sodium_DLL_RELEASE) -endif() - -# create imported target -if(sodium_USE_STATIC_LIBS) - set(_LIB_TYPE STATIC) -else() - set(_LIB_TYPE SHARED) -endif() -add_library(sodium ${_LIB_TYPE} IMPORTED) - -set_target_properties(sodium PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${sodium_INCLUDE_DIR}" - IMPORTED_LINK_INTERFACE_LANGUAGES "C" -) - -if (sodium_USE_STATIC_LIBS) - set_target_properties(sodium PROPERTIES - INTERFACE_COMPILE_DEFINITIONS "SODIUM_STATIC" - IMPORTED_LOCATION "${sodium_LIBRARY_RELEASE}" - IMPORTED_LOCATION_DEBUG "${sodium_LIBRARY_DEBUG}" - ) -else() - if (UNIX) - set_target_properties(sodium PROPERTIES - IMPORTED_LOCATION "${sodium_LIBRARY_RELEASE}" - IMPORTED_LOCATION_DEBUG "${sodium_LIBRARY_DEBUG}" - ) - elseif (WIN32) - set_target_properties(sodium PROPERTIES - IMPORTED_IMPLIB "${sodium_LIBRARY_RELEASE}" - IMPORTED_IMPLIB_DEBUG "${sodium_LIBRARY_DEBUG}" - ) - if (NOT (sodium_DLL_DEBUG MATCHES ".*-NOTFOUND")) - set_target_properties(sodium PROPERTIES - IMPORTED_LOCATION_DEBUG "${sodium_DLL_DEBUG}" - ) - endif() - if (NOT (sodium_DLL_RELEASE MATCHES ".*-NOTFOUND")) - set_target_properties(sodium PROPERTIES - IMPORTED_LOCATION_RELWITHDEBINFO "${sodium_DLL_RELEASE}" - IMPORTED_LOCATION_MINSIZEREL "${sodium_DLL_RELEASE}" - IMPORTED_LOCATION_RELEASE "${sodium_DLL_RELEASE}" - ) - endif() - endif() -endif() diff --git a/configure.ac b/configure.ac deleted file mode 100644 index 9878a39ec174..000000000000 --- a/configure.ac +++ /dev/null @@ -1,913 +0,0 @@ -AC_PREREQ([2.60]) -AC_INIT([libdashbls],[2.1]) -AC_CONFIG_AUX_DIR([build-aux]) -AC_CONFIG_MACRO_DIR([build-aux/m4]) - -dnl Unless the user specified ARFLAGS, force it to be cr -AC_ARG_VAR(ARFLAGS, [Flags for the archiver, defaults to if not set]) -if test "x${ARFLAGS+set}" != "xset"; then - ARFLAGS="qc" -fi - -AC_CANONICAL_HOST - -AH_TOP([#ifndef RLC_CONF_H]) -AH_TOP([#define RLC_CONF_H]) -AH_BOTTOM([#endif /*RLC_CONF_H*/]) -AM_INIT_AUTOMAKE([foreign no-define subdir-objects]) - -dnl faketime messes with timestamps and causes configure to be re-run. -dnl --disable-maintainer-mode can be used to bypass this. -AM_MAINTAINER_MODE([enable]) - -dnl make the compilation flags quiet unless V=1 is used -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) - -dnl Compiler checks (here before libtool). -if test "x${CFLAGS+set}" = "xset"; then - CFLAGS_overridden=yes -else - CFLAGS_overridden=no -fi -if test "x${CXXFLAGS+set}" = "xset"; then - CXXFLAGS_overridden=yes -else - CXXFLAGS_overridden=no -fi - -AC_PROG_CC - -AC_PROG_CXX - -dnl By default, libtool for mingw refuses to link static libs into a dll for -dnl fear of mixing pic/non-pic objects, and import/export complications. Since -dnl we have those under control, re-enable that functionality. -case $host in - *mingw*) - lt_cv_deplibs_check_method="pass_all" - ;; -esac -dnl Require C++14 compiler (no GNU extensions) -AX_CXX_COMPILE_STDCXX([14], [noext], [mandatory], [nodefault]) - -dnl Libtool init checks. -LT_INIT([pic-only]) - -AC_PATH_TOOL(AR, ar) -AC_PATH_TOOL(RANLIB, ranlib) -AC_PATH_TOOL(STRIP, strip) - -AM_PROG_AS - -AC_ARG_ENABLE([tests], - [AS_HELP_STRING([--enable-tests], - [Compile with tests [default=yes]])], - [use_tests=$enableval], - [use_tests=yes]) - -AC_ARG_ENABLE([bench], - [AS_HELP_STRING([--enable-bench], - [Compile with benchmarks [default=yes]])], - [use_bench=$enableval], - [use_bench=yes]) - -AC_ARG_ENABLE([hardening], - [AS_HELP_STRING([--enable-hardening], - [Enable hardening flags and arguments [default=auto]])], - [use_hardening=$enableval], - [use_hardening=auto]) - -AC_ARG_ENABLE([optimizations], - [AS_HELP_STRING([--enable-optimizations], - [Enable compiler and library optimizations [default=yes]])], - [use_optimizations=$enableval], - [use_optimizations=yes]) - -AC_ARG_ENABLE([debug], - [AS_HELP_STRING([--enable-debug], - [Build with debugging support [default=no]])], - [use_debug=$enableval], - [use_debug=no]) - -AC_LANG_PUSH([C]) - -dnl Check for a flag to turn compiler warnings into errors. This is helpful for checks which may -dnl appear to succeed because by default they merely emit warnings when they fail. -dnl -dnl Note that this is not necessarily a check to see if -Werror is supported, but rather to see if -dnl a compile with -Werror can succeed. This is important because the compiler may already be -dnl warning about something unrelated, for example about some path issue. If that is the case, -dnl -Werror cannot be used because all of those warnings would be turned into errors. -AX_CHECK_COMPILE_FLAG([-Werror], [FLAG_WERROR="-Werror"], [FLAG_WERROR=""]) - -if test x"$use_debug" = x"yes" -o x"$use_optimizations" = x"no"; then - dnl Clear default -g -O2 flags - if test x"$CFLAGS_overridden" = x"no"; then - CFLAGS="" - fi - if test x"$CXXFLAGS_overridden" = x"no"; then - CXXFLAGS="" - fi - - dnl Disable optimizations - AX_CHECK_COMPILE_FLAG([-O0], [[DEBUG_FLAGS="$DEBUG_FLAGS -O0"]], [], [[$FLAG_WERROR]]) - - if test x"$use_debug" = x"yes"; then - dnl Prefer -g3, fall back to -g if that is unavailable. - AX_CHECK_COMPILE_FLAG( - [-g3], - [[DEBUG_FLAGS="$DEBUG_FLAGS -g3"]], - [AX_CHECK_COMPILE_FLAG([-g],[[DEBUG_FLAGS="$DEBUG_FLAGS -g"]])], [[$FLAG_WERROR]]) - - AX_CHECK_COMPILE_FLAG([-ftrapv],[DEBUG_FLAGS="$DEBUG_FLAGS -ftrapv"], [], [[$FLAG_WERROR]]) - else - dnl Reintroduce -g flag deleted during C(XX)FLAGS reset - AX_CHECK_COMPILE_FLAG([-g],[[DEBUG_FLAGS="$DEBUG_FLAGS -g"]], [], [[$FLAG_WERROR]]) - - dnl -ftrapv and -fwrapv conflict, so we only set this if use_debug=no - AX_CHECK_COMPILE_FLAG([-fwrapv],[DEBUG_FLAGS="$DEBUG_FLAGS -fwrapv"], [], [[$FLAG_WERROR]]) - fi -fi - -dnl Define enum mappings for relic config -AC_DEFINE([RLC_VERSION], ["0.5.0"], [Relic Version]) - -dnl dashbls: Library processor architecture -AC_DEFINE([AVR], [1], [Atmel AVR ATMega128 8-bit architecture.]) -AC_DEFINE([MSP], [2], [MSP430 16-bit architecture.]) -AC_DEFINE([ARM], [3], [ARM 32-bit architecture.]) -AC_DEFINE([X86], [4], [Intel x86-compatible 32-bit architecture.]) -AC_DEFINE([X64], [5], [AMD64-compatible 64-bit architecture.]) - -dnl Relic: Generic options -AC_DEFINE([RELIC_NONE], [0], [Unknown or unrecognized parameter.]) - -dnl Relic: Arithmetic backends -AC_DEFINE([EASY], [1], [Easy C-only backend.]) -AC_DEFINE([GMP], [2], [Backend based on GNU Multiple Precision library.]) -AC_DEFINE([GMP_SEC], [3], [Backend based on GNU Multiple Precision library, but using constant-time code.]) - -AC_DEFUN([GMP_CHECK],[ - AC_REQUIRE([AC_PROG_CC]) - - CPPFLAGS_TEMP="$CPPFLAGS" - CPPFLAGS="$GMP_CPPFLAGS $CPPFLAGS" - LIBS_TEMP="$LIBS" - LIBS="$GMP_LDFLAGS $LIBS" - - AC_CHECK_HEADER( - gmp.h, - [AC_CHECK_LIB(gmp, __gmpz_init, [], [gmp_fail_reason="libgmp not found or unusable"; has_gmp=no;])], - [gmp_fail_reason="gmp header not found"; has_gmp=no;] - ) - - if test x"$has_gmp" != x"no"; then - # Proper support for macOS aarch64 was introduced in 6.3.0, but LTS distros - # like Ubuntu 20.04 (focal) use 6.2.0, so, the minimum supported version is - # determined by platform and architecture. - case $host in - *darwin*) - case $host_cpu in - aarch*) - gmp_major_version=6 - gmp_minor_version=3 - ;; - esac - ;; - *) - gmp_major_version=6 - gmp_minor_version=2 - ;; - esac - AC_MSG_CHECKING([gmp version >= $gmp_major_version.$gmp_minor_version]) - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[@%:@include ]], - [[ - @%:@if __GNU_MP_VERSION < $gmp_major_version || __GNU_MP_VERSION_MINOR < $gmp_minor_version - @%:@error Unsupported GMP version - @%:@endif]])], - [AC_MSG_RESULT([yes]); GMP_LIBS="-lgmp"; has_gmp=yes;], - [AC_MSG_RESULT([no]); gmp_fail_reason="unsupported gmp version"; has_gmp=no;] - ) - fi - - if test x"$want_backend" = x"gmp" && test x"$has_gmp" = x"no"; then - AC_MSG_ERROR([$gmp_fail_reason]) - fi - - CPPFLAGS="$CPPFLAGS_TEMP" - LIBS="$LIBS_TEMP" -]) - -AC_ARG_WITH([backend], - [AS_HELP_STRING([--with-backend=auto|easy|gmp], - [backend implementation to use [default=auto]])], - [want_backend=$withval], - [want_backend=auto] -) - -case $host in - *darwin*) - AC_PATH_PROG([BREW],brew,) - if test x$BREW != x; then - # These Homebrew packages may be keg-only, meaning that they won't be found - # in expected paths because they may conflict with system files. Ask - # Homebrew where each one is located, then adjust paths accordingly. - gmp_prefix=`$BREW --prefix gmp 2>/dev/null` - if test x$gmp_prefix != x; then - GMP_CPPFLAGS="-I$gmp_prefix/include" - GMP_LDFLAGS="-L$gmp_prefix/lib" - fi - fi - ;; - *freebsd*) - GMP_CPPFLAGS="-I/usr/local/include" - GMP_LDFLAGS="-L/usr/local/lib" - ;; -esac - -if test x"$want_backend" = x"auto"; then - if test x"$use_optimizations" = x"no"; then - want_backend=easy - else - GMP_CHECK - if test x"$has_gmp" = x"yes"; then - want_backend=gmp - else - want_backend=easy - fi - fi -else - case $want_backend in - gmp) - dnl GMP_CHECK will report the reason if and why the backend cannot be used. - GMP_CHECK - ;; - easy) - ;; - *) - AC_MSG_ERROR([invalid backend explicitly requested]) - ;; - esac -fi - -case $want_backend in -gmp) - AC_DEFINE(ARITH, GMP, [Define if GNU MP backend is requested]) - ;; -easy) - AC_DEFINE(ARITH, EASY, [Define if C-only backend is requested].) - ;; -*) - AC_MSG_ERROR([invalid backend explicitly requested]) - ;; -esac - -dnl Relic: Multithreading APIs -AC_DEFINE([OPENMP], [1], [OpenMP multithreading support.]) -AC_DEFINE([PTHREAD], [2], [POSIX multithreading support.]) - -dnl Relic: Supported operating systems -AC_DEFINE([LINUX], [1], [GNU/Linux operating system.]) -AC_DEFINE([FREEBSD], [2], [FreeBSD operating system.]) -AC_DEFINE([MACOSX], [3], [MacOS operating system.]) -AC_DEFINE([WINDOWS], [4], [Windows operating system.]) -AC_DEFINE([DROID], [5], [Android operating system.]) -AC_DEFINE([DUINO], [6], [Arduino platform.]) -dnl AC_DEFINE([OPENBSD], [7], [OpenBSD operating system.]) - -dnl Relic: Supported timers -AC_DEFINE([HREAL], [1], [Per-process high-resolution timer.]) -AC_DEFINE([HPROC], [2], [Per-process high-resolution timer.]) -AC_DEFINE([HTHRD], [3], [Per-thread high-resolution timer.]) -AC_DEFINE([ANSI], [5], [ANSI-compatible timer.]) -AC_DEFINE([POSIX], [4], [POSIX-compatible timer.]) -AC_DEFINE([CYCLE], [6], [Cycle-counting timer.]) -AC_DEFINE([PERF], [7], [Performance monitoring framework.]) - -dnl Relic: Memory-allocation policies -AC_DEFINE([AUTO], [1], [Automatic memory allocation.]) -AC_DEFINE([DYNAMIC], [2], [Dynamic memory allocation.]) - -dnl Relic (CP): Support for faster CRT-based exponentiation in factoring-based cryptosystems -AC_DEFINE([PKCS1], [2], [RSA PKCS#1 v1.5 padding.]) -AC_DEFINE([PKCS2], [3], [RSA PKCS#1 v2.1 padding.]) - -dnl Relic (MD): Available hash functions -AC_DEFINE([SH224], [2], [SHA-224 hash function.]) -AC_DEFINE([SH256], [3], [SHA-256 hash function.]) -AC_DEFINE([SH384], [4], [SHA-384 hash function.]) -AC_DEFINE([SH512], [5], [SHA-512 hash function.]) -AC_DEFINE([B2S160], [6], [BLAKE2s-160 hash function.]) -AC_DEFINE([B2S256], [7], [BLAKE2s-256 hash function.]) - -dnl Relic (RAND): Available pseudo-random number generators -AC_DEFINE([HASHD], [1], [NIST HASH-DRBG generator.]) -AC_DEFINE([RDRND], [2], [Intel RdRand instruction.]) -AC_DEFINE([UDEV], [3], [Operating system underlying generator.]) -AC_DEFINE([CALL], [4], [Override library generator with the callback.]) - -dnl Relic (RAND): Available random number generator seeders -AC_DEFINE([LIBC], [1], [Standard C library generator.]) -dnl AC_DEFINE([RDRND], [2], [Intel RdRand instruction.]) -dnl AC_DEFINE([UDEV], [3], [Operating system underlying generator.]) -AC_DEFINE([WCGR], [4], [Use Windows' CryptGenRandom.]) - -dnl Relic (BN): Options for the multiple precision -AC_DEFINE([SINGLE], [1], [A multiple precision integer can store w words.]) -AC_DEFINE([CARRY], [2], [A multiple precision integer can store the result of an addition.]) -AC_DEFINE([DOUBLE], [3], [A multiple precision integer can store the result of a multiplication.]) - -AC_DEFINE([BASIC], [1], [Basic method.]) -AC_DEFINE([PRIME], [1], [Prime curves.]) -AC_DEFINE([TATEP], [1], [Tate pairing.]) -AC_DEFINE([COMBA], [2], [Comba method.]) -AC_DEFINE([LEHME], [2], [Lehmer's fast GCD Algorithm.]) -AC_DEFINE([SAFEP], [2], [Safe prime generation.]) -AC_DEFINE([QUICK], [2], [Fast reduction modulo special form prime.]) -AC_DEFINE([BINAR], [2], [Binary inversion.]) -AC_DEFINE([LAZYR], [2], [Lazy-reduced extension field arithmetic.]) -AC_DEFINE([LODAH], [2], [Lopez-Dahab multiplication.]) -AC_DEFINE([SLIDE], [2], [Sliding window modular exponentiation.]) -AC_DEFINE([PROJC], [2], [Projective coordinates.]) -AC_DEFINE([COMBS], [2], [Single-table comb method.]) -AC_DEFINE([TRICK], [2], [Shamir's trick.]) -AC_DEFINE([CHAR2], [2], [Binary curves.]) -AC_DEFINE([WEILP], [2], [Weil pairing.]) -AC_DEFINE([MONTY], [3], [Montgomery method.]) -AC_DEFINE([STEIN], [3], [Stein's binary GCD Algorithm.]) -AC_DEFINE([STRON], [3], [Strong prime generation.]) -AC_DEFINE([INTEG], [3], [Integrated modular addtion.]) -AC_DEFINE([INTER], [3], [Interleaving of w-(T)NAFs.]) -AC_DEFINE([ALMOS], [3], [Almost inverse algorithm.]) -AC_DEFINE([JACOB], [3], [Jacobian coordinates.]) -AC_DEFINE([COMBD], [3], [Double-table comb method.]) -AC_DEFINE([HALVE], [3], [Halving.]) -AC_DEFINE([EDDIE], [3], [Edwards curves.]) -AC_DEFINE([EXTND], [3], [Extended projective twisted Edwards coordinates.]) -AC_DEFINE([OATEP], [3], [Optimal ate pairing.]) -AC_DEFINE([PMERS], [4], [Pseudo-Mersenne method.]) -AC_DEFINE([MULTP], [4], [Reuse multiplication for squaring.]) -AC_DEFINE([EXGCD], [4], [Extended Euclidean algorithm.]) -AC_DEFINE([LWNAF], [4], [Left-to-right Width-w NAF.]) -AC_DEFINE([JOINT], [4], [Joint sparse form.]) -AC_DEFINE([DIVST], [5], [Constant-time inversion by Bernstein-Yang division steps.]) -AC_DEFINE([ITOHT], [5], [Itoh-Tsuji inversion.]) -AC_DEFINE([LWREG], [5], [Left-to-right Width-w NAF.]) -AC_DEFINE([BRUCH], [6], [Hardware-friendly inversion by Brunner-Curiger-Hofstetter.]) -AC_DEFINE([CTAIA], [7], [Constant-time version of almost inverse.]) -AC_DEFINE([LOWER], [8], [Use implementation provided by the lower layer.]) - -if test x"$use_debug" = x"yes"; then - AC_DEFINE([DEBUG], [1], [Define this symbol if debugging support is enabled]) -fi - -dnl Define relic switches -AC_ARG_ENABLE([profiling], - [AS_HELP_STRING([--enable-profiling], - [Build with profiling support [default=no]])], - [use_profiling=$enableval], - [use_profiling=no]) - -if test x$use_profiling = xyes; then - AC_DEFINE([PROFL], [1], [Define this symbol if profiling support is enabled]) -fi - -AC_ARG_ENABLE([check], - [AS_HELP_STRING([--enable-check], - [Build with error-checking support [default=no]])], - [use_check=$enableval], - [use_check=no]) - -if test x$use_check = xyes; then - AC_DEFINE([CHECK], [1], [Define this symbol if error-checking support is enabled]) -fi - -AC_ARG_ENABLE([verbs], - [AS_HELP_STRING([--enable-verbs], - [Build with detailed error messages [default=no]])], - [use_verbs=$enableval], - [use_verbs=no]) - -if test x$use_verbs = xyes; then - AC_DEFINE([VERBS], [1], [Define this symbol if detailed error messages are enabled]) -fi - -AC_ARG_ENABLE([overhead], - [AS_HELP_STRING([--enable-overhead], - [Build with overhead estimation [default=no]])], - [use_overhead=$enableval], - [use_overhead=no]) - -if test x$use_overhead = xyes; then - AC_DEFINE([OVERH], [1], [Define this symbol if overhead estimation is enabled]) -fi - -AC_ARG_ENABLE([quiet], - [AS_HELP_STRING([--enable-quiet], - [Build with printing disabled [default=yes]])], - [use_quiet=$enableval], - [use_quiet=yes]) - -if test x$use_quiet = xyes; then - AC_DEFINE([QUIET], [1], [Define this symbol if printing is disabled]) -fi - -AC_ARG_ENABLE([color], - [AS_HELP_STRING([--enable-color], - [Build with colored output support [default=yes]])], - [use_color=$enableval], - [use_color=yes]) - -if test x$use_color = xyes; then - AC_DEFINE([COLOR], [1], [Define this symbol if colored output is enabled]) -fi - -AC_ARG_ENABLE([big_endian], - [AS_HELP_STRING([--enable-big-endian], - [Build with big-endian support [default=no]])], - [use_big_endian=$enableval], - [use_big_endian=no]) - -if test x$use_big_endian = xyes; then - AC_DEFINE([BIGED], [1], [Define this symbol if big-endian support is enabled]) -fi - -use_pkgconfig=yes - -if test x"$use_optimizations" = x"yes"; then - case $host_cpu in - amd64 | x86_64) - dnl Support for AMD64 (also known as x86_64 on some platforms) processors - CPU_ARCH="x64" - AC_DEFINE([ARCH], [X64], [Architecture.]) - AC_DEFINE([WSIZE], [64], [Size of word in this architecture.]) - ;; - aarch*) - dnl Support for 64-bit ARM processors - dnl Relic does not support aarch64 yet, set CPU_ARCH to none and ARCH to RELIC_NONE. - CPU_ARCH="none" - AC_DEFINE([ARCH], [RELIC_NONE], [Architecture.]) - AC_DEFINE([WSIZE], [64], [Size of word in this architecture.]) - ;; - i?86) - dnl Support for Intel x86 processors - CPU_ARCH="x86" - AC_DEFINE([ARCH], [X86], [Architecture.]) - AC_DEFINE([WSIZE], [32], [Size of word in this architecture.]) - ;; - arm*) - dnl Support for 32-bit native ARM processors - CPU_ARCH="arm" - AC_DEFINE([ARCH], [ARM], [Architecture.]) - AC_DEFINE([WSIZE], [32], [Size of word in this architecture.]) - ;; - *64*) - dnl Support for an undefined 64-bit architecture - CPU_ARCH="none" - AC_DEFINE([ARCH], [RELIC_NONE], [Architecture.]) - AC_DEFINE([WSIZE], [64], [Size of word in this architecture.]) - ;; - *32*) - dnl Support for an undefined 32-bit architecture - CPU_ARCH="none" - AC_DEFINE([ARCH], [RELIC_NONE], [Architecture.]) - AC_DEFINE([WSIZE], [32], [Size of word in this architecture.]) - ;; - *) - AC_MSG_ERROR([Unable to determine host architecture, may not be supported!]) - ;; - esac -else - case $host_cpu in - *64*) - dnl Support for an undefined 64-bit architecture - CPU_ARCH="none" - AC_DEFINE([ARCH], [RELIC_NONE], [Architecture.]) - AC_DEFINE([WSIZE], [64], [Size of word in this architecture.]) - ;; - *32* | arm* | i?86) - dnl Support for an undefined 32-bit architecture - CPU_ARCH="none" - AC_DEFINE([ARCH], [RELIC_NONE], [Architecture.]) - AC_DEFINE([WSIZE], [32], [Size of word in this architecture.]) - ;; - *) - AC_MSG_ERROR([Unable to determine host architecture, may not be supported!]) - ;; - esac -fi - -case $host in - *darwin*) - AC_DEFINE([OPSYS], [MACOSX], [Detected operation system.]) - TARGET_OS=darwin - - AC_PATH_PROG([BREW],brew,) - if test x$BREW = x; then - AC_PATH_PROG([PORT],port,) - # If homebrew isn't installed and macports is, add the macports default paths - # as a last resort. - if test x$PORT != x; then - CPPFLAGS="$CPPFLAGS -isystem /opt/local/include" - LDFLAGS="$LDFLAGS -L/opt/local/lib" - fi - fi - ;; - *mingw*) - AC_DEFINE([OPSYS], [WINDOWS], [Detected operation system.]) - TARGET_OS=windows - - use_pkgconfig=no - LIBTOOL_APP_LDFLAGS="$LIBTOOL_APP_LDFLAGS -all-static" - - dnl libtool insists upon adding -nostdlib and a list of objects/libs to link against. - dnl That breaks our ability to build dll's with static libgcc/libstdc++/libssp. Override - dnl its command here, with the predeps/postdeps removed, and -static inserted. Postdeps are - dnl also overridden to prevent their insertion later. - dnl This should only affect dll's. - archive_cmds_CXX="\$CC -shared \$libobjs \$deplibs \$compiler_flags -static -o \$output_objdir/\$soname \${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker \$lib" - postdeps_CXX= - ;; - *linux*) - AC_DEFINE([OPSYS], [LINUX], [Detected operation system.]) - TARGET_OS=linux - - RELIC_CPPFLAGS="-D_GNU_SOURCE" - ;; - *android*) - AC_DEFINE([OPSYS], [DROID], [Detected operation system.]) - TARGET_OS=android - ;; - *freebsd*) - AC_DEFINE([OPSYS], [FREEBSD], [Detected operation system.]) - TARGET_OS=freebsd - ;; - *netbsd*) - AC_DEFINE([OPSYS], [NETBSD], [Detected operation system.]) - TARGET_OS=netbsd - ;; - *) - AC_DEFINE([OPSYS], [RELIC_NONE], [Detected operation system.]) - ;; -esac - -case $host in - *darwin*) - dnl Relic: Don't define FP_QNRES on Darwin - AC_DEFINE([SEED], [UDEV], [Chosen random generator seeder.]) - ;; - *mingw*) - AC_DEFINE([FP_QNRES], [], [Use -1 as quadratic non-residue.]) - AC_DEFINE([SEED], [WCGR], [Chosen random generator seeder.]) - ;; - *) - AC_DEFINE([FP_QNRES], [], [Use -1 as quadratic non-residue.]) - AC_DEFINE([SEED], [UDEV], [Chosen random generator seeder.]) - ;; -esac - -if test x$use_pkgconfig = xyes; then - m4_ifndef([PKG_PROG_PKG_CONFIG], [AC_MSG_ERROR(PKG_PROG_PKG_CONFIG macro not found. Please install pkg-config and re-run autogen.sh.)]) - m4_ifdef([PKG_PROG_PKG_CONFIG], [ - PKG_PROG_PKG_CONFIG - if test x"$PKG_CONFIG" = "x"; then - AC_MSG_ERROR(pkg-config not found.) - fi - ]) -fi - -saved_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS -pipe" -AC_MSG_CHECKING([if ${CC} supports -pipe]) -AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], - [ AC_MSG_RESULT([yes]) ], - [ AC_MSG_RESULT([no]) - CFLAGS="$saved_CFLAGS" - ]) - -saved_CFLAGS="$CFLAGS" -CFLAGS="$CFLAGS -fomit-frame-pointer" -AC_MSG_CHECKING([if ${CC} supports -fomit-frame-pointer]) -AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], - [ AC_MSG_RESULT([yes]) ], - [ AC_MSG_RESULT([no]) - CFLAGS="$saved_CFLAGS" - ]) - -if test x"$CFLAGS_overridden" = x"no" -a x"$CXXFLAGS_overridden" = x"no"; then - dnl Enable warnings - AX_CHECK_COMPILE_FLAG([-Wall],[WARN_FLAGS="$WARN_FLAGS -Wall"], [], [[$FLAG_WERROR]]) - AX_CHECK_COMPILE_FLAG([-Wcast-align],[WARN_FLAGS="$WARN_FLAGS -Wcast-align"], [], [[$FLAG_WERROR]]) - AX_CHECK_COMPILE_FLAG([-Wextra],[WARN_FLAGS="$WARN_FLAGS -Wextra"], [], [[$FLAG_WERROR]]) - - dnl Exclude known warnings - AX_CHECK_COMPILE_FLAG([-Wlong-long],[NOWARN_FLAGS="$NOWARN_FLAGS -Wno-long-long"], [], [[$FLAG_WERROR]]) - AX_CHECK_COMPILE_FLAG([-Wshadow],[NOWARN_FLAGS="$NOWARN_FLAGS -Wno-shadow"], [], [[$FLAG_WERROR]]) - AX_CHECK_COMPILE_FLAG([-Wsign-compare],[NOWARN_FLAGS="$NOWARN_FLAGS -Wno-sign-compare"], [], [[$FLAG_WERROR]]) - AX_CHECK_COMPILE_FLAG([-Wstrict-prototypes],[NOWARN_FLAGS="$NOWARN_FLAGS -Wno-strict-prototypes"], [], [[$FLAG_WERROR]]) - AX_CHECK_COMPILE_FLAG([-Wunused-function],[NOWARN_FLAGS="$NOWARN_FLAGS -Wno-unused-function"], [], [[$FLAG_WERROR]]) - AX_CHECK_COMPILE_FLAG([-Wunused-parameter],[NOWARN_FLAGS="$NOWARN_FLAGS -Wno-unused-parameter"], [], [[$FLAG_WERROR]]) -fi - -dnl set default settings for relic -AC_DEFINE([ALIGN], [1], [Byte boundary to align digit vectors.]) - -AC_DEFINE(WITH_BN,, Build multiple precision integer module.) -AC_DEFINE(WITH_DV,, Temporary double-precision digit vectors.) -AC_DEFINE(WITH_FP,, Build prime field module.) -AC_DEFINE(WITH_FPX,, Build prime field extension module.) -AC_DEFINE(WITH_FB,, Build binary field module.) -AC_DEFINE(WITH_FBX,, Build binary field extension module.) -AC_DEFINE(WITH_EP,, Build prime elliptic curve module.) -AC_DEFINE(WITH_EPX,, Build prime field extension elliptic curve module.) -AC_DEFINE(WITH_EB,, Build binary elliptic curve module.) -AC_DEFINE(WITH_ED,, Build elliptic Edwards curve module.) -AC_DEFINE(WITH_EC,, Build elliptic curve cryptography module.) -AC_DEFINE(WITH_PP,, Build pairings over prime curves module.) -AC_DEFINE(WITH_PC,, Build pairing-based cryptography module.) -AC_DEFINE(WITH_BC,, Build block ciphers.) -AC_DEFINE(WITH_MD,, Build hash functions.) -AC_DEFINE(WITH_CP,, Build cryptographic protocols.) -AC_DEFINE(WITH_MPC,, Build Multi-party computation primitives.) - -AC_DEFINE(BN_PRECI, 1024, Required precision in bits.) -AC_DEFINE(BN_KARAT, 0, Number of Karatsuba steps.) -AC_DEFINE(BN_MAGNI, [DOUBLE], Effective size of a multiple precision integer.) - -AC_DEFINE(BN_METHD, "COMBA;COMBA;MONTY;SLIDE;BASIC;BASIC", Multiple precision arithmetic method.) -AC_DEFINE(BN_MUL, COMBA, Chosen multiple precision multiplication method.) -AC_DEFINE(BN_SQR, COMBA, Chosen multiple precision multiplication method.) -AC_DEFINE(BN_MOD, MONTY, Chosen multiple precision modular reduction method.) -AC_DEFINE(BN_MXP, SLIDE, Chosen multiple precision modular exponentiation method.) -AC_DEFINE(BN_GCD, BASIC, Chosen multiple precision greatest common divisor method.) -AC_DEFINE(BN_GEN, BASIC, Chosen prime generation algorithm.) - -AC_DEFINE(FP_PRIME, 381, Prime field size in bits.) -AC_DEFINE(FP_METHD, "INTEG;INTEG;INTEG;MONTY;LOWER;SLIDE", Prime field arithmetic method.) -AC_DEFINE(FP_KARAT, 0, Number of Karatsuba steps.) -AC_DEFINE(FP_WIDTH, 4, Width of window processing for exponentiation methods.) -AC_DEFINE(FP_ADD, INTEG, Chosen prime field multiplication method.) -AC_DEFINE(FP_MUL, INTEG, Chosen prime field multiplication method.) -AC_DEFINE(FP_SQR, INTEG, Chosen prime field multiplication method.) -AC_DEFINE(FP_RDC, MONTY, Chosen prime field reduction method.) -AC_DEFINE(FP_INV, LOWER, Chosen prime field inversion method.) -AC_DEFINE(FP_EXP, SLIDE, Chosen multiple precision modular exponentiation method.) - -AC_DEFINE(FPX_METHD, "INTEG;INTEG;LAZYR", Prime extension field arithmetic method.) -AC_DEFINE(FPX_QDR, INTEG, Chosen extension field arithmetic method.) -AC_DEFINE(FPX_CBC, INTEG, Chosen extension field arithmetic method.) -AC_DEFINE(FPX_RDC, LAZYR, Chosen extension field arithmetic method.) - -AC_DEFINE(FB_METHD, "LODAH;QUICK;QUICK;QUICK;QUICK;QUICK;EXGCD;SLIDE;QUICK", Binary field arithmetic method) -AC_DEFINE(FB_POLYN, 283, Irreducible polynomial size in bits.) -AC_DEFINE(FB_KARAT, 0, Number of Karatsuba levels.) -AC_DEFINE(FB_TRINO,, Prefer trinomials over pentanomials.) -AC_DEFINE(FB_PRECO,, Precompute multiplication table for sqrt(z).) -AC_DEFINE(FB_WIDTH, 4, Width of window processing for exponentiation methods.) -AC_DEFINE(FB_MUL, LODAH, Chosen binary field multiplication method.) -AC_DEFINE(FB_SQR, QUICK, Chosen binary field squaring method.) -AC_DEFINE(FB_RDC, QUICK, Chosen binary field modular reduction method.) -AC_DEFINE(FB_SRT, QUICK, Chosen binary field modular reduction method.) -AC_DEFINE(FB_TRC, QUICK, Chosen trace computation method.) -AC_DEFINE(FB_SLV, QUICK, Chosen method to solve a quadratic equation.) -AC_DEFINE(FB_INV, EXGCD, Chosen binary field inversion method.) -AC_DEFINE(FB_EXP, SLIDE, Chosen multiple precision modular exponentiation method.) -AC_DEFINE(FB_ITR, QUICK, Chosen method to solve a quadratic equation.) - -AC_DEFINE(EP_METHD, "PROJC;LWNAF;COMBS;INTER", Prime elliptic curve arithmetic method.) -AC_DEFINE(EP_ENDOM,, Support for prime curves with efficient endormorphisms.) -AC_DEFINE(EP_MIXED,, Use mixed coordinates.) -AC_DEFINE(EP_PRECO,, Build precomputation table for generator.) -AC_DEFINE(EP_CTMAP,, Enable isogeny map for SSWU map-to-curve.) -AC_DEFINE(EP_DEPTH, 4, Width of precomputation table for fixed point methods.) -AC_DEFINE(EP_WIDTH, 4, Width of window processing for unknown point methods.) -AC_DEFINE(EP_ADD, PROJC, Chosen prime elliptic curve coordinate method.) -AC_DEFINE(EP_MUL, LWNAF, Chosen prime elliptic curve point multiplication method.) -AC_DEFINE(EP_FIX, COMBS, Chosen prime elliptic curve point multiplication method.) -AC_DEFINE(EP_SIM, INTER, Chosen prime elliptic curve simulteanous point multiplication method.) - -AC_DEFINE(EB_METHD, "PROJC;LWNAF;COMBS;INTER", Binary elliptic curve arithmetic method.) -AC_DEFINE(EB_PLAIN,, Support for ordinary curves without endormorphisms.) -AC_DEFINE(EB_KBLTZ,, Support for Koblitz anomalous binary curves.) -AC_DEFINE(EB_MIXED,, Use mixed coordinates.) -AC_DEFINE(EB_PRECO,, Build precomputation table for generator.) -AC_DEFINE(EB_DEPTH, 4, Width of precomputation table for fixed point methods.) -AC_DEFINE(EB_WIDTH, 4, Width of window processing for unknown point methods.) -AC_DEFINE(EB_ADD, PROJC, Chosen binary elliptic curve coordinate method.) -AC_DEFINE(EB_MUL, LWNAF, Chosen binary elliptic curve point multiplication method.) -AC_DEFINE(EB_FIX, COMBS, Chosen binary elliptic curve point multiplication method.) -AC_DEFINE(EB_SIM, INTER, Chosen binary elliptic curve simulteanous point multiplication method.) - -AC_DEFINE(ED_METHD, "PROJC;LWNAF;COMBS;INTER", Edwards elliptic curve arithmetic method.) -AC_DEFINE(ED_PRECO,, Build precomputation table for generator.) -AC_DEFINE(ED_DEPTH, 4, Width of precomputation table for fixed point methods.) -AC_DEFINE(ED_WIDTH, 4, Width of window processing for unknown point methods.) -AC_DEFINE(ED_ADD, PROJC, Chosen binary elliptic curve coordinate method.) -AC_DEFINE(ED_MUL, LWNAF, Chosen prime elliptic twisted Edwards curve point multiplication method.) -AC_DEFINE(ED_FIX, COMBS, Chosen prime elliptic twisted Edwards curve point multiplication method.) -AC_DEFINE(ED_SIM, INTER, Chosen prime elliptic curve simulteanous point multiplication method.) - -AC_DEFINE(EC_METHD, "PRIME", Chosen elliptic curve cryptography method.) -AC_DEFINE(EC_CUR, PRIME, Chosen elliptic curve type.) - -AC_DEFINE(PP_METHD, "LAZYR;OATEP", Bilinear pairing method.) -AC_DEFINE(PP_EXT, LAZYR, Chosen extension field arithmetic method.) -AC_DEFINE(PP_MAP, OATEP, Chosen pairing method over prime elliptic curves.) - -AC_DEFINE(MD_METHD, "SH256", Choice of hash function.) -AC_DEFINE(MD_MAP, SH256, Chosen hash function.) - -AC_DEFINE(CP_CRT,, Support for faster CRT-based exponentiation in factoring-based cryptosystems.) -AC_DEFINE(CP_RSAPD, PKCS2, Chosen RSA padding method.) - -AC_DEFINE(ALLOC, AUTO, Chosen memory allocation policy.) -AC_DEFINE(RAND, HASHD, Chosen random generator.) -AC_DEFINE(MULTI, PTHREAD, Chosen multithreading API.) -AC_DEFINE(TIMER, CYCLE, Chosen timer.) - -dnl Check for pthread compile/link requirements -AX_PTHREAD - -AC_SEARCH_LIBS([clock_gettime],[rt]) - -if test "$TARGET_OS" != "windows"; then - dnl All windows code is PIC, forcing it on just adds useless compile warnings - AX_CHECK_COMPILE_FLAG([-fPIC], [HARDENED_FLAGS="$HARDENED_FLAGS -fPIC"], [], [[$FLAG_WERROR]]) -fi - -dnl All versions of gcc that we commonly use for building are subject to bug -dnl https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90348. To work around that, set -dnl -fstack-reuse=none for all gcc builds. (Only gcc understands this flag) -AX_CHECK_COMPILE_FLAG([-fstack-reuse=none], [HARDENED_FLAGS="$HARDENED_FLAGS -fstack-reuse=none"], [], [[$FLAG_WERROR]]) -if test "$use_hardening" != "no"; then - use_hardening=yes - AX_CHECK_COMPILE_FLAG([-Wstack-protector], [HARDENED_FLAGS="$HARDENED_FLAGS -Wstack-protector"]) - AX_CHECK_COMPILE_FLAG([-fstack-protector-all], [HARDENED_FLAGS="$HARDENED_FLAGS -fstack-protector-all"], [], [[$FLAG_WERROR]]) - - AX_CHECK_COMPILE_FLAG([-fcf-protection=full], [HARDENED_FLAGS="$HARDENED_FLAGS -fcf-protection=full"], [], [[$FLAG_WERROR]]) - - case $host in - *mingw*) - dnl stack-clash-protection doesn't currently work, and likely should just be skipped for Windows. - dnl See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90458 for more details. - ;; - *) - AX_CHECK_COMPILE_FLAG([-fstack-clash-protection], [HARDENED_FLAGS="$HARDENED_FLAGS -fstack-clash-protection"], [], [[$FLAG_WERROR]]) - ;; - esac - - case $host in - *aarch64*) - AX_CHECK_COMPILE_FLAG([-mbranch-protection=bti], [HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -mbranch-protection=bti"], [], [[$CXXFLAG_WERROR]]) - ;; - esac - - AX_CHECK_LINK_FLAG([-Wl,--enable-reloc-section], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--enable-reloc-section"], [], []) - AX_CHECK_LINK_FLAG([-Wl,--dynamicbase], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--dynamicbase"], [], []) - AX_CHECK_LINK_FLAG([-Wl,--nxcompat], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--nxcompat"], [], []) - AX_CHECK_LINK_FLAG([-Wl,--high-entropy-va], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--high-entropy-va"], [], []) - AX_CHECK_LINK_FLAG([-Wl,-z,relro], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,relro"], [], []) - AX_CHECK_LINK_FLAG([-Wl,-z,now], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,now"], [], []) - AX_CHECK_LINK_FLAG([-Wl,-z,separate-code], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,separate-code"], [], []) - AX_CHECK_LINK_FLAG([-fPIE -pie], [HARDENED_FLAGS="$HARDENED_FLAGS -fPIE"; HARDENED_LDFLAGS="$HARDENED_LDFLAGS -pie"], [], []) -fi - -CORE_CPPFLAGS="$CORE_CPPFLAGS -DHAVE_BUILD_INFO" - -case $host in - *mingw*) - AC_CHECK_LIB([user32], [main], [], [AC_MSG_ERROR([libuser32 missing])]) - AC_CHECK_LIB([shell32], [SHGetSpecialFolderPathW], [], [AC_MSG_ERROR([libshell32 missing])]) - AC_CHECK_LIB([advapi32], [CryptAcquireContextW], [], [AC_MSG_ERROR([libadvapi32 missing])]) - AC_CHECK_LIB([psapi], [GetProcessMemoryInfo], [], [AC_MSG_ERROR([libpsapi missing])]) - AC_CHECK_LIB([bcrypt], [main], [], [AC_MSG_ERROR([libbcrypt missing])]) - - dnl -static is interpreted by libtool, where it has a different meaning. - dnl In libtool-speak, it's -all-static. - AX_CHECK_LINK_FLAG([-static], [LIBTOOL_APP_LDFLAGS="$LIBTOOL_APP_LDFLAGS -all-static"]) - - CORE_CPPFLAGS="$CORE_CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -D_WIN32_WINNT=0x0601 -D_WIN32_IE=0x0501 -DWIN32_LEAN_AND_MEAN" - dnl Prevent the definition of min/max macros. - dnl We always want to use the standard library. - CORE_CPPFLAGS="$CORE_CPPFLAGS -DNOMINMAX" - - dnl libtool insists upon adding -nostdlib and a list of objects/libs to link against. - dnl That breaks our ability to build dll's with static libgcc/libstdc++/libssp. Override - dnl its command here, with the predeps/postdeps removed, and -static inserted. Postdeps are - dnl also overridden to prevent their insertion later. - dnl This should only affect dll's. - archive_cmds_CXX="\$CC -shared \$libobjs \$deplibs \$compiler_flags -static -o \$output_objdir/\$soname \${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker \$lib" - postdeps_CXX= - - dnl We require Windows 7 (NT 6.1) or later - AX_CHECK_LINK_FLAG([-Wl,--major-subsystem-version -Wl,6 -Wl,--minor-subsystem-version -Wl,1], [CORE_LDFLAGS="$CORE_LDFLAGS -Wl,--major-subsystem-version -Wl,6 -Wl,--minor-subsystem-version -Wl,1"], [], []) - ;; - *darwin*) - AX_CHECK_LINK_FLAG([-Wl,-headerpad_max_install_names], [CORE_LDFLAGS="$CORE_LDFLAGS -Wl,-headerpad_max_install_names"], [], []) - CORE_CPPFLAGS="$CORE_CPPFLAGS -DMAC_OSX -DOBJC_OLD_DISPATCH_PROTOTYPES=0" - OBJCXXFLAGS="$CXXFLAGS" - ;; -esac - -dnl These flags are specific to ld64, and may cause issues with other linkers. -dnl For example: GNU ld will interpret -dead_strip as -de and then try and use -dnl "ad_strip" as the symbol for the entry point. -if test "$TARGET_OS" = "darwin"; then - AX_CHECK_LINK_FLAG([-Wl,-dead_strip], [CORE_LDFLAGS="$CORE_LDFLAGS -Wl,-dead_strip"], [], []) - AX_CHECK_LINK_FLAG([-Wl,-dead_strip_dylibs], [CORE_LDFLAGS="$CORE_LDFLAGS -Wl,-dead_strip_dylibs"], [], []) - AX_CHECK_LINK_FLAG([-Wl,-bind_at_load], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-bind_at_load"], [], []) -fi - -dnl Don't allow extended (non-ASCII) symbols in identifiers. This is easier for code review. -AX_CHECK_COMPILE_FLAG([-fno-extended-identifiers], [CORE_FLAGS="$CORE_FLAGS -fno-extended-identifiers"], [], [[$FLAG_WERROR]]) - -AC_LANG_POP([C]) - -AC_MSG_CHECKING([whether to build runtest]) -if test x$use_tests = xyes; then - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi - -AC_MSG_CHECKING([whether to build runbench]) -if test x$use_bench = xyes; then - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi - -AM_CONDITIONAL([TARGET_DARWIN], [test "$TARGET_OS" = "darwin"]) -AM_CONDITIONAL([TARGET_LINUX], [test "$TARGET_OS" = "linux"]) -AM_CONDITIONAL([TARGET_WINDOWS], [test "$TARGET_OS" = "windows"]) - -AM_CONDITIONAL(WITH_BN, test 1 -eq 1) -AM_CONDITIONAL(WITH_FP, test 1 -eq 1) -AM_CONDITIONAL(WITH_FPX, test 1 -eq 1) -AM_CONDITIONAL(WITH_FB, test 1 -eq 1) -AM_CONDITIONAL(WITH_EP, test 1 -eq 1) -AM_CONDITIONAL(WITH_EPX, test 1 -eq 1) -AM_CONDITIONAL(WITH_EB, test 1 -eq 1) -AM_CONDITIONAL(WITH_ED, test 1 -eq 1) -AM_CONDITIONAL(WITH_EC, test 1 -eq 1) -AM_CONDITIONAL(WITH_PP, test 1 -eq 1) -AM_CONDITIONAL(WITH_PC, test 1 -eq 1) -AM_CONDITIONAL(WITH_BC, test 1 -eq 1) -AM_CONDITIONAL(WITH_MD, test 1 -eq 1) -AM_CONDITIONAL(WITH_CP, test 1 -eq 1) -AM_CONDITIONAL(WITH_MPC, test 1 -eq 1) -AM_CONDITIONAL(WITH_DV, test 1 -eq 1) -AM_CONDITIONAL(WITH_FBX, test 1 -eq 1) - -AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" = x"yes"]) -AM_CONDITIONAL([USE_BENCH], [test x"$use_bench" = x"yes"]) -AM_CONDITIONAL([HARDEN], [test "$use_hardening" = "yes"]) -AM_CONDITIONAL([OPTIMIZE], [test "$use_optimizations" = "yes"]) - -AM_CONDITIONAL([ARITH_EASY], [test "$want_backend" = "easy"]) -AM_CONDITIONAL([ARITH_GMP], [test "$want_backend" = "gmp"]) - -AC_SUBST(CPU_ARCH) -AC_SUBST(DEBUG_FLAGS) -AC_SUBST(RAND_PATH, hashd) -AC_SUBST(RELIC_CPPFLAGS) -AC_SUBST(WARN_FLAGS) -AC_SUBST(NOWARN_FLAGS) -AC_SUBST(LIBTOOL_APP_LDFLAGS) -AC_SUBST(HARDENED_FLAGS) -AC_SUBST(HARDENED_LDFLAGS) -AC_SUBST(CORE_LDFLAGS) -AC_SUBST(CORE_CPPFLAGS) -AC_SUBST(CORE_FLAGS) - -AC_SUBST(GMP_LDFLAGS) -AC_SUBST(GMP_CPPFLAGS) -AC_SUBST(GMP_LIBS) - -AC_CONFIG_HEADERS([depends/relic/include/relic_conf.h]) -AC_CONFIG_FILES([Makefile]) - -AC_OUTPUT - -dnl Peplace conflict-prone PACKAGE-prefixed macros with DASHBLS -sed -i.old 's/PACKAGE/DASHBLS/g' depends/relic/include/relic_conf.h -sed -i.old 's/PACKAGE/DASHBLS/g' config.status - -echo -echo "Options used to compile and link:" -echo " target os = $TARGET_OS" -echo " backend = $want_backend" -echo " build bench = $use_tests" -echo " build test = $use_bench" -echo " use debug = $use_debug" -echo " use hardening = $use_hardening" -echo " use optimizations = $use_optimizations" -echo -echo " LDFLAGS = $HARDENED_LDFLAGS $CORE_LDFLAGS $GMP_LDFLAGS" -echo " CFLAGS = $DEBUG_FLAGS $HARDENED_FLAGS $CORE_FLAGS $WARN_FLAGS $NOWARN_FLAGS" -echo " CPPFLAGS = $CORE_CPPFLAGS $GMP_CPPFLAGS" -echo " CXXFLAGS = $DEBUG_FLAGS $HARDENED_FLAGS $CORE_FLAGS $WARN_FLAGS $NOWARN_FLAGS" -echo " PTHREAD_FLAGS = $PTHREAD_CFLAGS $PTHREAD_LIBS" -echo diff --git a/go-bindings/Makefile b/go-bindings/Makefile index dcea3f24f2d3..0c4e33b0e0eb 100644 --- a/go-bindings/Makefile +++ b/go-bindings/Makefile @@ -12,23 +12,6 @@ BUILD_DIR=$(CURDIR)/../build CURR_DIR := $(dir $(MAKEFILE_PATH)) SRC_DIR=$(CURDIR)/../src -GMP_PREFIX := /usr/local - -ifeq ("$(OS)", "Darwin") - ifneq ($(wildcard /opt/local/bin/port),) - GMP_PREFIX := /opt/local - endif - ifeq ("$(ARCH)", "arm64") - ifneq ($(wildcard /opt/homebrew/bin/brew),) - GMP_PREFIX := /opt/homebrew - endif - endif -else ifeq ("$(OS)", "Linux") - ifneq ($(wildcard /home/linuxbrew/.linuxbrew/bin/brew),) - GMP_PREFIX := /home/linuxbrew/.linuxbrew - endif -endif - MIMALLOC_LIB := mimalloc-secure MIMALLOC_LIB_PATH := $(CURR_DIR)../build/depends/mimalloc @@ -36,18 +19,15 @@ ifneq ($(wildcard $(MIMALLOC_LIB_PATH)/libmimalloc-secure-debug.a),) MIMALLOC_LIB := mimalloc-secure-debug endif +# blst is compiled into libdashbls; its headers come from the CMake build CGO_CXXFLAGS ?= "\ --I$(CURR_DIR)../build/depends/relic/include \ +-I$(CURR_DIR)../build/_deps/blst-src/bindings \ -I$(CURR_DIR)../depends/mimalloc/include \ --I$(CURR_DIR)../depends/relic/include \ --I$(CURR_DIR)../include \ --I$(GMP_PREFIX)/include" +-I$(CURR_DIR)../include" CGO_LDFLAGS ?= "\ -L$(CURR_DIR)../build/src -ldashbls \ --L$(MIMALLOC_LIB_PATH) -l$(MIMALLOC_LIB) \ --L$(CURR_DIR)../build/depends/relic/lib -lrelic_s \ --L$(GMP_PREFIX)/lib -lgmp" +-L$(MIMALLOC_LIB_PATH) -l$(MIMALLOC_LIB)" .PHONY: default prepare fmt test cover vet help clean config diff --git a/include/dashbls/bls.hpp b/include/dashbls/bls.hpp index cd6922a58cd6..d9108873511c 100644 --- a/include/dashbls/bls.hpp +++ b/include/dashbls/bls.hpp @@ -40,8 +40,6 @@ class BLS { static bool Init(); static void SetSecureAllocator(Util::SecureAllocCallback allocCb, Util::SecureFreeCallback freeCb); - - static void CheckRelicErrors(bool should_throw = true); }; } // end namespace bls diff --git a/include/dashbls/chaincode.hpp b/include/dashbls/chaincode.hpp index bd3e57b4d779..ecd5db79fd39 100644 --- a/include/dashbls/chaincode.hpp +++ b/include/dashbls/chaincode.hpp @@ -15,19 +15,10 @@ #ifndef SRC_CHAINCODE_HPP_ #define SRC_CHAINCODE_HPP_ +#include #include #include -#include "relic_conf.h" - -#if defined GMP && ARITH == GMP -#include -#endif - - -#include "relic.h" -#include "relic_test.h" - #include "util.hpp" namespace bls { @@ -51,9 +42,8 @@ class ChainCode { ChainCode() {} private: - bn_t chainCode; + std::array chainCode{}; }; } // end namespace bls #endif // SRC_CHAINCODE_HPP_ - diff --git a/include/dashbls/elements.hpp b/include/dashbls/elements.hpp index 95937f62dbc6..cbc4154d5fc4 100644 --- a/include/dashbls/elements.hpp +++ b/include/dashbls/elements.hpp @@ -16,17 +16,12 @@ #define SRC_BLSELEMENTS_HPP_ extern "C" { -#include "relic.h" +#include "blst.h" } -#include "relic_conf.h" -#include "util.hpp" - -#if defined GMP && ARITH == GMP -#include -#endif - #include +#include "util.hpp" + namespace bls { class G1Element; class G2Element; @@ -36,25 +31,27 @@ class G1Element { public: static const size_t SIZE = 48; - G1Element() { - g1_set_infty(p); - } - - static G1Element FromBytes(Bytes bytes, bool fLegacy = false); - static G1Element FromBytesUnchecked(Bytes bytes, bool fLegacy = false); - static G1Element FromByteVector(const std::vector &bytevec, bool fLegacy = false); - static G1Element FromNative(const g1_t element); - static G1Element FromMessage(const std::vector &message, - const uint8_t *dst, - int dst_len); - static G1Element FromMessage(Bytes message, - const uint8_t* dst, - int dst_len); + G1Element() { memset(&p, 0x00, sizeof(blst_p1)); } + + static G1Element FromBytes(Bytes bytes, bool legacy_encoding = false); + static G1Element FromBytesUnchecked(Bytes bytes, bool legacy_encoding = false); + static G1Element FromByteVector(const std::vector &bytevec, bool legacy_encoding = false); + static G1Element FromNative(const blst_p1 &element); + static G1Element FromAffine(const blst_p1_affine &element); + static G1Element FromMessage( + const std::vector &message, + const uint8_t *dst, + size_t dst_len); + static G1Element FromMessage( + Bytes message, + const uint8_t *dst, + size_t dst_len); static G1Element Generator(); bool IsValid() const; void CheckValid() const; - void ToNative(g1_t output) const; + void ToNative(blst_p1 *output) const; + void ToAffine(blst_p1_affine *output) const; G1Element Negate() const; GTElement Pair(const G2Element &b) const; uint32_t GetFingerprint(bool fLegacy = false) const; @@ -65,41 +62,41 @@ class G1Element { friend bool operator==(const G1Element &a, const G1Element &b); friend bool operator!=(const G1Element &a, const G1Element &b); friend std::ostream &operator<<(std::ostream &os, const G1Element &s); - friend G1Element& operator+=(G1Element& a, const G1Element& b); + friend G1Element &operator+=(G1Element &a, const G1Element &b); friend G1Element operator+(const G1Element &a, const G1Element &b); - friend G1Element operator*(const G1Element &a, const bn_t &k); - friend G1Element operator*(const bn_t &k, const G1Element &a); + friend G1Element operator*(const G1Element &a, const blst_scalar &k); + friend G1Element operator*(const blst_scalar &k, const G1Element &a); friend GTElement operator&(const G1Element &a, const G2Element &b); private: - g1_t p; + blst_p1 p; }; class G2Element { public: static const size_t SIZE = 96; - G2Element() { - g2_set_infty(q); - } - - static G2Element FromBytes(Bytes bytes, bool fLegacy = false); - static G2Element FromBytesUnchecked(Bytes bytes, bool fLegacy = false); - static G2Element FromByteVector(const std::vector &bytevec, bool fLegacy = false); - static G2Element FromNative(const g2_t element); - static G2Element FromMessage(const std::vector& message, - const uint8_t* dst, - int dst_len, - bool fLegacy = false); - static G2Element FromMessage(Bytes message, - const uint8_t* dst, - int dst_len, - bool fLegacy = false); + G2Element() { memset(&q, 0x00, sizeof(blst_p2)); } + + static G2Element FromBytes(Bytes bytes, bool legacy_encoding = false); + static G2Element FromBytesUnchecked(Bytes bytes, bool legacy_encoding = false); + static G2Element FromByteVector(const std::vector &bytevec, bool legacy_encoding = false); + static G2Element FromNative(const blst_p2 &element); + static G2Element FromAffine(const blst_p2_affine &element); + static G2Element FromMessage( + const std::vector &message, + const uint8_t *dst, + size_t dst_len, bool legacy_encoding = false); + static G2Element FromMessage( + Bytes message, + const uint8_t *dst, + size_t dst_len, bool legacy_encoding = false); static G2Element Generator(); bool IsValid() const; void CheckValid() const; - void ToNative(g2_t output) const; + void ToNative(blst_p2 *output) const; + void ToAffine(blst_p2_affine *output) const; G2Element Negate() const; GTElement Pair(const G1Element &a) const; std::vector Serialize(bool fLegacy = false) const; @@ -109,22 +106,25 @@ class G2Element { friend bool operator==(G2Element const &a, G2Element const &b); friend bool operator!=(G2Element const &a, G2Element const &b); friend std::ostream &operator<<(std::ostream &os, const G2Element &s); - friend G2Element& operator+=(G2Element& a, const G2Element& b); + friend G2Element &operator+=(G2Element &a, const G2Element &b); friend G2Element operator+(const G2Element &a, const G2Element &b); - friend G2Element operator*(const G2Element &a, const bn_t &k); - friend G2Element operator*(const bn_t &k, const G2Element &a); + friend G2Element operator*(const G2Element &a, const blst_scalar &k); + friend G2Element operator*(const blst_scalar &k, const G2Element &a); private: - g2_t q; + blst_p2 q; }; class GTElement { public: - static const size_t SIZE = 384; + static const size_t SIZE = sizeof(blst_fp12); + static GTElement FromBytes(Bytes bytes); static GTElement FromBytesUnchecked(Bytes bytes); static GTElement FromByteVector(const std::vector &bytevec); - static GTElement FromNative(const gt_t *element); + static GTElement FromNative(const blst_fp12 *element); + static GTElement FromAffine(const blst_p1_affine &element); + static GTElement FromAffine(const blst_p2_affine &element); static GTElement Unity(); // unity void Serialize(uint8_t *buffer) const; @@ -135,10 +135,9 @@ class GTElement { friend bool operator!=(GTElement const &a, GTElement const &b); friend std::ostream &operator<<(std::ostream &os, const GTElement &s); friend GTElement operator*(GTElement &a, GTElement &b); - GTElement &operator=(const GTElement &rhs); private: - gt_t r; + blst_fp12 r; GTElement() {} }; diff --git a/include/dashbls/extendedprivatekey.hpp b/include/dashbls/extendedprivatekey.hpp index aefdbf057257..575256ab9425 100644 --- a/include/dashbls/extendedprivatekey.hpp +++ b/include/dashbls/extendedprivatekey.hpp @@ -15,21 +15,13 @@ #ifndef SRC_EXTENDEDPRIVATEKEY_HPP_ #define SRC_EXTENDEDPRIVATEKEY_HPP_ -#include "relic_conf.h" - #include -#if defined GMP && ARITH == GMP -#include -#endif - #include "chaincode.hpp" #include "elements.hpp" #include "extendedpublickey.hpp" #include "privatekey.hpp" -#include "relic.h" -#include "relic_test.h" namespace bls { /* diff --git a/include/dashbls/extendedpublickey.hpp b/include/dashbls/extendedpublickey.hpp index b44d5c636a3c..c1fbdf7bf0dd 100644 --- a/include/dashbls/extendedpublickey.hpp +++ b/include/dashbls/extendedpublickey.hpp @@ -15,20 +15,12 @@ #ifndef SRC_EXTENDEDPUBLICKEY_HPP_ #define SRC_EXTENDEDPUBLICKEY_HPP_ -#include "relic_conf.h" - #include -#if defined GMP && ARITH == GMP -#include -#endif - #include "chaincode.hpp" #include "elements.hpp" -#include "relic.h" -#include "relic_test.h" namespace bls { diff --git a/include/dashbls/hdkeys.hpp b/include/dashbls/hdkeys.hpp index 629ec5e3d142..1cadd7423b9c 100644 --- a/include/dashbls/hdkeys.hpp +++ b/include/dashbls/hdkeys.hpp @@ -15,16 +15,11 @@ #ifndef SRC_BLSHDKEYS_HPP_ #define SRC_BLSHDKEYS_HPP_ -#include "relic_conf.h" #include -#if defined GMP && ARITH == GMP -#include -#endif - -#include "util.hpp" -#include "privatekey.hpp" #include "hkdf.hpp" +#include "privatekey.hpp" +#include "util.hpp" namespace bls { @@ -32,14 +27,14 @@ class HDKeys { /** * Implements HD keys as specified in EIP2333. **/ - public: +public: static const uint8_t HASH_LEN = 32; static PrivateKey KeyGen(const std::vector& seed) { return KeyGen(Bytes(seed)); } - + static PrivateKey KeyGen(const Bytes& seed) { // KeyGen @@ -56,65 +51,44 @@ class HDKeys { throw std::invalid_argument("Seed size must be at least 32 bytes"); } - // "BLS-SIG-KEYGEN-SALT-" in ascii - const uint8_t saltHkdf[20] = {66, 76, 83, 45, 83, 73, 71, 45, 75, 69, - 89, 71, 69, 78, 45, 83, 65, 76, 84, 45}; + blst_scalar* skBn = Util::SecAlloc(1); + blst_keygen_v3(skBn, seed.begin(), seed.size(), info, infoLen); + uint8_t* skBytes = Util::SecAlloc(32); + blst_bendian_from_scalar(skBytes, skBn); - uint8_t *prk = Util::SecAlloc(32); - uint8_t *ikmHkdf = Util::SecAlloc(seed.size() + 1); - memcpy(ikmHkdf, seed.begin(), seed.size()); - ikmHkdf[seed.size()] = 0; - - const uint8_t L = 48; // `ceil((3 * ceil(log2(r))) / 16)`, where `r` is the - // order of the BLS 12-381 curve - - uint8_t *okmHkdf = Util::SecAlloc(L); - - uint8_t keyInfoHkdf[infoLen + 2]; - memcpy(keyInfoHkdf, info, infoLen); - keyInfoHkdf[infoLen] = 0; // Two bytes for L, 0 and 48 - keyInfoHkdf[infoLen + 1] = L; - - HKDF256::ExtractExpand( - okmHkdf, - L, - ikmHkdf, - seed.size() + 1, - saltHkdf, - 20, - keyInfoHkdf, - infoLen + 2); - - bn_t order; - bn_new(order); - g1_get_ord(order); - - // Make sure private key is less than the curve order - bn_t *skBn = Util::SecAlloc(1); - bn_new(*skBn); - bn_read_bin(*skBn, okmHkdf, L); - bn_mod_basic(*skBn, *skBn, order); - - uint8_t *skBytes = Util::SecAlloc(32); - bn_write_bin(skBytes, 32, *skBn); PrivateKey k = PrivateKey::FromBytes(Bytes(skBytes, 32)); - Util::SecFree(prk); - Util::SecFree(ikmHkdf); Util::SecFree(skBn); - Util::SecFree(okmHkdf); Util::SecFree(skBytes); return k; } - static void IKMToLamportSk(uint8_t* outputLamportSk, const uint8_t* ikm, size_t ikmLen, const uint8_t* salt, size_t saltLen) { + static void IKMToLamportSk( + uint8_t* outputLamportSk, + const uint8_t* ikm, + size_t ikmLen, + const uint8_t* salt, + size_t saltLen) + { // Expands the ikm to 255*HASH_LEN bytes for the lamport sk const uint8_t info[1] = {0}; - HKDF256::ExtractExpand(outputLamportSk, HASH_LEN * 255, ikm, ikmLen, salt, saltLen, info, 0); + HKDF256::ExtractExpand( + outputLamportSk, + HASH_LEN * 255, + ikm, + ikmLen, + salt, + saltLen, + info, + 0); } - static void ParentSkToLamportPK(uint8_t* outputLamportPk, const PrivateKey& parentSk, uint32_t index) { + static void ParentSkToLamportPK( + uint8_t* outputLamportPk, + const PrivateKey& parentSk, + uint32_t index) + { uint8_t* salt = Util::SecAlloc(4); uint8_t* ikm = Util::SecAlloc(HASH_LEN); uint8_t* notIkm = Util::SecAlloc(HASH_LEN); @@ -134,11 +108,15 @@ class HDKeys { uint8_t* lamportPk = Util::SecAlloc(HASH_LEN * 255 * 2); for (size_t i = 0; i < 255; i++) { - Util::Hash256(lamportPk + i * HASH_LEN, lamport0 + i * HASH_LEN, HASH_LEN); + Util::Hash256( + lamportPk + i * HASH_LEN, lamport0 + i * HASH_LEN, HASH_LEN); } - for (size_t i=0; i < 255; i++) { - Util::Hash256(lamportPk + 255 * HASH_LEN + i * HASH_LEN, lamport1 + i * HASH_LEN, HASH_LEN); + for (size_t i = 0; i < 255; i++) { + Util::Hash256( + lamportPk + 255 * HASH_LEN + i * HASH_LEN, + lamport1 + i * HASH_LEN, + HASH_LEN); } Util::Hash256(outputLamportPk, lamportPk, HASH_LEN * 255 * 2); @@ -150,7 +128,8 @@ class HDKeys { Util::SecFree(lamportPk); } - static PrivateKey DeriveChildSk(const PrivateKey& parentSk, uint32_t index) { + static PrivateKey DeriveChildSk(const PrivateKey& parentSk, uint32_t index) + { uint8_t* lamportPk = Util::SecAlloc(HASH_LEN); HDKeys::ParentSkToLamportPK(lamportPk, parentSk, index); std::vector lamportPkVector(lamportPk, lamportPk + HASH_LEN); @@ -159,21 +138,29 @@ class HDKeys { return child; } - static PrivateKey DeriveChildSkUnhardened(const PrivateKey& parentSk, uint32_t index) { + static PrivateKey DeriveChildSkUnhardened( + const PrivateKey& parentSk, + uint32_t index) + { uint8_t* buf = Util::SecAlloc(G1Element::SIZE + 4); uint8_t* digest = Util::SecAlloc(HASH_LEN); - memcpy(buf, parentSk.GetG1Element().Serialize().data(), G1Element::SIZE); + memcpy( + buf, parentSk.GetG1Element().Serialize().data(), G1Element::SIZE); Util::IntToFourBytes(buf + G1Element::SIZE, index); Util::Hash256(digest, buf, G1Element::SIZE + 4); - PrivateKey ret = PrivateKey::Aggregate({parentSk, PrivateKey::FromBytes(Bytes(digest, HASH_LEN), true)}); + PrivateKey ret = PrivateKey::Aggregate( + {parentSk, PrivateKey::FromBytes(Bytes(digest, HASH_LEN), true)}); Util::SecFree(buf); Util::SecFree(digest); return ret; } - static G1Element DeriveChildG1Unhardened(const G1Element& pk, uint32_t index) { + static G1Element DeriveChildG1Unhardened( + const G1Element& pk, + uint32_t index) + { uint8_t* buf = Util::SecAlloc(G1Element::SIZE + 4); uint8_t* digest = Util::SecAlloc(HASH_LEN); memcpy(buf, pk.Serialize().data(), G1Element::SIZE); @@ -181,35 +168,33 @@ class HDKeys { Util::IntToFourBytes(buf + G1Element::SIZE, index); Util::Hash256(digest, buf, G1Element::SIZE + 4); - bn_t nonce, ord; - bn_new(nonce); - bn_zero(nonce); - bn_read_bin(nonce, digest, HASH_LEN); - bn_new(ord); - g1_get_ord(ord); - bn_mod_basic(nonce, nonce, ord); + blst_scalar nonce; + // The digest is big-endian; upstream chia loaded it as little-endian, + // which only worked because operator* reversed the bytes again. + blst_scalar_from_bendian(&nonce, digest); Util::SecFree(buf); Util::SecFree(digest); G1Element gen = G1Element::Generator(); - return pk + gen * nonce; + + return pk + (gen * nonce); } - static G2Element DeriveChildG2Unhardened(const G2Element& pk, uint32_t index) { + static G2Element DeriveChildG2Unhardened( + const G2Element& pk, + uint32_t index) + { uint8_t* buf = Util::SecAlloc(G2Element::SIZE + 4); uint8_t* digest = Util::SecAlloc(HASH_LEN); memcpy(buf, pk.Serialize().data(), G2Element::SIZE); Util::IntToFourBytes(buf + G2Element::SIZE, index); Util::Hash256(digest, buf, G2Element::SIZE + 4); - bn_t nonce, ord; - bn_new(nonce); - bn_zero(nonce); - bn_read_bin(nonce, digest, HASH_LEN); - bn_new(ord); - g1_get_ord(ord); - bn_mod_basic(nonce, nonce, ord); + blst_scalar nonce; + // The digest is big-endian; upstream chia loaded it as little-endian, + // which only worked because operator* reversed the bytes again. + blst_scalar_from_bendian(&nonce, digest); Util::SecFree(buf); Util::SecFree(digest); @@ -218,5 +203,5 @@ class HDKeys { return pk + gen * nonce; } }; -} // end namespace bls +} // end namespace bls #endif // SRC_BLSHDKEYS_HPP_ diff --git a/include/dashbls/hkdf.hpp b/include/dashbls/hkdf.hpp index a7ddc863ebab..e338966dc784 100644 --- a/include/dashbls/hkdf.hpp +++ b/include/dashbls/hkdf.hpp @@ -15,13 +15,7 @@ #ifndef SRC_BLSHKDF_HPP_ #define SRC_BLSHKDF_HPP_ -#include "relic_conf.h" #include - -#if defined GMP && ARITH == GMP -#include -#endif - #include #include "util.hpp" @@ -40,12 +34,11 @@ class HKDF256 { // assert(ikm_len == 32); // Used for EIP2333 key derivation // Hash256 used as the hash function (sha256) // PRK Output is 32 bytes (HashLen) - md_hmac(prk_output, ikm, ikm_len, salt, saltLen); + Util::md_hmac(prk_output, ikm, ikm_len, salt, saltLen); } static void Expand(uint8_t* okm, size_t L, const uint8_t* prk, const uint8_t* info, const size_t infoLen) { assert(L <= 255 * HASH_LEN); // L <= 255 * HashLen - assert(infoLen >= 0); size_t N = (L + HASH_LEN - 1) / HASH_LEN; // Round up size_t bytesWritten = 0; @@ -59,12 +52,12 @@ class HKDF256 { if (i == 1) { memcpy(hmacInput1, info, infoLen); hmacInput1[infoLen] = i; - md_hmac(T, hmacInput1, infoLen + 1, prk, HASH_LEN); + Util::md_hmac(T, hmacInput1, infoLen + 1, prk, HASH_LEN); } else { memcpy(hmacInput, T, HASH_LEN); memcpy(hmacInput + HASH_LEN, info, infoLen); hmacInput[HASH_LEN + infoLen] = i; - md_hmac(T, hmacInput, HASH_LEN + infoLen + 1, prk, HASH_LEN); + Util::md_hmac(T, hmacInput, HASH_LEN + infoLen + 1, prk, HASH_LEN); } size_t to_write = L - bytesWritten; if (to_write > HASH_LEN) { diff --git a/include/dashbls/legacy.hpp b/include/dashbls/legacy.hpp index b3e1ee1345f1..30621760694b 100644 --- a/include/dashbls/legacy.hpp +++ b/include/dashbls/legacy.hpp @@ -5,27 +5,24 @@ #ifndef SRC_LEGACY_HPP_ #define SRC_LEGACY_HPP_ -#include - -#include "relic_conf.h" - -#if defined GMP && ARITH == GMP -#include -#endif - extern "C" { -#include "relic.h" +#include "blst.h" } +#include + +namespace bls { /** * Maps a byte array to a point in an elliptic curve over a quadratic extension. * - * Called ep2_map() in old relic version, _legacy prefix is to avoid duplicated symbols + * Called ep2_map() in old relic version. Now reimplemented on blst and must stay + * bit-for-bit compatible: pre-v19 (legacy scheme) consensus depends on it. * - * @param[out] p - the result. - * @param[in] msg - the byte array to map. - * @param[in] len - the array length in bytes. + * @param[out] p - the result. + * @param[in] msg - the byte array to map (must be 32 bytes). + * @param[in] len - the array length in bytes (must be 32). */ -void ep2_map_legacy(ep2_t p, const uint8_t *msg, int len); +void ep2_map_legacy(blst_p2 *p, const uint8_t *msg, size_t len); +} // namespace bls #endif // #define SRC_LEGACY_HPP_ diff --git a/include/dashbls/privatekey.hpp b/include/dashbls/privatekey.hpp index d02a7d292c12..a85051da59b5 100644 --- a/include/dashbls/privatekey.hpp +++ b/include/dashbls/privatekey.hpp @@ -15,12 +15,6 @@ #ifndef SRC_BLSPRIVATEKEY_HPP_ #define SRC_BLSPRIVATEKEY_HPP_ -#include "relic_conf.h" - -#if defined GMP && ARITH == GMP -#include -#endif - #include "elements.hpp" namespace bls { @@ -34,9 +28,6 @@ class PrivateKey { // Construct a private key from a BIP32 based seed. static PrivateKey FromSeedBIP32(const Bytes& seed); - // Construct a random private key. - static PrivateKey RandomPrivateKey(); - // Construct a private key from a bytearray. static PrivateKey FromBytes(const Bytes& bytes, bool modOrder = false); @@ -76,13 +67,13 @@ class PrivateKey { friend G2Element operator*(const G2Element &a, const PrivateKey &k); friend G2Element operator*(const PrivateKey &k, const G2Element &a); - friend PrivateKey operator*(const PrivateKey& a, const bn_t& k); - friend PrivateKey operator*(const bn_t& k, const PrivateKey& a); + friend PrivateKey operator*(const PrivateKey& a, const blst_scalar& k); + friend PrivateKey operator*(const blst_scalar& k, const PrivateKey& a); // Serialize the key into bytes void Serialize(uint8_t *buffer) const; - std::vector Serialize(bool fLegacy = false) const; - std::array SerializeToArray(bool fLegacy = false) const; + std::vector Serialize() const; + std::array SerializeToArray() const; G2Element SignG2( const uint8_t *msg, @@ -105,7 +96,7 @@ class PrivateKey { void InvalidateCaches(); // The actual byte data - bn_st* keydata{nullptr}; + blst_scalar* keydata{nullptr}; mutable bool fG1CacheValid{false}; mutable G1Element g1Cache; diff --git a/include/dashbls/schemes.hpp b/include/dashbls/schemes.hpp index 1aee61dd346d..a7dbdf2b2ce3 100644 --- a/include/dashbls/schemes.hpp +++ b/include/dashbls/schemes.hpp @@ -1,14 +1,14 @@ // Copyright 2020 Chia Network Inc // Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in coiance with the License. +// you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or iied. +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. @@ -19,12 +19,6 @@ #include #include -#include "relic_conf.h" - -#if defined GMP && ARITH == GMP -#include -#endif - #include "elements.hpp" #include "privatekey.hpp" @@ -36,7 +30,6 @@ namespace bls { class Bytes; class CoreMPL { - public: CoreMPL() = delete; CoreMPL(const std::string& strId) : strCiphersuiteId(strId) {} @@ -47,31 +40,42 @@ class CoreMPL { virtual PrivateKey KeyGen(const Bytes& seed); // Generates a public key from a secret key - virtual vector SkToPk(const PrivateKey &seckey); + virtual vector SkToPk(const PrivateKey& seckey); - virtual G1Element SkToG1(const PrivateKey &seckey); + virtual G1Element SkToG1(const PrivateKey& seckey); - virtual G2Element Sign(const PrivateKey &seckey, const vector &message); + virtual G2Element Sign( + const PrivateKey& seckey, + const vector& message); virtual G2Element Sign(const PrivateKey& seckey, const Bytes& message); - virtual bool Verify(const vector &pubkey, - const vector &message, - const vector &signature); + virtual bool Verify( + const vector& pubkey, + const vector& message, + const vector& signature); - virtual bool Verify(const Bytes& pubkey, const Bytes& message, const Bytes& signature); + virtual bool Verify( + const Bytes& pubkey, + const Bytes& message, + const Bytes& signature); - virtual bool Verify(const G1Element &pubkey, - const vector &message, - const G2Element &signature); + virtual bool Verify( + const G1Element& pubkey, + const vector& message, + const G2Element& signature); - virtual bool Verify(const G1Element& pubkey, const Bytes& message, const G2Element& signature); + virtual bool Verify( + const G1Element& pubkey, + const Bytes& message, + const G2Element& signature); - virtual std::array Aggregate(const vector> &signatures); + virtual std::array Aggregate( + const vector>& signatures); virtual std::array Aggregate(const vector& signatures); - virtual G2Element Aggregate(const vector &signatures); + virtual G2Element Aggregate(const vector& signatures); - virtual G1Element Aggregate(const vector &publicKeys); + virtual G1Element Aggregate(const vector& publicKeys); virtual G2Element AggregateSecure(const std::vector& vecPublicKeys, const std::vector& vecSignatures, @@ -81,21 +85,25 @@ class CoreMPL { const G2Element& signature, const Bytes& message); - virtual bool AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature); + virtual bool AggregateVerify( + const vector>& pubkeys, + const vector>& messages, + const vector& signature); - virtual bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const Bytes& signature); + virtual bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const Bytes& signature); - virtual bool AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature); + virtual bool AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature); - virtual bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const G2Element& signature); + virtual bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature); PrivateKey DeriveChildSk(const PrivateKey& sk, uint32_t index); PrivateKey DeriveChildSkUnhardened(const PrivateKey& sk, uint32_t index); @@ -103,7 +111,8 @@ class CoreMPL { protected: const std::string& strCiphersuiteId; - bool NativeVerify(g1_t *pubKeys, g2_t *mappedHashes, size_t length); + static bool NativeVerify(const std::vector& g1s, + const std::vector& g2s); G2Element AggregateSecure(std::vector const &vecPublicKeys, std::vector const &vecSignatures, const Bytes& message, @@ -118,106 +127,127 @@ class BasicSchemeMPL final : public CoreMPL { public: static const std::string CIPHERSUITE_ID; BasicSchemeMPL() : CoreMPL(BasicSchemeMPL::CIPHERSUITE_ID) {} - bool AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature) override; - - bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const Bytes& signature) override; - - bool AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature) override; - - bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const G2Element& signature) override; + bool AggregateVerify( + const vector>& pubkeys, + const vector>& messages, + const vector& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const Bytes& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature) override; }; class AugSchemeMPL final : public CoreMPL { - public: static const std::string CIPHERSUITE_ID; AugSchemeMPL() : CoreMPL(AugSchemeMPL::CIPHERSUITE_ID) {} - G2Element Sign(const PrivateKey &seckey, const vector &message) override; + G2Element Sign(const PrivateKey& seckey, const vector& message) + override; G2Element Sign(const PrivateKey& seckey, const Bytes& message) override; // Used for prepending different augMessage - G2Element Sign(const PrivateKey &seckey, - const vector &message, - const G1Element &prepend_pk); + G2Element Sign( + const PrivateKey& seckey, + const vector& message, + const G1Element& prepend_pk); // Used for prepending different augMessage - G2Element Sign(const PrivateKey& seckey, - const Bytes& message, - const G1Element& prepend_pk); - - bool Verify(const vector &pubkey, - const vector &message, - const vector &signature) override; - - bool Verify(const Bytes& pubkey, - const Bytes& message, - const Bytes& signature) override; - - bool Verify(const G1Element &pubkey, - const vector &message, - const G2Element &signature) override; - - bool Verify(const G1Element& pubkey, - const Bytes& message, - const G2Element& signature) override; + G2Element Sign( + const PrivateKey& seckey, + const Bytes& message, + const G1Element& prepend_pk); + + bool Verify( + const vector& pubkey, + const vector& message, + const vector& signature) override; + + bool Verify( + const Bytes& pubkey, + const Bytes& message, + const Bytes& signature) override; + + bool Verify( + const G1Element& pubkey, + const vector& message, + const G2Element& signature) override; + + bool Verify( + const G1Element& pubkey, + const Bytes& message, + const G2Element& signature) override; + + bool AggregateVerify( + const vector>& pubkeys, + const vector>& messages, + const vector& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const Bytes& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature) override; + + bool AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature) override; - bool AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature) override; - - bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const Bytes& signature) override; - - bool AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature) override; - - bool AggregateVerify(const vector& pubkeys, - const vector& messages, - const G2Element& signature) override; + bool VerifySecure(const std::vector& vecPublicKeys, + const G2Element& signature, + const Bytes& message) override; }; class PopSchemeMPL final : public CoreMPL { - public: static const std::string CIPHERSUITE_ID; static const std::string POP_CIPHERSUITE_ID; PopSchemeMPL() : CoreMPL(PopSchemeMPL::CIPHERSUITE_ID) {} - G2Element PopProve(const PrivateKey &seckey); + G2Element PopProve(const PrivateKey& seckey); - bool PopVerify(const G1Element &pubkey, const G2Element &signature_proof); + bool PopVerify(const G1Element& pubkey, const G2Element& signature_proof); - bool PopVerify(const vector &pubkey, const vector &proof); + bool PopVerify(const vector& pubkey, const vector& proof); bool PopVerify(const Bytes& pubkey, const Bytes& proof); - bool FastAggregateVerify(const vector &pubkeys, - const vector &message, - const G2Element &signature); - - bool FastAggregateVerify(const vector& pubkeys, - const Bytes& message, - const G2Element& signature); - - bool FastAggregateVerify(const vector> &pubkeys, - const vector &message, - const vector &signature); - - bool FastAggregateVerify(const vector& pubkeys, - const Bytes& message, - const Bytes& signature); + bool FastAggregateVerify( + const vector& pubkeys, + const vector& message, + const G2Element& signature); + + bool FastAggregateVerify( + const vector& pubkeys, + const Bytes& message, + const G2Element& signature); + + bool FastAggregateVerify( + const vector>& pubkeys, + const vector& message, + const vector& signature); + + bool FastAggregateVerify( + const vector& pubkeys, + const Bytes& message, + const Bytes& signature); }; /** @@ -228,23 +258,23 @@ class LegacySchemeMPL final : public CoreMPL { public: LegacySchemeMPL() : CoreMPL(std::string{}) {} - virtual vector SkToPk(const PrivateKey &seckey) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + virtual vector SkToPk(const PrivateKey &) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } - G2Element Sign(const PrivateKey &seckey, const vector &message) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + G2Element Sign(const PrivateKey &, const vector &) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } G2Element Sign(const PrivateKey &seckey, const Bytes& message) final; - bool Verify(const vector& pubkey, - const vector& message, - const vector& signature) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + bool Verify(const vector&, + const vector&, + const vector&) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } - bool Verify(const G1Element& pubkey, - const vector& message, - const G2Element& signature) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + bool Verify(const G1Element&, + const vector&, + const G2Element&) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } - bool Verify(const Bytes& pubkey, const Bytes& message, const Bytes& signature) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + bool Verify(const Bytes&, const Bytes&, const Bytes&) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } bool Verify(const G1Element &pubkey, const Bytes& message, const G2Element &signature) final; - std::array Aggregate(const vector> &signatures) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + std::array Aggregate(const vector> &) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } G2Element AggregateSecure(const std::vector& vecPublicKeys, const std::vector& vecSignatures, @@ -254,17 +284,17 @@ class LegacySchemeMPL final : public CoreMPL { const G2Element& signature, const Bytes& message) final; - bool AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + bool AggregateVerify(const vector> &, + const vector> &, + const vector &) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } - bool AggregateVerify(const vector &pubkeys, - const vector &messages, - const Bytes &signature) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + bool AggregateVerify(const vector &, + const vector &, + const Bytes &) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } - bool AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } + bool AggregateVerify(const vector &, + const vector> &, + const G2Element &) final { throw std::runtime_error("Not supported in LegacySchemeMPL"); } bool AggregateVerify(const vector &pubkeys, const vector &messages, diff --git a/include/dashbls/test-utils.hpp b/include/dashbls/test-utils.hpp index 154079ff4a99..237940c87c1c 100644 --- a/include/dashbls/test-utils.hpp +++ b/include/dashbls/test-utils.hpp @@ -47,10 +47,10 @@ void endStopwatch(string testName, std::vector getRandomSeed() { uint8_t buf[32]; - bn_t r; - bn_new(r); - bn_rand(r, RLC_POS, 256); - bn_write_bin(buf, 32, r); + + for (int i = 0; i < 32; i++) + buf[i] = rand (); + std::vector ret(buf, buf + 32); return ret; } diff --git a/include/dashbls/util.hpp b/include/dashbls/util.hpp index 37fd8547a983..02ec7b3877a7 100644 --- a/include/dashbls/util.hpp +++ b/include/dashbls/util.hpp @@ -19,9 +19,14 @@ #include #include #include +#include #include #include +extern "C" { +#include "blst.h" +} + namespace bls { class BLS; @@ -60,8 +65,41 @@ class Util { public: static void Hash256(uint8_t* output, const uint8_t* message, size_t messageLen) { - md_map_sh256(output, message, messageLen); + blst_sha256(output, message, messageLen); + } + +static void md_hmac(uint8_t *mac, const uint8_t *in, size_t in_len, const uint8_t *key, + size_t key_len) { + constexpr size_t block_size = 64; + constexpr size_t md_len = 32; + // The pads and the padded key are derived from the key, so they live in + // the same secure memory as the private keys (see SecAlloc). + uint8_t *buf = SecAlloc(block_size + md_len + block_size + in_len + block_size); + if (buf == NULL) + throw std::runtime_error("out of memory"); + uint8_t *opad = buf; // block_size + md_len + uint8_t *ipad = opad + block_size + md_len; // block_size + in_len + uint8_t *_key = ipad + block_size + in_len; // block_size + + if (key_len > block_size) { + Hash256(_key, key, key_len); + key_len = md_len; + } else { + memcpy(_key, key, key_len); } + memset(_key + key_len, 0, block_size - key_len); + key = _key; + + for (size_t i = 0; i < block_size; i++) { + opad[i] = 0x5C ^ key[i]; + ipad[i] = 0x36 ^ key[i]; + } + memcpy(ipad + block_size, in, in_len); + Hash256(opad + block_size, ipad, block_size + in_len); + Hash256(mac, opad, block_size + md_len); + + SecFree(buf); +} static std::string HexStr(const uint8_t* data, size_t len) { std::stringstream s; @@ -80,8 +118,8 @@ class Util { } /* - * Securely allocates a portion of memory, using libsodium. This prevents - * paging to disk, and zeroes out the memory when it's freed. + * Securely allocates a portion of memory. This prevents paging to disk, + * and zeroes out the memory when it's freed. */ template static T* SecAlloc(size_t numTs) { diff --git a/js-bindings/CMakeLists.txt b/js-bindings/CMakeLists.txt index 5790f3a11619..86660a01a011 100644 --- a/js-bindings/CMakeLists.txt +++ b/js-bindings/CMakeLists.txt @@ -5,8 +5,6 @@ include_directories( ${INCLUDE_DIRECTORIES} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../include - ${CMAKE_CURRENT_SOURCE_DIR}/../depends/relic/include - ${CMAKE_CURRENT_BINARY_DIR}/../depends/relic/include ${CMAKE_CURRENT_SOURCE_DIR}/../depends/catch2/include ) diff --git a/js-bindings/blsjs.d.ts b/js-bindings/blsjs.d.ts index 95cb05962ad1..556a2a8edaaf 100644 --- a/js-bindings/blsjs.d.ts +++ b/js-bindings/blsjs.d.ts @@ -48,7 +48,6 @@ export declare class G1Element { deepcopy(): G1Element; getFingerprint(): number; add(el: G1Element): G1Element; - mul(bn: Bignum): G1Element; equalTo(el: G1Element): boolean; delete(): void; } @@ -63,7 +62,6 @@ export declare class G2Element { negate(): G2Element; deepcopy(): G2Element; add(el: G2Element): G2Element; - mul(bn: Bignum): G2Element; equalTo(el: G2Element): boolean; delete(): void; } @@ -82,12 +80,6 @@ export declare class PrivateKey { delete(): void; } -export declare class Bignum { - static fromString(s: string, radix: number): Bignum; - toString(radix: number): string; - delete(): void; -} - export declare class Util { static hash256(msg: Uint8Array): Uint8Array; static hexStr(msg: Uint8Array): string; @@ -100,7 +92,6 @@ export interface ModuleInstance { G1Element: typeof G1Element; G2Element: typeof G2Element; PrivateKey: typeof PrivateKey; - Bignum: typeof Bignum; Util: typeof Util; } diff --git a/js-bindings/helpers.cpp b/js-bindings/helpers.cpp index e58f5e4909f2..41a92a0a2e41 100644 --- a/js-bindings/helpers.cpp +++ b/js-bindings/helpers.cpp @@ -26,12 +26,6 @@ namespace helpers { return buffer; } - val toUint8Array(bn_t bn) { - std::vector vec = toVector(bn); - val buffer = toUint8Array(vec); - return buffer; - } - std::vector toVector(uint8_t *pointer, size_t data_size) { std::vector data; data.reserve(data_size); @@ -48,13 +42,6 @@ namespace helpers { return vec; } - std::vector toVector(bn_t bn) { - uint8_t buf[bn_size_bin(bn)]; - bn_write_bin(buf, bn_size_bin(bn), bn); - std::vector vec = helpers::toVector(buf, bn_size_bin(bn)); - return vec; - } - std::vector> jsBuffersArrayToVector(val buffersArray) { auto l = buffersArray["length"].as(); std::vector> vec; @@ -64,20 +51,6 @@ namespace helpers { return vec; } - std::vector jsBuffersArrayToBnVector(val buffersArray) { - auto l = buffersArray["length"].as(); - std::vector vec; - for (unsigned i = 0; i < l; ++i) { - bn_t data; - bn_new(data); - std::vector bnVec = toVector(buffersArray[i]); - bn_read_bin(data, bnVec.data(), static_cast(bnVec.size())); - bn_t *point = &data; - vec.push_back(point); - } - return vec; - } - val byteArraysVectorToJsBuffersArray(std::vector arraysVector, size_t element_size) { auto vecSize = arraysVector.size(); std::vector valVector; diff --git a/js-bindings/helpers.h b/js-bindings/helpers.h index 031df07043dc..faf2976e3e31 100644 --- a/js-bindings/helpers.h +++ b/js-bindings/helpers.h @@ -18,9 +18,6 @@ #include #include #include -extern "C" { -#include -} #include using namespace emscripten; @@ -31,14 +28,10 @@ namespace helpers { val toUint8Array(std::vector vec); - val toUint8Array(bn_t bn); - std::vector toVector(uint8_t *pointer, size_t data_size); std::vector toVector(val jsBuffer); - std::vector toVector(bn_t bn); - template inline std::vector toVectorFromJSArray(val jsArray) { auto l = jsArray["length"].as(); @@ -62,8 +55,6 @@ namespace helpers { std::vector> jsBuffersArrayToVector(val buffersArray); - std::vector jsBuffersArrayToBnVector(val buffersArray); - val byteArraysVectorToJsBuffersArray(std::vector arraysVector, size_t element_size); } // namespace helpers diff --git a/js-bindings/jsbindings.cpp b/js-bindings/jsbindings.cpp index 81daa4abc74e..6e9d45f1160b 100644 --- a/js-bindings/jsbindings.cpp +++ b/js-bindings/jsbindings.cpp @@ -70,7 +70,6 @@ EMSCRIPTEN_BINDINGS(blsjs) { .function("deepcopy", &G1ElementWrapper::Deepcopy) .function("getFingerprint", &G1ElementWrapper::GetFingerprint) .function("add", &G1ElementWrapper::Add) - .function("mul", &G1ElementWrapper::Mul) .function("equalTo", &G1ElementWrapper::EqualTo); class_("G2Element") @@ -84,7 +83,6 @@ EMSCRIPTEN_BINDINGS(blsjs) { .function("negate", &G2ElementWrapper::Negate) .function("deepcopy", &G2ElementWrapper::Deepcopy) .function("add", &G2ElementWrapper::Add) - .function("mul", &G2ElementWrapper::Mul) .function("equalTo", &G2ElementWrapper::EqualTo); class_("PrivateKey") @@ -99,10 +97,6 @@ EMSCRIPTEN_BINDINGS(blsjs) { .function("mulG2", &PrivateKeyWrapper::MulG2) .function("equalTo", &PrivateKeyWrapper::EqualTo); - class_("Bignum") - .class_function("fromString", &BignumWrapper::FromString) - .function("toString", &BignumWrapper::ToString); - class_("Util") .class_function("hash256", &UtilWrapper::Hash256) .class_function("hexStr", &UtilWrapper::HexStr); diff --git a/js-bindings/tests/test.js b/js-bindings/tests/test.js index 34671d6546b7..7c1455932f4f 100644 --- a/js-bindings/tests/test.js +++ b/js-bindings/tests/test.js @@ -22,7 +22,6 @@ blsjs().then((blsjs) => { const modules = [ 'AugSchemeMPL', 'BasicSchemeMPL', - "Bignum", 'G1Element', 'G2Element', 'PopSchemeMPL', @@ -42,7 +41,6 @@ blsjs().then((blsjs) => { const { AugSchemeMPL, BasicSchemeMPL, - Bignum, G1Element, G2Element, PopSchemeMPL, @@ -380,17 +378,11 @@ blsjs().then((blsjs) => { assert(AugSchemeMPL.aggregateVerify([], [], new G2Element())); } - function testBignum() { - const mersenne = Bignum.fromString('162259276829213363391578010288127', 10); - assert(mersenne.toString(16).toLowerCase() == '7ffffffffffffffffffffffffff'); - } - testSchemes(); testVectorsInvalid(); testVectorsValid(); testReadme(); testAggregateVerifyZeroItems(); - testBignum(); }).then(function() { console.log("\nAll tests passed."); }); diff --git a/js-bindings/wrappers/BignumWrapper.cpp b/js-bindings/wrappers/BignumWrapper.cpp deleted file mode 100644 index 26fea069a0ff..000000000000 --- a/js-bindings/wrappers/BignumWrapper.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2020 Chia Network Inc - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 - -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include "BignumWrapper.h" - -namespace js_wrappers { -Bignum::Bignum() { - bn_make(&content, 1); -} - -Bignum::~Bignum() { - bn_clean(&content); -} - -Bignum::Bignum(const Bignum &other) { - bn_copy(&content, &other.content); -} - -bn_st *Bignum::operator &() { return &content; } - -BignumWrapper::BignumWrapper(const Bignum &bn) : JSWrapper(bn) {} - -BignumWrapper BignumWrapper::FromString(const std::string &s, int radix) { - Bignum result; - bn_read_str(&result, s.c_str(), s.size(), radix); - return BignumWrapper(result); -} - -std::string BignumWrapper::ToString(int radix) { - auto wrapper = GetWrappedInstance(); - int strsize = bn_size_str(&wrapper, radix); - std::vector strholder(strsize); - bn_write_str(&strholder[0], strsize, &wrapper, radix); - return std::string(&strholder[0], strsize - 1); -} -} // namespace js_wrappers diff --git a/js-bindings/wrappers/BignumWrapper.h b/js-bindings/wrappers/BignumWrapper.h deleted file mode 100644 index 337d52702506..000000000000 --- a/js-bindings/wrappers/BignumWrapper.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Chia Network Inc - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 - -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef JS_BINDINGS_WRAPPERS_BIGNUMWRAPPER_H_ -#define JS_BINDINGS_WRAPPERS_BIGNUMWRAPPER_H_ - -#include -#include "JSWrapper.h" - -namespace js_wrappers { -class Bignum { -public: - Bignum(); - ~Bignum(); - Bignum(const Bignum &other); - - bn_st *operator &(); - -private: - bn_st content; -}; - -class BignumWrapper : public JSWrapper { -public: - explicit BignumWrapper(const Bignum &bn); - static BignumWrapper FromString(const std::string &s, int radix); - std::string ToString(int radix); -}; -} // namespace js_wrappers - -#endif // JS_BINDINGS_WRAPPERS_SIGNATUREWRAPPER_H_ diff --git a/js-bindings/wrappers/G1ElementWrapper.cpp b/js-bindings/wrappers/G1ElementWrapper.cpp index 0d630514886b..f623a5062173 100644 --- a/js-bindings/wrappers/G1ElementWrapper.cpp +++ b/js-bindings/wrappers/G1ElementWrapper.cpp @@ -44,16 +44,6 @@ G1ElementWrapper G1ElementWrapper::Add(const G1ElementWrapper &other) { return G1ElementWrapper(GetWrappedInstance() + other.GetWrappedInstance()); } -G1ElementWrapper G1ElementWrapper::Mul(const BignumWrapper &other) { - bn_t factor; - // Since the type of bn_t is bn_st[0], we can do this dance to make a temporary - // copy of the struct itself to hand to G1ElementWrapper's multiply. The - // type was clearly intended to by by-value in argument lists (degrade to ptr) - // but value semantics in C++ complicates matters. - factor[0] = *(&other.GetWrappedInstance()); - return G1ElementWrapper(GetWrappedInstance() * factor); -} - bool G1ElementWrapper::EqualTo(const G1ElementWrapper &others) { return GetWrappedInstance() == others.GetWrappedInstance(); } diff --git a/js-bindings/wrappers/G1ElementWrapper.h b/js-bindings/wrappers/G1ElementWrapper.h index 1b5a0f8282a7..e7185c5237a9 100644 --- a/js-bindings/wrappers/G1ElementWrapper.h +++ b/js-bindings/wrappers/G1ElementWrapper.h @@ -17,7 +17,6 @@ #include #include "JSWrapper.h" -#include "BignumWrapper.h" namespace js_wrappers { class G1ElementWrapper : public JSWrapper { @@ -38,8 +37,6 @@ class G1ElementWrapper : public JSWrapper { G1ElementWrapper Add(const G1ElementWrapper &other); - G1ElementWrapper Mul(const BignumWrapper &other); - bool EqualTo(const G1ElementWrapper &others); G1ElementWrapper Negate(); diff --git a/js-bindings/wrappers/G2ElementWrapper.cpp b/js-bindings/wrappers/G2ElementWrapper.cpp index 980a7dd8e706..de4a208f5b96 100644 --- a/js-bindings/wrappers/G2ElementWrapper.cpp +++ b/js-bindings/wrappers/G2ElementWrapper.cpp @@ -67,16 +67,6 @@ G2ElementWrapper G2ElementWrapper::Add(const G2ElementWrapper& other) { return G2ElementWrapper(GetWrappedInstance() + other.GetWrappedInstance()); } -G2ElementWrapper G2ElementWrapper::Mul(const BignumWrapper& other) { - bn_t factor; - // Since the type of bn_t is bn_st[0], we can do this dance to make a - // temporary copy of the struct itself to hand to G2ElementWrapper's - // multiply. The type was clearly intended to by by-value in argument lists - // (degrade to ptr) but value semantics in C++ complicates matters. - factor[0] = *(&other.GetWrappedInstance()); - return G2ElementWrapper(GetWrappedInstance() * factor); -} - bool G2ElementWrapper::EqualTo(const G2ElementWrapper& others) { return GetWrappedInstance() == others.GetWrappedInstance(); } diff --git a/js-bindings/wrappers/G2ElementWrapper.h b/js-bindings/wrappers/G2ElementWrapper.h index 46f23f6ca826..829affd2ab79 100644 --- a/js-bindings/wrappers/G2ElementWrapper.h +++ b/js-bindings/wrappers/G2ElementWrapper.h @@ -17,7 +17,6 @@ #include #include "JSWrapper.h" -#include "BignumWrapper.h" namespace js_wrappers { class G2ElementWrapper : public JSWrapper { @@ -46,8 +45,6 @@ class G2ElementWrapper : public JSWrapper { G2ElementWrapper Add(const G2ElementWrapper &other); - G2ElementWrapper Mul(const BignumWrapper &other); - bool EqualTo(const G2ElementWrapper &others); }; } // namespace js_wrappers diff --git a/pyproject.toml b/pyproject.toml index c9b5e5526393..a427ccb8e03e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,13 +47,9 @@ test-requires = [ ] [tool.cibuildwheel.linux] -before-all = "dnf -y install gmp-devel" manylinux-aarch64-image = "manylinux_2_28" manylinux-x86_64-image = "manylinux_2_28" -[tool.cibuildwheel.macos] -environment = { CMAKE_ARGS = "-DARITH=easy" } - [tool.pytest.ini_options] testpaths = ["binds/python"] addopts = "--benchmark-skip" diff --git a/rust-bindings/bls-dash-sys/build.rs b/rust-bindings/bls-dash-sys/build.rs index 0570baaa89b0..c514df3125a6 100644 --- a/rust-bindings/bls-dash-sys/build.rs +++ b/rust-bindings/bls-dash-sys/build.rs @@ -138,13 +138,9 @@ fn main() { .collect(); include_paths.extend([ - bls_dash_build_path.join("depends/relic-src/include"), - bls_dash_build_path.join("depends/relic/include"), bls_dash_build_path.join("src"), root_path.join("include/dashbls"), - bls_dash_build_path.join("depends/relic/include"), bls_dash_build_path.join("depends/mimalloc/include"), - root_path.join("depends/relic/include"), root_path.join("depends/mimalloc/include"), bls_dash_src_path.clone(), ]); @@ -186,21 +182,6 @@ fn main() { cc.compile("bls-dash-sys"); - // // Link dependencies - // println!( - // "cargo:rustc-link-search={}", - // bls_dash_build_path.join("_deps/sodium-build").display() - // ); - - // println!("cargo:rustc-link-lib=static=sodium"); - - println!( - "cargo:rustc-link-search={}", - root_path.join("build/depends/relic/lib").display() - ); - - println!("cargo:rustc-link-lib=static=relic_s"); - let mimalloc_dir = root_path.join("build/depends/mimalloc"); println!("cargo:rustc-link-search={}", mimalloc_dir.display()); let mimalloc_lib = if mimalloc_dir.join("libmimalloc-secure-debug.a").exists() { @@ -217,26 +198,6 @@ fn main() { println!("cargo:rustc-link-lib=static=dashbls"); - // Link GMP if exists - let gmp_libraries_file_path = bls_dash_build_path.join("gmp_libraries.txt"); - - if gmp_libraries_file_path.exists() { - let gmp_libraries_path = PathBuf::from( - fs::read_to_string(gmp_libraries_file_path) - .expect("should read gmp includes from file"), - ); - - let gmp_libraries_parent_path = gmp_libraries_path - .parent() - .expect("can't get gmp libraries parent dir"); - - println!( - "cargo:rustc-link-search={}", - gmp_libraries_parent_path.display() - ); - - println!("cargo:rustc-link-lib=static=gmp"); - } println!("cargo:warning=########## bls_dash_build_path:{}", bls_dash_build_path.display()); // Generate rust code for c binding to src/lib.rs @@ -312,7 +273,6 @@ fn main() { // } // println!("cargo:rustc-link-search={}", target_path.display()); // println!("cargo:rustc-link-lib=static=gmp"); -// println!("cargo:rustc-link-lib=static=sodium"); // println!("cargo:rustc-link-lib=static=relic_s"); // println!("cargo:rustc-link-search={}", bls_dash_build_path.join("src").display()); // println!("cargo:rustc-link-lib=static=bls"); @@ -404,12 +364,8 @@ fn main() { .collect(); include_paths.extend([ - bls_dash_build_path.join(format!("relic-{}-{}/depends/relic-src/include", platform, arch)), - bls_dash_build_path.join(format!("relic-{}-{}/depends/relic/include", platform, arch)), - bls_dash_build_path.join("contrib/relic/src"), root_path.join("src"), root_path.join("include/dashbls"), - root_path.join("depends/relic/include"), root_path.join("depends/mimalloc/include"), root_path.join("depends/catch2/include"), bls_dash_src_path.clone(), @@ -430,16 +386,10 @@ fn main() { .flag("-Wno-delete-non-abstract-non-virtual-dtor") .flag("-std=c++14"); - cc.compile("dashbls"); + cc.compile("bls-dash-sys"); println!("cargo:rustc-link-search={}", target_path.display()); - println!("cargo:rustc-link-lib=static=gmp"); - //println!("cargo:rustc-link-lib=c++"); - //println!("cargo:rustc-link-lib=c"); - //println!("cargo:rustc-link-lib=static=sodium"); - println!("cargo:rustc-link-lib=static=relic_s"); - println!("cargo:rustc-link-lib=static=bls"); - println!("cargo:rustc-link-search={}", bls_dash_src_path.display()); + println!("cargo:rustc-link-lib=static=mimalloc-secure"); println!("cargo:rustc-link-lib=static=dashbls"); println!("cargo:rerun-if-changed={}", bls_dash_src_path.display()); } diff --git a/rust-bindings/bls-dash-sys/c-bindings/schemes.cpp b/rust-bindings/bls-dash-sys/c-bindings/schemes.cpp index bc2e632c8027..96c0d2fa4432 100644 --- a/rust-bindings/bls-dash-sys/c-bindings/schemes.cpp +++ b/rust-bindings/bls-dash-sys/c-bindings/schemes.cpp @@ -324,8 +324,13 @@ G2Element LegacySchemeMPLSign( { bls::LegacySchemeMPL* schemePtr = (bls::LegacySchemeMPL*)scheme; const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk; - return new bls::G2Element( - schemePtr->Sign(*skPtr, bls::Bytes((uint8_t*)msg, msgLen))); + try { + return new bls::G2Element( + schemePtr->Sign(*skPtr, bls::Bytes((uint8_t*)msg, msgLen))); + } catch (const std::exception& ex) { + gErrMsg = ex.what(); + return nullptr; + } } bool LegacySchemeMPLVerify( diff --git a/rust-bindings/bls-signatures/src/schemes.rs b/rust-bindings/bls-signatures/src/schemes.rs index 3019bc0b4aa6..1755bc3549e6 100644 --- a/rust-bindings/bls-signatures/src/schemes.rs +++ b/rust-bindings/bls-signatures/src/schemes.rs @@ -1,9 +1,9 @@ -use std::ffi::c_void; +use std::ffi::{c_void, CStr}; use bls_dash_sys::{ AugSchemeMPLAggregateVerify, AugSchemeMPLFree, AugSchemeMPLSign, AugSchemeMPLVerify, BasicSchemeMPLAggregateVerify, BasicSchemeMPLFree, CoreMPLAggregatePubKeys, - CoreMPLAggregateSigs, CoreMPLSign, CoreMPLVerify, CoreMPLVerifySecure, + CoreMPLAggregateSigs, CoreMPLSign, CoreMPLVerify, CoreMPLVerifySecure, GetLastErrorMsg, LegacySchemeMPLAggregateVerify, LegacySchemeMPLSign, LegacySchemeMPLVerify, LegacySchemeMPLVerifySecure, NewAugSchemeMPL, NewBasicSchemeMPL, NewLegacySchemeMPL, }; @@ -198,16 +198,23 @@ impl Scheme for LegacySchemeMPL { } fn sign(&self, private_key: &PrivateKey, message: &[u8]) -> G2Element { - G2Element { - c_element: unsafe { - LegacySchemeMPLSign( - self.scheme, - private_key.as_mut_ptr(), - message.as_ptr() as *const _, - message.len(), - ) - }, + // The legacy scheme signs 32-byte message hashes; the C++ side throws + // for anything else, and a C++ exception must not cross the FFI. + assert_eq!(message.len(), 32, "the legacy scheme signs a 32-byte message hash"); + let c_element = unsafe { + LegacySchemeMPLSign( + self.scheme, + private_key.as_mut_ptr(), + message.as_ptr() as *const _, + message.len(), + ) + }; + // The C shim returns null when the C++ side threw. + if c_element.is_null() { + let msg = unsafe { CStr::from_ptr(GetLastErrorMsg()) }; + panic!("LegacySchemeMPLSign failed: {}", msg.to_string_lossy()); } + G2Element { c_element } } fn verify(&self, public_key: &G1Element, message: &[u8], signature: &G2Element) -> bool { @@ -383,10 +390,11 @@ mod tests { .g1_element() .expect("unable to get public key"); - let message_1 = b"ayya"; - let message_2 = b"ayyb"; - let message_3 = b"ayyc"; - let message_4 = b"ayyd"; + // 32-byte messages: the legacy scheme only signs message hashes + let message_1 = &[0x11u8; 32]; + let message_2 = &[0x22u8; 32]; + let message_3 = &[0x33u8; 32]; + let message_4 = &[0x44u8; 32]; let signature_1 = scheme.sign(&private_key_1, message_1); let signature_2 = scheme.sign(&private_key_2, message_2); @@ -431,4 +439,42 @@ mod tests { fn verify_aggregate_legacy() { verify_aggregate(LegacySchemeMPL::new()); } + + fn legacy_key_and_signature() -> (LegacySchemeMPL, G1Element, G2Element) { + let scheme = LegacySchemeMPL::new(); + let private_key = PrivateKey::key_gen(&scheme, b"seedweedseedweedseedweedseedweed") + .expect("unable to generate private key"); + let public_key = private_key.g1_element().expect("unable to get public key"); + let signature = scheme.sign(&private_key, &[0x11u8; 32]); + (scheme, public_key, signature) + } + + #[test] + #[should_panic(expected = "32-byte message hash")] + fn legacy_sign_rejects_short_message() { + let scheme = LegacySchemeMPL::new(); + let private_key = PrivateKey::key_gen(&scheme, b"seedweedseedweedseedweedseedweed") + .expect("unable to generate private key"); + scheme.sign(&private_key, &[0x11u8; 31]); + } + + #[test] + #[should_panic(expected = "32-byte message hash")] + fn legacy_sign_rejects_long_message() { + let scheme = LegacySchemeMPL::new(); + let private_key = PrivateKey::key_gen(&scheme, b"seedweedseedweedseedweedseedweed") + .expect("unable to generate private key"); + scheme.sign(&private_key, &[0x11u8; 33]); + } + + #[test] + fn legacy_verify_rejects_wrong_message_length() { + let (scheme, public_key, signature) = legacy_key_and_signature(); + assert!(scheme.verify(&public_key, &[0x11u8; 32], &signature)); + for message in [&[0x11u8; 31][..], &[0x11u8; 33][..]] { + assert!(!scheme.verify(&public_key, message, &signature)); + assert!(!scheme.verify_secure([&public_key], message, &signature)); + assert!(!scheme.aggregate_verify([&public_key], [message], &signature)); + } + } } diff --git a/setup.py b/setup.py index cb8f9b6b8a56..6b748cfe5bdc 100644 --- a/setup.py +++ b/setup.py @@ -73,7 +73,6 @@ def build_extension(self, ext: CMakeExtension) -> None: "-DBUILD_BLS_BENCHMARKS=OFF", "-DBUILD_BLS_TESTS=OFF", "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=" + extdir, - "-DMULTI=", "-DPYBIND11_FINDPYTHON=ON", "-DPython_EXECUTABLE=" + sys.executable, "-DVERSION_INFO=" + self.distribution.get_version(), diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5802843a61ed..02eb9ae8f917 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,41 +1,63 @@ -file(GLOB HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/dashbls/*.hpp) +file(GLOB HEADERS ${PROJECT_SOURCE_DIR}/include/dashbls/*.hpp) source_group("SrcHeaders" FILES ${HEADERS}) -add_library(dashbls +list(APPEND bls_sources ${HEADERS} - ${CMAKE_CURRENT_SOURCE_DIR}/privatekey.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/bls.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/chaincode.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/elements.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/extendedprivatekey.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/extendedpublickey.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/legacy.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/schemes.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/threshold.cpp) - -target_include_directories(dashbls - PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR} - $<$:${GMP_INCLUDES}> - ${CMAKE_CURRENT_SOURCE_DIR}/../include/dashbls - ${CMAKE_CURRENT_SOURCE_DIR}/../depends/mimalloc/include - ${CMAKE_CURRENT_SOURCE_DIR}/../depends/relic/include - ${CMAKE_CURRENT_BINARY_DIR}/../depends/relic/include + privatekey.cpp + bls.cpp + chaincode.cpp + elements.cpp + extendedprivatekey.cpp + extendedpublickey.cpp + legacy.cpp + schemes.cpp + threshold.cpp + ${blst_SOURCE_DIR}/src/server.c ) -target_compile_definitions(dashbls - PRIVATE - BLSALLOC_MIMALLOC=1 -) +if(MSVC) + list(APPEND bls_sources + ${blst_SOURCE_DIR}/build/win64/add_mod_256-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/add_mod_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/add_mod_384x384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/ct_inverse_mod_256-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/ct_is_square_mod_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/ctq_inverse_mod_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/ctx_inverse_mod_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/div3w-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/mulq_mont_256-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/mulq_mont_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/mulx_mont_256-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/mulx_mont_384-x86_64.asm + ${blst_SOURCE_DIR}/build/win64/sha256-x86_64.asm + ) +else() + list(APPEND bls_sources + ${blst_SOURCE_DIR}/build/assembly.S + ) + set_source_files_properties(${blst_SOURCE_DIR}/src/server.c PROPERTIES COMPILE_OPTIONS -fno-builtin) + add_compile_options(-fPIC) + add_compile_options(-Wall) + add_compile_options(-Wextra) + if((CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") AND (NOT EMSCRIPTEN)) + add_compile_options(-mno-avx) + endif() +endif() +add_library(dashbls ${bls_sources}) +target_include_directories(dashbls PUBLIC ${blst_SOURCE_DIR}/bindings ${PROJECT_SOURCE_DIR}/include/dashbls/) +target_compile_definitions(dashbls PRIVATE __BLST_PORTABLE__ BLSALLOC_MIMALLOC=1) +if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64|AMD64|aarch64|arm64|ARM64") + # blst ships assembly for x86_64 and aarch64 only; other 64-bit targets + # (riscv64, powerpc64, ...) build its portable C code instead. + target_compile_definitions(dashbls PRIVATE __BLST_NO_ASM__) +endif() target_link_libraries(dashbls PUBLIC - relic_s mimalloc-static ) -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../depends/relic/include/ DESTINATION include/dashbls) -install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../depends/relic/include/ DESTINATION include/dashbls) +install(FILES ${blst_SOURCE_DIR}/bindings/blst.h ${blst_SOURCE_DIR}/bindings/blst_aux.h DESTINATION include/dashbls) install(FILES ${HEADERS} DESTINATION include/dashbls) install(FILES $ DESTINATION lib) @@ -43,9 +65,13 @@ if(BUILD_BLS_TESTS) include(${CMAKE_CURRENT_SOURCE_DIR}/../depends/catch2/CMakeLists.txt) add_executable(runtest test.cpp) + if(EMSCRIPTEN) + target_link_options(runtest PRIVATE "-sEXPORTED_FUNCTIONS=_malloc") + endif() target_link_libraries(runtest - PRIVATE dashbls - PRIVATE catch2) + PRIVATE + dashbls + catch2) if(EMSCRIPTEN) target_link_options(runtest PRIVATE "SHELL:-s MALLOC=emmalloc") @@ -66,3 +92,19 @@ if(BUILD_BLS_BENCHMARKS) endif() endif() endif() + +if(BUILD_BLS_TESTS) + # runtest compares the library against test-vectors/reference.txt; + # vectorgen regenerates that file from whichever library it is built against. + target_compile_definitions(runtest PRIVATE + DASHBLS_REFERENCE_VECTORS="${CMAKE_CURRENT_SOURCE_DIR}/../test-vectors/reference.txt") + + add_executable(vectorgen ${CMAKE_CURRENT_SOURCE_DIR}/../tools/vectorgen.cpp) + target_include_directories(vectorgen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(vectorgen PRIVATE dashbls) + + if(EMSCRIPTEN) + # mimalloc's Emscripten backend is built on emmalloc + target_link_options(vectorgen PRIVATE "SHELL:-s MALLOC=emmalloc") + endif() +endif() diff --git a/src/bls.cpp b/src/bls.cpp index e0af3a388216..19cce171f82e 100644 --- a/src/bls.cpp +++ b/src/bls.cpp @@ -18,10 +18,6 @@ #include "mimalloc.h" #endif -#if BLSALLOC_SODIUM -#include "sodium.h" -#endif - namespace bls { const size_t BLS::MESSAGE_HASH_LEN; @@ -31,41 +27,14 @@ bool BLSInitResult = BLS::Init(); Util::SecureAllocCallback Util::secureAllocCallback; Util::SecureFreeCallback Util::secureFreeCallback; -static void relic_core_initializer(void* ptr) -{ - core_init(); - if (err_get_code() != RLC_OK) { - throw std::runtime_error("core_init() failed"); - } - - const int r = ep_param_set_any_pairf(); - if (r != RLC_OK) { - throw std::runtime_error("ep_param_set_any_pairf() failed"); - } -} - bool BLS::Init() { - if (ALLOC != AUTO) { - throw std::runtime_error("Must have ALLOC == AUTO"); - } #if BLSALLOC_MIMALLOC SetSecureAllocator(mi_malloc, mi_free); -#elif BLSALLOC_SODIUM - if (sodium_init() < 0) { - throw std::runtime_error("libsodium init failed"); - } - SetSecureAllocator(sodium_malloc, sodium_free); #else SetSecureAllocator(malloc, free); #endif -#if MULTI != RELIC_NONE - core_set_thread_initializer(relic_core_initializer, nullptr); -#else - relic_core_initializer(nullptr); -#endif - return true; } @@ -77,18 +46,4 @@ void BLS::SetSecureAllocator( Util::secureFreeCallback = freeCb; } - -void BLS::CheckRelicErrors(bool should_throw) -{ - if (!core_get()) { - throw std::runtime_error("Library not initialized properly. Call BLS::Init()"); - } - if (core_get()->code != RLC_OK) { - core_get()->code = RLC_OK; - if (should_throw) { - throw std::invalid_argument("Relic library error"); - } - } -} - } // end namespace bls diff --git a/src/bn_helpers.hpp b/src/bn_helpers.hpp deleted file mode 100644 index 05175437ebee..000000000000 --- a/src/bn_helpers.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2026 The Dash Core developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef SRC_BN_HELPERS_HPP_ -#define SRC_BN_HELPERS_HPP_ - -#include "relic_conf.h" - -extern "C" { -#include "relic.h" -} - -#include - -namespace bls { - -// RAII wrapper for dynamically allocated bn_t arrays. -// Ensures bn_free + delete[] runs even when exceptions are thrown. -// Tracks initialization count so partial construction cleans up correctly. -struct BnArrayGuard { - bn_t* data; - size_t count; - size_t initialized{0}; - - explicit BnArrayGuard(size_t n) : data(new bn_t[n]), count(n) { - for (size_t i = 0; i < count; i++) { - bn_new(data[i]); - initialized++; - } - } - - ~BnArrayGuard() { - for (size_t i = 0; i < initialized; i++) { - bn_free(data[i]); - } - delete[] data; - } - - bn_t& operator[](size_t i) { return data[i]; } - const bn_t& operator[](size_t i) const { return data[i]; } - - BnArrayGuard(const BnArrayGuard&) = delete; - BnArrayGuard& operator=(const BnArrayGuard&) = delete; -}; - -// RAII wrapper for a single bn_t value. -struct BnGuard { - bn_t val; - - BnGuard() { bn_new(val); } - ~BnGuard() { bn_free(val); } - - operator bn_t&() { return val; } - - BnGuard(const BnGuard&) = delete; - BnGuard& operator=(const BnGuard&) = delete; -}; - -} // namespace bls - -#endif // SRC_BN_HELPERS_HPP_ diff --git a/src/chaincode.cpp b/src/chaincode.cpp index efacdc95ae29..e5a7204703f9 100644 --- a/src/chaincode.cpp +++ b/src/chaincode.cpp @@ -14,6 +14,8 @@ #include "bls.hpp" +#include + namespace bls { ChainCode ChainCode::FromBytes(const Bytes& bytes) { @@ -21,21 +23,15 @@ ChainCode ChainCode::FromBytes(const Bytes& bytes) { throw std::invalid_argument("ChainCode::FromBytes: Invalid size"); } ChainCode c = ChainCode(); - bn_new(c.chainCode); - bn_read_bin(c.chainCode, bytes.begin(), ChainCode::SIZE); + memcpy(c.chainCode.data(), bytes.begin(), ChainCode::SIZE); return c; } -ChainCode::ChainCode(const ChainCode &cc) { - uint8_t bytes[ChainCode::SIZE]; - cc.Serialize(bytes); - bn_new(chainCode); - bn_read_bin(chainCode, bytes, ChainCode::SIZE); -} +ChainCode::ChainCode(const ChainCode &cc) : chainCode(cc.chainCode) {} // Comparator implementation. bool operator==(ChainCode const &a, ChainCode const &b) { - return bn_cmp(a.chainCode, b.chainCode) == RLC_EQ; + return a.chainCode == b.chainCode; } bool operator!=(ChainCode const &a, ChainCode const &b) { @@ -49,7 +45,7 @@ std::ostream &operator<<(std::ostream &os, ChainCode const &s) { } void ChainCode::Serialize(uint8_t *buffer) const { - bn_write_bin(buffer, ChainCode::SIZE, chainCode); + memcpy(buffer, chainCode.data(), SIZE); } std::vector ChainCode::Serialize() const { diff --git a/src/elements.cpp b/src/elements.cpp index b0c747af823c..3f77b4d54ddf 100644 --- a/src/elements.cpp +++ b/src/elements.cpp @@ -12,16 +12,194 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include #include "bls.hpp" #include "legacy.hpp" +namespace { +// The legacy codec reproduces the byte-level behavior of the relic-based +// implementation exactly, including its handling of malformed input. relic +// was built without CHECK, so its internal errors did not throw: an +// out-of-range field element left the coordinate at zero, and a failed +// square root left y holding its pre-existing raw contents (0, or a raw +// limb 1 when the sign bit had been stored). All of it is consensus-visible +// through re-serialization and is pinned by test-vectors/reference.txt. + +// BLS12-381 base field prime p, big-endian. +static const uint8_t P_BE[48] = { + 0x1a, 0x01, 0x11, 0xea, 0x39, 0x7f, 0xe6, 0x9a, 0x4b, 0x1b, 0xa7, 0xb6, + 0x43, 0x4b, 0xac, 0xd7, 0x64, 0x77, 0x4b, 0x84, 0xf3, 0x85, 0x12, 0xbf, + 0x67, 0x30, 0xd2, 0xa0, 0xf6, 0xb0, 0xf6, 0x24, 0x1e, 0xab, 0xff, 0xfe, + 0xb1, 0x53, 0xff, 0xff, 0xb9, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xab}; + +// (p - 1) / 2, big-endian. The legacy sign convention is y > (p-1)/2 +// ("larger" root), matching relic's ep_pck/ep2_pck for pairing-friendly +// curves. +static const uint8_t HALF_P_BE[48] = { + 0x0d, 0x00, 0x88, 0xf5, 0x1c, 0xbf, 0xf3, 0x4d, 0x25, 0x8d, 0xd3, 0xdb, + 0x21, 0xa5, 0xd6, 0x6b, 0xb2, 0x3b, 0xa5, 0xc2, 0x79, 0xc2, 0x89, 0x5f, + 0xb3, 0x98, 0x69, 0x50, 0x7b, 0x58, 0x7b, 0x12, 0x0f, 0x55, 0xff, 0xff, + 0x58, 0xa9, 0xff, 0xff, 0xdc, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xd5, 0x55}; + +// (2^384)^-1 mod p, big-endian. When relic (built without CHECK) failed to +// find a square root during legacy point decompression with the sign bit +// set, the y coordinate was left holding a raw limb value of 1, which reads +// back from Montgomery form as this constant. Preserved bit-for-bit for +// compatibility with historical consensus data. +static const uint8_t MONT_R_INV_BE[48] = { + 0x14, 0xfe, 0xc7, 0x01, 0xe8, 0xfb, 0x0c, 0xe9, 0xed, 0x5e, 0x64, 0x27, + 0x3c, 0x4f, 0x53, 0x8b, 0x17, 0x97, 0xab, 0x14, 0x58, 0xa8, 0x8d, 0xe9, + 0x34, 0x3e, 0xa9, 0x79, 0x14, 0x95, 0x6d, 0xc8, 0x7f, 0xe1, 0x12, 0x74, + 0xd8, 0x98, 0xfa, 0xfb, 0xf4, 0xd3, 0x82, 0x59, 0x38, 0x0b, 0x48, 0x20}; + +inline void FpFromBE48(blst_fp& out, const uint8_t* be) +{ + blst_fp_from_bendian(&out, be); +} + +// Compares a big-endian 48-byte value against a constant. Returns the +// memcmp sign. +inline int CmpBE48(const uint8_t* a, const uint8_t* b) +{ + return memcmp(a, b, 48); +} + +inline void FpZero(blst_fp& out) { memset(&out, 0x00, sizeof(blst_fp)); } + +inline void FpOneConst(blst_fp& out) +{ + uint8_t be[48] = {0}; + be[47] = 1; + blst_fp_from_bendian(&out, be); +} + +// relic's ep2_upk sign rule (decompression side, with the IETF tie-break): +// sign = c1 > (p-1)/2, but when c1 == 0 the sign of c0 is used instead. +// Note the serialization side (ep2_pck) uses c1 only, with no tie-break. +inline bool Fp2SignUpk(const blst_fp2& y) +{ + uint8_t be[48]; + blst_bendian_from_fp(be, &y.fp[1]); + bool c1Zero = true; + for (int i = 0; i < 48; i++) + if (be[i] != 0) { c1Zero = false; break; } + if (!c1Zero) return CmpBE48(be, HALF_P_BE) > 0; + blst_bendian_from_fp(be, &y.fp[0]); + return CmpBE48(be, HALF_P_BE) > 0; +} + +// The "larger root" test used by both the legacy codec (relic's +// ep_pck/ep2_pck convention) and the legacy hash-to-curve: y > (p-1)/2 on +// the canonical representation. +inline bool FpSignGtHalf(const blst_fp& a) +{ + uint8_t be[48]; + blst_bendian_from_fp(be, &a); + return CmpBE48(be, HALF_P_BE) > 0; +} +} // anon namespace + namespace bls { +static void LegacyDecodeG1( + blst_p1_affine& a, + const uint8_t* bytes, + const bool signBit) +{ + uint8_t xbytes[G1Element::SIZE]; + memcpy(xbytes, bytes, G1Element::SIZE); + // the relic-based G1 codec erased the top three bits of the first byte + // unconditionally, before the sign bit was even examined (unlike G2, + // which only clears the sign bit) + xbytes[0] &= 0x1f; + + if (CmpBE48(xbytes, P_BE) >= 0) { + // relic's fp_read_bin error path: coordinate left untouched (zero) + FpZero(a.x); + } else { + FpFromBE48(a.x, xbytes); + } + + // rhs = x^3 + 4 + blst_fp rhs; + blst_fp_sqr(&rhs, &a.x); + blst_fp_mul(&rhs, &rhs, &a.x); + blst_fp four; + uint8_t fourBytes[48] = {0}; + fourBytes[47] = 4; + FpFromBE48(four, fourBytes); + blst_fp_add(&rhs, &rhs, &four); + + if (blst_fp_sqrt(&a.y, &rhs)) { + if (FpSignGtHalf(a.y) != signBit) { + blst_fp_cneg(&a.y, &a.y, true); + } + } else { + // relic's ep_upk failure: y keeps the raw sign-bit marker + if (signBit) { + FpFromBE48(a.y, MONT_R_INV_BE); + } else { + FpZero(a.y); + } + } +} + +static void LegacyDecodeG2( + blst_p2_affine& a, + const uint8_t* bytes, + const bool signBit) +{ + uint8_t c0[48], c1[48]; + memcpy(c0, bytes, 48); + memcpy(c1, bytes + 48, 48); + if (signBit) { + c0[0] &= 0x7f; + } + + if (CmpBE48(c0, P_BE) >= 0) { + FpZero(a.x.fp[0]); + } else { + FpFromBE48(a.x.fp[0], c0); + } + if (CmpBE48(c1, P_BE) >= 0) { + FpZero(a.x.fp[1]); + } else { + FpFromBE48(a.x.fp[1], c1); + } + + // rhs = x^3 + (4, 4) + blst_fp2 rhs; + blst_fp2_sqr(&rhs, &a.x); + blst_fp2_mul(&rhs, &rhs, &a.x); + blst_fp four; + uint8_t fourBytes[48] = {0}; + fourBytes[47] = 4; + FpFromBE48(four, fourBytes); + blst_fp2 b2; + b2.fp[0] = four; + b2.fp[1] = four; + blst_fp2_add(&rhs, &rhs, &b2); + + if (blst_fp2_sqrt(&a.y, &rhs)) { + if (Fp2SignUpk(a.y) != signBit) { + blst_fp2_cneg(&a.y, &a.y, true); + } + } else { + if (signBit) { + FpFromBE48(a.y.fp[0], MONT_R_INV_BE); + } else { + FpZero(a.y.fp[0]); + } + FpZero(a.y.fp[1]); + } +} const size_t G1Element::SIZE; -G1Element G1Element::FromBytes(Bytes const bytes, bool fLegacy) { +G1Element G1Element::FromBytes(Bytes const bytes, bool fLegacy) +{ G1Element ele = G1Element::FromBytesUnchecked(bytes, fLegacy); if (!fLegacy) { ele.CheckValid(); @@ -35,55 +213,46 @@ G1Element G1Element::FromBytesUnchecked(Bytes const bytes, bool fLegacy) throw std::invalid_argument("G1Element::FromBytes: Invalid size"); } - G1Element ele; - - // convert bytes to relic form - uint8_t buffer[G1Element::SIZE + 1]; - std::memcpy(buffer + 1, bytes.begin(), G1Element::SIZE); - buffer[0] = 0x00; - buffer[1] &= 0x1f; // erase 3 msbs from given input - + // check if the element is canonical + const uint8_t* raw_bytes = bytes.begin(); + bool fZerosOnly = (raw_bytes[0] & 0x1f) == 0 && + Util::HasOnlyZeros(Bytes(raw_bytes + 1, bytes.size() - 1)); if ((bytes[0] & 0xc0) == 0xc0) { // representing infinity - buffer[0] = 0x00; - buffer[1] &= 0x1f; // erase 3 msbs from given input - - bool fZerosOnly = Util::HasOnlyZeros(Bytes(buffer, G1Element::SIZE + 1)); // enforce that infinity must be 0xc0000..00 if (bytes[0] != 0xc0 || !fZerosOnly) { - throw std::invalid_argument("Given G1 infinity element must be canonical"); + throw std::invalid_argument( + "Given G1 infinity element must be canonical"); } + return G1Element(); // return infinity element (point all zero) + } + if (fLegacy) { + G1Element ele; + blst_p1_affine a; + LegacyDecodeG1(a, bytes.begin(), (bytes[0] & 0x80) != 0); + // Build the Jacobian point by hand: blst_p1_from_affine maps the + // all-zero affine pair to infinity, but relic kept degenerate + // decodes (e.g. x = 0, y = 0) as ordinary z=1 points, which is + // consensus-visible through re-serialization. + ele.p.x = a.x; + ele.p.y = a.y; + FpOneConst(ele.p.z); return ele; - } else { - if (fLegacy) { - if (bytes[0] & 0x80) { - buffer[0] = 0x03; // Insert extra byte for Y=1 - buffer[1] &= 0x7f; // Remove initial Y bit - } else { - buffer[0] = 0x02; // Insert extra byte for Y=0 - } - } else { - buffer[0] = 0x00; - buffer[1] &= 0x1f; // erase 3 msbs from given input - - bool fZerosOnly = Util::HasOnlyZeros(Bytes(buffer, G1Element::SIZE + 1)); - if ((bytes[0] & 0xc0) != 0x80) { - throw std::invalid_argument( - "Given G1 non-infinity element must start with 0b10"); - } - - if (fZerosOnly) { - throw std::invalid_argument("G1 non-infinity element can't have only zeros"); - } - if (bytes[0] & 0x20) { // sign bit - buffer[0] = 0x03; - } else { - buffer[0] = 0x02; - } - } } - g1_read_bin(ele.p, buffer, G1Element::SIZE + 1); - BLS::CheckRelicErrors(!fLegacy); - return ele; + if ((bytes[0] & 0xc0) != 0x80) { + throw std::invalid_argument( + "Given G1 non-infinity element must start with 0b10"); + } + if (fZerosOnly) { + throw std::invalid_argument( + "G1 non-infinity element can't have only zeros"); + } + + blst_p1_affine a; + BLST_ERROR err = blst_p1_uncompress(&a, bytes.begin()); + if (err != BLST_SUCCESS) + throw std::invalid_argument("G1Element::FromBytes: Invalid bytes"); + + return G1Element::FromAffine(a); } G1Element G1Element::FromByteVector(const std::vector& bytevec, bool fLegacy) @@ -91,35 +260,46 @@ G1Element G1Element::FromByteVector(const std::vector& bytevec, bool fL return G1Element::FromBytes(Bytes(bytevec), fLegacy); } -G1Element G1Element::FromNative(const g1_t element) +G1Element G1Element::FromNative(const blst_p1& element) { G1Element ele; - g1_copy(ele.p, element); + memcpy(&(ele.p), &element, sizeof(blst_p1)); return ele; } -G1Element G1Element::Copy() { +G1Element G1Element::FromAffine(const blst_p1_affine& element) +{ G1Element ele; - g1_copy(ele.p, this->p); - + blst_p1_from_affine(&(ele.p), &element); return ele; } - -G1Element G1Element::FromMessage(const std::vector& message, - const uint8_t* dst, - int dst_len) +G1Element G1Element::FromMessage( + const std::vector& message, + const uint8_t* dst, + size_t dst_len) { return FromMessage(Bytes(message), dst, dst_len); } -G1Element G1Element::FromMessage(Bytes const message, - const uint8_t* dst, - int dst_len) +G1Element G1Element::FromMessage( + Bytes const message, + const uint8_t* dst, + size_t dst_len) { G1Element ans; - ep_map_dst(ans.p, message.begin(), (int)message.size(), dst, dst_len); - BLS::CheckRelicErrors(); + const byte* aug = nullptr; + size_t aug_len = 0; + + blst_hash_to_g1( + &(ans.p), + message.begin(), + message.size(), + dst, + dst_len, + aug, + aug_len); + assert(ans.IsValid()); return ans; } @@ -127,35 +307,46 @@ G1Element G1Element::FromMessage(Bytes const message, G1Element G1Element::Generator() { G1Element ele; - g1_get_gen(ele.p); - BLS::CheckRelicErrors(); + ele.p = *(blst_p1_generator()); return ele; } -bool G1Element::IsValid() const { - // Infinity no longer valid in Relic - // https://github.com/relic-toolkit/relic/commit/f3be2babb955cf9f82743e0ae5ef265d3da6c02b - if (g1_is_infty((g1_st*)p) == 1) +bool G1Element::IsValid() const +{ + // Infinity was considered a valid G1Element in older Relic versions + // on which this library was previously based. + // For historical compatibililty this behavior is maintained. + + if (blst_p1_is_inf(&p)) return true; - return g1_is_valid((g1_st*)p); + // blst_p1_in_g1 assumes a point on the curve; relic's g1_is_valid + // checked both + return blst_p1_on_curve(&p) && blst_p1_in_g1(&p); } -void G1Element::CheckValid() const { +void G1Element::CheckValid() const +{ if (!IsValid()) throw std::invalid_argument("G1 element is invalid"); - BLS::CheckRelicErrors(); } -void G1Element::ToNative(g1_t output) const { - g1_copy(output, p); +void G1Element::ToNative(blst_p1* output) const +{ + memcpy(output, &p, sizeof(blst_p1)); } +void G1Element::ToAffine(blst_p1_affine* output) const +{ + blst_p1_to_affine(output, &p); +} + +G1Element G1Element::Copy() { return *this; } + G1Element G1Element::Negate() const { - G1Element ans; - g1_neg(ans.p, p); - BLS::CheckRelicErrors(); + G1Element ans = G1Element::FromNative(p); + blst_p1_cneg(&(ans.p), true); return ans; } @@ -165,84 +356,83 @@ uint32_t G1Element::GetFingerprint(const bool fLegacy) const { uint8_t buffer[G1Element::SIZE]; uint8_t hash[32]; - memcpy(buffer, Serialize(fLegacy).data(), G1Element::SIZE); + memcpy(buffer, SerializeToArray(fLegacy).data(), G1Element::SIZE); Util::Hash256(hash, buffer, G1Element::SIZE); return Util::FourBytesToInt(hash); } -std::vector G1Element::Serialize(const bool fLegacy) const { - const auto arr = G1Element::SerializeToArray(fLegacy); +std::vector G1Element::Serialize(const bool fLegacy) const +{ + const auto arr = SerializeToArray(fLegacy); return std::vector{arr.begin(), arr.end()}; } -std::array G1Element::SerializeToArray(const bool fLegacy) const { - uint8_t buffer[G1Element::SIZE + 1]; - g1_write_bin(buffer, G1Element::SIZE + 1, p, 1); - +std::array G1Element::SerializeToArray(const bool fLegacy) const +{ std::array result{}; - if (buffer[0] == 0x00) { // infinity - result[0] = 0xc0; + if (!fLegacy) { + blst_p1_compress(result.data(), &p); return result; } - if (buffer[0] == 0x03) { // sign bit set - buffer[1] |= fLegacy ? 0x80 : 0x20; + if (blst_p1_is_inf(&p)) { + result[0] = 0xc0; + return result; } - if (!fLegacy) { - buffer[1] |= 0x80; // indicate compression + blst_p1_affine a; + blst_p1_to_affine(&a, &p); + blst_bendian_from_fp(result.data(), &a.x); + if (FpSignGtHalf(a.y)) { + result[0] |= 0x80; } - - std::copy_n(buffer + 1, G1Element::SIZE, result.begin()); return result; } -bool operator==(const G1Element & a, const G1Element &b) +bool operator==(const G1Element& a, const G1Element& b) { - return g1_cmp(a.p, b.p) == RLC_EQ; + return blst_p1_is_equal(&(a.p), &(b.p)); } -bool operator!=(const G1Element & a, const G1Element & b) { return !(a == b); } +bool operator!=(const G1Element& a, const G1Element& b) { return !(a == b); } -std::ostream& operator<<(std::ostream& os, const G1Element &ele) +std::ostream& operator<<(std::ostream& os, const G1Element& ele) { return os << Util::HexStr(ele.Serialize()); } G1Element& operator+=(G1Element& a, const G1Element& b) { - g1_add(a.p, a.p, b.p); - BLS::CheckRelicErrors(); + blst_p1_add_or_double(&(a.p), &(a.p), &(b.p)); return a; } G1Element operator+(const G1Element& a, const G1Element& b) { G1Element ans; - g1_add(ans.p, a.p, b.p); - BLS::CheckRelicErrors(); + blst_p1_add_or_double(&(ans.p), &(a.p), &(b.p)); return ans; } -G1Element operator*(const G1Element& a, const bn_t& k) +G1Element operator*(const G1Element& a, const blst_scalar& k) { G1Element ans; - g1_mul(ans.p, (g1_st*)a.p, (bn_st*)k); - BLS::CheckRelicErrors(); + byte* bte = Util::SecAlloc(32); + blst_lendian_from_scalar(bte, &k); + blst_p1_mult(&(ans.p), &(a.p), bte, 256); + Util::SecFree(bte); + return ans; } -G1Element operator*(const bn_t& k, const G1Element& a) { return a * k; } - - +G1Element operator*(const blst_scalar& k, const G1Element& a) { return a * k; } // G2Element definitions below - - const size_t G2Element::SIZE; -G2Element G2Element::FromBytes(Bytes const bytes, const bool fLegacy) { +G2Element G2Element::FromBytes(Bytes const bytes, const bool fLegacy) +{ G2Element ele = G2Element::FromBytesUnchecked(bytes, fLegacy); if (!fLegacy) { ele.CheckValid(); @@ -256,59 +446,59 @@ G2Element G2Element::FromBytesUnchecked(Bytes const bytes, const bool fLegacy) throw std::invalid_argument("G2Element::FromBytes: Invalid size"); } - G2Element ele; - uint8_t buffer[G2Element::SIZE + 1]; - if (fLegacy) { - std::memcpy(buffer + 1, bytes.begin(), G2Element::SIZE); - buffer[0] = 0x00; - } else { - std::memcpy(buffer + 1, bytes.begin() + G2Element::SIZE / 2, G2Element::SIZE / 2); - std::memcpy(buffer + 1 + G2Element::SIZE / 2, bytes.begin(), G2Element::SIZE / 2); - buffer[0] = 0x00; - buffer[49] &= 0x1f; // erase 3 msbs from input - if ((bytes[48] & 0xe0) != 0x00) { + // The relic implementation computed its zeros-only check over a + // buffer that still contained the first byte unmasked, so for the + // legacy G2 codec any input with the two top bits set - canonical + // infinity included - was rejected as non-canonical. + if ((bytes[0] & 0xc0) == 0xc0) { throw std::invalid_argument( - "Given G2 element must always have 48th byte start with 0b000"); + "Given G2 infinity element must be canonical"); } + G2Element ele; + blst_p2_affine a; + LegacyDecodeG2(a, bytes.begin(), (bytes[0] & 0x80) != 0); + // See the G1 legacy path: keep degenerate all-zero decodes as + // ordinary z=1 points instead of mapping them to infinity. + ele.q.x = a.x; + ele.q.y = a.y; + FpOneConst(ele.q.z.fp[0]); + FpZero(ele.q.z.fp[1]); + return ele; + } + + if ((bytes[48] & 0xe0) != 0x00) { + throw std::invalid_argument( + "Given G2 element must always have 48th byte start with 0b000"); } - bool fZerosOnly = Util::HasOnlyZeros(Bytes(buffer, G2Element::SIZE + 1)); - if (((bytes[0] & 0xc0) == 0xc0)) { // infinity + + bool fZerosOnly = (bytes[0] & 0x1f) == 0 && + Util::HasOnlyZeros(Bytes(bytes.begin() + 1, bytes.size() - 1)); + if ((bytes[0] & 0xc0) == 0xc0) { // infinity // enforce that infinity must be 0xc0000..00 if (bytes[0] != 0xc0 || !fZerosOnly) { throw std::invalid_argument( "Given G2 infinity element must be canonical"); } - return ele; + return G2Element(); } - if (fLegacy) { - if (bytes[0] & 0x80) { - buffer[0] = 0x03; // Insert extra byte for Y=1 - buffer[1] &= 0x7f; // Remove initial Y bit - } else { - buffer[0] = 0x02; // Insert extra byte for Y=0 - } - } else { - if (((bytes[0] & 0xc0) != 0x80)) { - throw std::invalid_argument( - "G2 non-inf element must have 0th byte start with 0b10"); - } - - if (fZerosOnly) { - throw std::invalid_argument("G2 non-infinity element can't have only zeros"); - } + if ((bytes[0] & 0xc0) != 0x80) { + throw std::invalid_argument( + "G2 non-inf element must have 0th byte start with 0b10"); + } - if (bytes[0] & 0x20) { - buffer[0] = 0x03; - } else { - buffer[0] = 0x02; - } + if (fZerosOnly) { + throw std::invalid_argument( + "G2 non-infinity element can't have only zeros"); } - g2_read_bin(ele.q, buffer, G2Element::SIZE + 1); - BLS::CheckRelicErrors(!fLegacy); - return ele; + blst_p2_affine a; + BLST_ERROR err = blst_p2_uncompress(&a, bytes.begin()); + if (err != BLST_SUCCESS) + throw std::invalid_argument("G2Element::FromBytes: Invalid bytes"); + + return G2Element::FromAffine(a); } G2Element G2Element::FromByteVector(const std::vector& bytevec, bool fLegacy) @@ -316,33 +506,51 @@ G2Element G2Element::FromByteVector(const std::vector& bytevec, bool fL return G2Element::FromBytes(Bytes(bytevec), fLegacy); } -G2Element G2Element::FromNative(const g2_t element) +G2Element G2Element::FromNative(const blst_p2& element) { G2Element ele; - g2_copy(ele.q, (g2_st*)element); + memcpy(&(ele.q), &element, sizeof(blst_p2)); return ele; } -G2Element G2Element::FromMessage(const std::vector& message, - const uint8_t* dst, - int dst_len, - const bool fLegacy) +G2Element G2Element::FromAffine(const blst_p2_affine& element) +{ + G2Element ele; + blst_p2_from_affine(&(ele.q), &element); + return ele; +} + +G2Element G2Element::FromMessage( + const std::vector& message, + const uint8_t* dst, + size_t dst_len, + const bool fLegacy) { return FromMessage(Bytes(message), dst, dst_len, fLegacy); } -G2Element G2Element::FromMessage(Bytes const message, - const uint8_t* dst, - int dst_len, - const bool fLegacy) +G2Element G2Element::FromMessage( + Bytes const message, + const uint8_t* dst, + size_t dst_len, + const bool fLegacy) { G2Element ans; if (fLegacy) { - ep2_map_legacy(ans.q, message.begin(), BLS::MESSAGE_HASH_LEN); + ep2_map_legacy(&(ans.q), message.begin(), message.size()); } else { - ep2_map_dst(ans.q, message.begin(), (int)message.size(), dst, dst_len); + const byte* aug = nullptr; + size_t aug_len = 0; + + blst_hash_to_g2( + &(ans.q), + message.begin(), + message.size(), + dst, + dst_len, + aug, + aug_len); } - BLS::CheckRelicErrors(); assert(ans.IsValid()); return ans; } @@ -350,139 +558,134 @@ G2Element G2Element::FromMessage(Bytes const message, G2Element G2Element::Generator() { G2Element ele; - g2_get_gen(ele.q); - BLS::CheckRelicErrors(); + ele.q = (*blst_p2_generator()); return ele; } -bool G2Element::IsValid() const { - // Infinity no longer valid in Relic - // https://github.com/relic-toolkit/relic/commit/f3be2babb955cf9f82743e0ae5ef265d3da6c02b - if (g2_is_infty((g2_st*)q) == 1) +bool G2Element::IsValid() const +{ + // Infinity was considered a valid G2Element in older Relic versions + // on which this library was previously based. + // For historical compatibililty this behavior is maintained. + + if (blst_p2_is_inf(&q)) return true; - return g2_is_valid((g2_st*)q); + return blst_p2_on_curve(&q) && blst_p2_in_g2(&q); } -void G2Element::CheckValid() const { +void G2Element::CheckValid() const +{ if (!IsValid()) throw std::invalid_argument("G2 element is invalid"); - BLS::CheckRelicErrors(); } -void G2Element::ToNative(g2_t output) const { - g2_copy(output, (g2_st*)q); +void G2Element::ToNative(blst_p2* output) const +{ + memcpy(output, (blst_p2*)&q, sizeof(blst_p2)); } -G2Element G2Element::Copy() { - G2Element ele; - g2_copy(ele.q, this->q); - - return ele; +void G2Element::ToAffine(blst_p2_affine* output) const +{ + blst_p2_to_affine(output, &q); } +G2Element G2Element::Copy() { return *this; } G2Element G2Element::Negate() const { - G2Element ans; - g2_neg(ans.q, (g2_st*)q); - BLS::CheckRelicErrors(); + G2Element ans = G2Element::FromNative(q); + blst_p2_cneg(&(ans.q), true); return ans; } GTElement G2Element::Pair(const G1Element& a) const { return a & (*this); } -std::vector G2Element::Serialize(const bool fLegacy) const { +std::vector G2Element::Serialize(const bool fLegacy) const +{ const auto arr = G2Element::SerializeToArray(fLegacy); return std::vector{arr.begin(), arr.end()}; } -std::array G2Element::SerializeToArray(const bool fLegacy) const { - uint8_t buffer[G2Element::SIZE + 1]; - g2_write_bin(buffer, G2Element::SIZE + 1, (g2_st*)q, 1); - +std::array G2Element::SerializeToArray(const bool fLegacy) const +{ std::array result{}; - - if (buffer[0] == 0x00) { // infinity - result.fill(0); - result[0] = 0xc0; + if (!fLegacy) { + blst_p2_compress(result.data(), &q); return result; } - if (fLegacy) { - if (buffer[0] == 0x03) { // sign bit set - buffer[1] |= 0x80; - } - } else { - // remove leading 3 bits - buffer[1] &= 0x1f; - buffer[49] &= 0x1f; - if (buffer[0] == 0x03) { - buffer[49] |= 0xa0; // swapped later to 0 - } else { - buffer[49] |= 0x80; - } + if (blst_p2_is_inf(&q)) { + result[0] = 0xc0; + return result; } - if (fLegacy) { - std::memcpy(result.data(), buffer + 1, G2Element::SIZE); - } else { - // Swap buffer, relic uses the opposite ordering for Fq2 elements - std::memcpy(result.data(), buffer + 1 + G2Element::SIZE / 2, G2Element::SIZE / 2); - std::memcpy(result.data() + G2Element::SIZE / 2, buffer + 1, G2Element::SIZE / 2); + blst_p2_affine a; + blst_p2_to_affine(&a, &q); + // legacy layout: x.c0 || x.c1 (the modern IETF layout is the swap) + blst_bendian_from_fp(result.data(), &a.x.fp[0]); + blst_bendian_from_fp(result.data() + 48, &a.x.fp[1]); + // legacy sign: c1 > (p-1)/2, no tie-break (relic's ep2_pck) + if (FpSignGtHalf(a.y.fp[1])) { + result[0] |= 0x80; } - return result; } bool operator==(G2Element const& a, G2Element const& b) { - return g2_cmp((g2_st*)a.q, (g2_st*)b.q) == RLC_EQ; + return blst_p2_is_equal(&(a.q), &(b.q)); } bool operator!=(G2Element const& a, G2Element const& b) { return !(a == b); } -std::ostream& operator<<(std::ostream& os, const G2Element & s) +std::ostream& operator<<(std::ostream& os, const G2Element& s) { return os << Util::HexStr(s.Serialize()); } G2Element& operator+=(G2Element& a, const G2Element& b) { - g2_add(a.q, a.q, (g2_st*)b.q); - BLS::CheckRelicErrors(); + blst_p2_add_or_double(&(a.q), &(a.q), &(b.q)); return a; } G2Element operator+(const G2Element& a, const G2Element& b) { G2Element ans; - g2_add(ans.q, (g2_st*)a.q, (g2_st*)b.q); - BLS::CheckRelicErrors(); + blst_p2_add_or_double(&(ans.q), &(a.q), &(b.q)); return ans; } -G2Element operator*(const G2Element& a, const bn_t& k) +G2Element operator*(const G2Element& a, const blst_scalar& k) { G2Element ans; - g2_mul(ans.q, (g2_st*)a.q, (bn_st*)k); - BLS::CheckRelicErrors(); + byte* bte = Util::SecAlloc(32); + blst_lendian_from_scalar(bte, &k); + blst_p2_mult(&(ans.q), &(a.q), bte, 256); + Util::SecFree(bte); + return ans; } -G2Element operator*(const bn_t& k, const G2Element& a) { return a * k; } - - +G2Element operator*(const blst_scalar& k, const G2Element& a) { return a * k; } // GTElement const size_t GTElement::SIZE; +/* + * Currently deserliazation is not available - these are currently + * broken and just return the zero element + */ GTElement GTElement::FromBytes(Bytes const bytes) { GTElement ele = GTElement::FromBytesUnchecked(bytes); - if (gt_is_valid(*(gt_t*)&ele) == 0) - throw std::invalid_argument("GTElement is invalid"); + // + // this doesn't seem to be the proper check as it doesn't work as expeced + // + // if (!blst_fp12_in_group(&(ele.r))) + // throw std::invalid_argument("GTElement is invalid"); return ele; } @@ -492,8 +695,7 @@ GTElement GTElement::FromBytesUnchecked(Bytes const bytes) throw std::invalid_argument("GTElement::FromBytes: Invalid size"); } GTElement ele = GTElement(); - gt_read_bin(ele.r, bytes.begin(), GTElement::SIZE); - BLS::CheckRelicErrors(); + memcpy(&(ele.r), bytes.begin(), SIZE); return ele; } @@ -502,23 +704,35 @@ GTElement GTElement::FromByteVector(const std::vector& bytevec) return GTElement::FromBytes(Bytes(bytevec)); } -GTElement GTElement::FromNative(const gt_t* element) +GTElement GTElement::FromNative(const blst_fp12* element) { GTElement ele = GTElement(); - gt_copy(ele.r, *(gt_t*)element); + ele.r = *element; return ele; } -GTElement GTElement::Unity() { +GTElement GTElement::FromAffine(const blst_p1_affine& affine) +{ GTElement ele = GTElement(); - gt_set_unity(ele.r); + blst_aggregated_in_g1(&ele.r, &affine); return ele; } +GTElement GTElement::FromAffine(const blst_p2_affine& affine) +{ + GTElement ele = GTElement(); + blst_aggregated_in_g2(&ele.r, &affine); + return ele; +} + +GTElement GTElement::Unity() +{ + return GTElement::FromNative(blst_fp12_one()); +} bool operator==(GTElement const& a, GTElement const& b) { - return gt_cmp(*(gt_t*)(a.r), *(gt_t*)(b.r)) == RLC_EQ; + return blst_fp12_is_equal(&(a.r), &(b.r)); } bool operator!=(GTElement const& a, GTElement const& b) { return !(a == b); } @@ -530,31 +744,31 @@ std::ostream& operator<<(std::ostream& os, GTElement const& ele) GTElement operator&(const G1Element& a, const G2Element& b) { - G1Element nonConstA(a); - gt_t ans; - gt_new(ans); - g2_t tmp; - g2_null(tmp); - g2_new(tmp); - b.ToNative(tmp); - pp_map_oatep_k12(ans, nonConstA.p, tmp); + blst_fp12 ans; + + blst_p1_affine aff1; + blst_p2_affine aff2; + a.ToAffine(&aff1); + b.ToAffine(&aff2); + + blst_miller_loop(&ans, &aff2, &aff1); + blst_final_exp(&ans, &ans); + GTElement ret = GTElement::FromNative(&ans); - gt_free(ans); - g2_free(tmp); + return ret; } GTElement operator*(GTElement& a, GTElement& b) { GTElement ans; - fp12_mul(ans.r, a.r, b.r); - BLS::CheckRelicErrors(); + blst_fp12_mul(&(ans.r), &(a.r), &(b.r)); return ans; } void GTElement::Serialize(uint8_t* buffer) const { - gt_write_bin(buffer, GTElement::SIZE, *(gt_t*)&r, 1); + memcpy(buffer, &r, GTElement::SIZE); } std::vector GTElement::Serialize() const diff --git a/src/extendedprivatekey.cpp b/src/extendedprivatekey.cpp index d5fe746ee690..237aa0515892 100644 --- a/src/extendedprivatekey.cpp +++ b/src/extendedprivatekey.cpp @@ -31,27 +31,16 @@ ExtendedPrivateKey ExtendedPrivateKey::FromSeed(const Bytes& bytes) { // Hash the seed into 64 bytes, half will be sk, half will be cc hashInput[bytes.size()] = 0; - md_hmac(ILeft, hashInput, bytes.size() + 1, prefix, sizeof(prefix)); + Util::md_hmac(ILeft, hashInput, bytes.size() + 1, prefix, sizeof(prefix)); hashInput[bytes.size()] = 1; - md_hmac(IRight, hashInput, bytes.size() + 1, prefix, sizeof(prefix)); + Util::md_hmac(IRight, hashInput, bytes.size() + 1, prefix, sizeof(prefix)); // Make sure private key is less than the curve order - bn_t* skBn = Util::SecAlloc(1); - bn_t order; - bn_new(order); - g1_get_ord(order); - - bn_new(*skBn); - bn_read_bin(*skBn, ILeft, PrivateKey::PRIVATE_KEY_SIZE); - bn_mod_basic(*skBn, *skBn, order); - bn_write_bin(ILeft, PrivateKey::PRIVATE_KEY_SIZE, *skBn); - ExtendedPrivateKey esk(ExtendedPublicKey::REVISION, 0, 0, 0, ChainCode::FromBytes(Bytes(IRight, ChainCode::SIZE)), - PrivateKey::FromBytes(Bytes(ILeft, PrivateKey::PRIVATE_KEY_SIZE))); + PrivateKey::FromBytes(Bytes(ILeft, PrivateKey::PRIVATE_KEY_SIZE), true)); - Util::SecFree(skBn); Util::SecFree(ILeft); Util::SecFree(hashInput); return esk; @@ -101,13 +90,13 @@ ExtendedPrivateKey ExtendedPrivateKey::PrivateChild(uint32_t i, const bool fLega } hmacInput[inputLen - 1] = 0; - md_hmac(ILeft, hmacInput, inputLen, + Util::md_hmac(ILeft, hmacInput, inputLen, hmacKey, ChainCode::SIZE); // Change 1 byte to generate a different sequence for chaincode hmacInput[inputLen - 1] = 1; - md_hmac(IRight, hmacInput, inputLen, + Util::md_hmac(IRight, hmacInput, inputLen, hmacKey, ChainCode::SIZE); PrivateKey newSk = PrivateKey::FromBytes(Bytes(ILeft, PrivateKey::PRIVATE_KEY_SIZE), true); diff --git a/src/extendedpublickey.cpp b/src/extendedpublickey.cpp index a484dea64621..ad1015a68c9b 100644 --- a/src/extendedpublickey.cpp +++ b/src/extendedpublickey.cpp @@ -59,13 +59,13 @@ ExtendedPublicKey ExtendedPublicKey::PublicChild(uint32_t i, const bool fLegacy) hmacInput[inputLen - 1] = 0; Util::IntToFourBytes(hmacInput + G1Element::SIZE, i); - md_hmac(ILeft, hmacInput, inputLen, + Util::md_hmac(ILeft, hmacInput, inputLen, hmacKey, ChainCode::SIZE); // Change 1 byte to generate a different sequence for chaincode hmacInput[inputLen - 1] = 1; - md_hmac(IRight, hmacInput, inputLen, + Util::md_hmac(IRight, hmacInput, inputLen, hmacKey, ChainCode::SIZE); PrivateKey leftSk = PrivateKey::FromBytes(Bytes(ILeft, PrivateKey::PRIVATE_KEY_SIZE), true); diff --git a/src/legacy.cpp b/src/legacy.cpp index 44780528d6ba..a7d5832b9886 100644 --- a/src/legacy.cpp +++ b/src/legacy.cpp @@ -3,142 +3,69 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "legacy.hpp" - -#include - -#define B12_P381_S3 "BE32CE5FBEED9CA374D38C0ED41EEFD5BB675277CDF12D11BC2FB026C41400045C03FFFFFFFDFFFD" -#define B12_P381_S32 "5F19672FDF76CE51BA69C6076A0F77EADDB3A93BE6F89688DE17D813620A00022E01FFFFFFFEFFFE" - -/** - * Returns the (sqrt(-3) - 1) / 2 mod q in the curve, where q is the prime. - * - * @param[out] h - the returned cofactor. - */ -static void ep2_curve_get_s32(bn_t s32In) { - static std::once_flag is_initialized; - static bn_t s32; - std::call_once(is_initialized, [] { - bn_new(s32); - bn_read_str(s32, B12_P381_S32, sizeof(B12_P381_S32), 16); - }); - bn_copy(s32In, s32); +#include +#include +#include + +namespace { + +// sqrt(-3) mod p, big-endian, zero-padded to 48 bytes. Value taken from the +// relic implementation's B12_P381_S3 constant; validated by +// s3^2 == -3 (mod p). +const uint8_t S3_BE[48] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x32, 0xce, 0x5f, + 0xbe, 0xed, 0x9c, 0xa3, 0x74, 0xd3, 0x8c, 0x0e, 0xd4, 0x1e, 0xef, 0xd5, + 0xbb, 0x67, 0x52, 0x77, 0xcd, 0xf1, 0x2d, 0x11, 0xbc, 0x2f, 0xb0, 0x26, + 0xc4, 0x14, 0x00, 0x04, 0x5c, 0x03, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xfd}; + +// (sqrt(-3) - 1) / 2 mod p (relic's B12_P381_S32). +const uint8_t S32_BE[48] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x19, 0x67, 0x2f, + 0xdf, 0x76, 0xce, 0x51, 0xba, 0x69, 0xc6, 0x07, 0x6a, 0x0f, 0x77, 0xea, + 0xdd, 0xb3, 0xa9, 0x3b, 0xe6, 0xf8, 0x96, 0x88, 0xde, 0x17, 0xd8, 0x13, + 0x62, 0x0a, 0x00, 0x02, 0x2e, 0x01, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfe}; + +// Effective cofactor h_eff for BLS12-381 G2 (RFC 9380 section 8.8.2), +// big-endian, 80 bytes / 636 bits. Scalar multiplication by h_eff is +// equivalent to the psi-endomorphism-based cofactor clearing the relic +// implementation performed (verified empirically point-by-point). +const uint8_t H_EFF_BE[80] = { + 0x0b, 0xc6, 0x9f, 0x08, 0xf2, 0xee, 0x75, 0xb3, 0x58, 0x4c, 0x6a, 0x0e, + 0xa9, 0x1b, 0x35, 0x28, 0x88, 0xe2, 0xa8, 0xe9, 0x14, 0x5a, 0xd7, 0x68, + 0x99, 0x86, 0xff, 0x03, 0x15, 0x08, 0xff, 0xe1, 0x32, 0x9c, 0x2f, 0x17, + 0x87, 0x31, 0xdb, 0x95, 0x6d, 0x82, 0xbf, 0x01, 0x5d, 0x12, 0x12, 0xb0, + 0x2e, 0xc0, 0xec, 0x69, 0xd7, 0x47, 0x7c, 0x1a, 0xe9, 0x54, 0xcb, 0xc0, + 0x66, 0x89, 0xf6, 0xa3, 0x59, 0x89, 0x4c, 0x0a, 0xde, 0xbb, 0xf6, 0xb4, + 0xe8, 0x02, 0x00, 0x05, 0xaa, 0xa9, 0x55, 0x51}; + +void FpOne(blst_fp& out) +{ + uint8_t be[48] = {0}; + be[47] = 1; + blst_fp_from_bendian(&out, be); } -/** - * Returns the sqrt(-3) mod q in the curve, where q is the prime. - * - * @param[out] h - the returned cofactor. - */ -static void ep2_curve_get_s3(bn_t s3In) { - static std::once_flag is_initialized; - static bn_t s3; - std::call_once(is_initialized, [] { - bn_new(s3); - bn_read_str(s3, B12_P381_S3, sizeof(B12_P381_S3), 16); - }); - bn_copy(s3In, s3); +void FpFour(blst_fp& out) +{ + uint8_t be[48] = {0}; + be[47] = 4; + blst_fp_from_bendian(&out, be); } -/** - * Returns the 'b' coefficient of the currently configured elliptic curve. - * - * @param[out] b - the 'b' coefficient of the elliptic curve. - */ -static void ep2_curve_get_b(fp2_t b) { - ctx_t *ctx = core_get(); - fp_copy(b[0], ctx->ep2_b[0]); - fp_copy(b[1], ctx->ep2_b[1]); -} +inline void FpZero(blst_fp& out) { memset(&out, 0x00, sizeof(blst_fp)); } -/** - * Returns the variable used to parameterize the given prime modulus. - * - * @param[out] x - the integer parameter. - */ -static void fp_param_get_var(bn_t x) { - bn_t a; - - bn_null(a); - - RLC_TRY { - bn_new(a); - /* x = -(2^63 + 2^62 + 2^60 + 2^57 + 2^48 + 2^16). */ - bn_set_2b(x, 63); - bn_set_2b(a, 62); - bn_add(x, x, a); - bn_set_2b(a, 60); - bn_add(x, x, a); - bn_set_2b(a, 57); - bn_add(x, x, a); - bn_set_2b(a, 48); - bn_add(x, x, a); - bn_set_2b(a, 16); - bn_add(x, x, a); - bn_neg(x, x); - } - RLC_CATCH_ANY { - RLC_THROW(ERR_CAUGHT); - } - RLC_FINALLY { - bn_free(a); - } +bool FpIsZero(const blst_fp& a) +{ + uint8_t be[48]; + blst_bendian_from_fp(be, &a); + for (int i = 0; i < 48; i++) + if (be[i] != 0) return false; + return true; } -/** - * Multiplies a point by the cofactor in a Barreto-Lynn-Soctt. - * - * @param[out] r - the result. - * @param[in] p - the point to multiply. - */ -static void ep2_mul_cof_b12(ep2_t r, ep2_t p) { - bn_t x; - ep2_t t0, t1, t2, t3; - - ep2_null(t0); - ep2_null(t1); - ep2_null(t2); - ep2_null(t3); - bn_null(x); - - RLC_TRY { - ep2_new(t0); - ep2_new(t1); - ep2_new(t2); - ep2_new(t3); - bn_new(x); - - fp_param_get_var(x); - - /* Compute t0 = xP. */ - ep2_mul_basic(t0, p, x); - /* Compute t1 = [x^2]P. */ - ep2_mul_basic(t1, t0, x); - - /* t2 = (x^2 - x - 1)P = x^2P - x*P - P. */ - ep2_sub(t2, t1, t0); - ep2_sub(t2, t2, p); - /* t3 = \psi(x - 1)P. */ - ep2_sub(t3, t0, p); - ep2_norm(t3, t3); - ep2_frb(t3, t3, 1); - ep2_add(t2, t2, t3); - /* t3 = \psi^2(2P). */ - ep2_dbl(t3, p); - ep2_norm(t3, t3); - ep2_frb(t3, t3, 2); - ep2_add(t2, t2, t3); - ep2_norm(r, t2); - } - RLC_CATCH_ANY { - RLC_THROW(ERR_CAUGHT); - } - RLC_FINALLY { - ep2_free(t0); - ep2_free(t1); - ep2_free(t2); - ep2_free(t3); - bn_free(x); - } +bool Fp2IsZero(const blst_fp2& a) +{ + return FpIsZero(a.fp[0]) && FpIsZero(a.fp[1]); } /** @@ -146,288 +73,191 @@ static void ep2_mul_cof_b12(ep2_t r, ep2_t p) { * The algorithm is Shallue–van de Woestijne encoding from * Section 3 of "Indifferentiable Hashing to Barreto–Naehrig Curves" * from Fouque-Tibouchi: + * @param[out] p - the encoded point. + * @param[in] t - the field element to encode. + * Returns false when the result is the point at infinity (t == 0). */ -static void ep2_sw_encode(ep2_t p, fp2_t t) { - if (fp2_is_zero(t)) { +bool ep2_sw_encode(blst_p2_affine& p, const blst_fp2& t) +{ + if (Fp2IsZero(t)) { // Maps t=0 to the point at infinity. - ep2_set_infty(p); - return; + return false; } - fp2_t nt; // Negative t - fp2_t w; - fp2_t b; - bn_t s_n3; - bn_t s_n3m1o2; - fp2_t x1; - fp2_t x2; - fp2_t x3; - fp2_t rhs; - - fp2_new(nt); - fp2_new(w); - fp2_new(b); - bn_new(s_n3); - bn_new(s_n3m1o2); - fp2_new(x1); - fp2_new(x2); - fp2_new(x3); - fp2_new(rhs); - - // nt = -t - fp2_neg(nt, t); - - uint8_t buf0[RLC_FP_BYTES]; // t[1] - uint8_t buf1[RLC_FP_BYTES]; // -t[1] - fp_write_bin(buf0, RLC_FP_BYTES, t[1]); - fp_write_bin(buf1, RLC_FP_BYTES, nt[1]); - - // Compare bytes since fp_cmp compares montgomery representation - int parity = memcmp(buf0, buf1, RLC_FP_BYTES) > 0; + + // parity of t: compare the canonical bytes of t.c1 against those of + // (-t).c1 + blst_fp2 nt = t; + blst_fp2_cneg(&nt, &nt, true); + uint8_t buf0[48], buf1[48]; + blst_bendian_from_fp(buf0, &t.fp[1]); + blst_bendian_from_fp(buf1, &nt.fp[1]); + const bool parity = memcmp(buf0, buf1, 48) > 0; + + blst_fp one, four; + FpOne(one); + FpFour(four); + blst_fp2 b; + b.fp[0] = four; + b.fp[1] = four; // w = t^2 + b + 1 - fp2_mul(w, t, t); - ep2_curve_get_b(b); - fp2_add(w, w, b); - fp_add_dig(w[0], w[0], 1); + blst_fp2 w; + blst_fp2_sqr(&w, &t); + blst_fp2_add(&w, &w, &b); + blst_fp_add(&w.fp[0], &w.fp[0], &one); - if (fp2_is_zero(w)) { - ep2_curve_get_gen(p); + if (Fp2IsZero(w)) { + p = *blst_p2_affine_generator(); if (parity) { - ep2_neg(p, p); + blst_fp2_cneg(&p.y, &p.y, true); } - fp2_free(nt); - fp2_free(w); - fp2_free(b); - bn_free(s_n3); - bn_free(s_n3m1o2); - fp2_free(x1); - fp2_free(x2); - fp2_free(x3); - fp2_free(rhs); - return; + return true; } - // sqrt(-3) - ep2_curve_get_s3(s_n3); - fp2_t s_n3p; - fp2_null(s_n3p); - fp2_new(s_n3p); - fp2_t s_n3m1o2p; - fp2_null(s_n3m1o2p); - fp2_new(s_n3m1o2p); + blst_fp2 s3p, s32p; + blst_fp_from_bendian(&s3p.fp[0], S3_BE); + FpZero(s3p.fp[1]); + blst_fp_from_bendian(&s32p.fp[0], S32_BE); + FpZero(s32p.fp[1]); - fp2_zero(s_n3p); - fp2_zero(s_n3m1o2p); - fp_prime_conv(s_n3p[0], s_n3); + // w = sqrt(-3) * t / (t^2 + b + 1) + blst_fp2_inverse(&w, &w); + blst_fp2_mul(&w, &w, &s3p); + blst_fp2_mul(&w, &w, &t); - // (sqrt(-3) - 1) / 2 - ep2_curve_get_s32(s_n3m1o2); - fp_prime_conv(s_n3m1o2p[0], s_n3m1o2); - - fp2_inv(w, w); - fp2_mul(w, w, s_n3p); - fp2_mul(w, w, t); - - // x1 = -wt + sqrt(-3) - fp2_neg(x1, w); - fp2_mul(x1, x1, t); - fp2_add(x1, x1, s_n3m1o2p); + // x1 = -wt + (sqrt(-3) - 1) / 2 + blst_fp2 x1; + x1 = w; + blst_fp2_cneg(&x1, &x1, true); + blst_fp2_mul(&x1, &x1, &t); + blst_fp2_add(&x1, &x1, &s32p); // x2 = -x1 - 1 - fp2_neg(x2, x1); - fp_sub_dig(x2[0], x2[0], 1); + blst_fp2 x2 = x1; + blst_fp2_cneg(&x2, &x2, true); + blst_fp_sub(&x2.fp[0], &x2.fp[0], &one); // x3 = 1/w^2 + 1 - fp2_mul(x3, w, w); - fp2_inv(x3, x3); - fp_add_dig(x3[0], x3[0], 1); - - fp2_zero(p->y); - fp2_set_dig(p->z, 1); - - // if x1 has no y, try x2. if x2 has no y, try x3 - fp2_copy(p->x, x1); - - ep2_rhs(rhs, p); - int Xx1 = fp2_srt(p->y, rhs) ? 1 : -1; - fp2_copy(p->x, x2); - ep2_rhs(rhs, p); - int Xx2 = fp2_srt(p->y, rhs) ? 1 : -1; + blst_fp2 x3; + blst_fp2_sqr(&x3, &w); + blst_fp2_inverse(&x3, &x3); + blst_fp_add(&x3.fp[0], &x3.fp[0], &one); + + const auto rhs = [&b](blst_fp2& out, const blst_fp2& x) { + blst_fp2_sqr(&out, &x); + blst_fp2_mul(&out, &out, &x); + blst_fp2_add(&out, &out, &b); + }; + + blst_fp2 r, y; + rhs(r, x1); + const int Xx1 = blst_fp2_sqrt(&y, &r) ? 1 : -1; + rhs(r, x2); + const int Xx2 = blst_fp2_sqrt(&y, &r) ? 1 : -1; // This formula computes which index to use, in constant time // without conditional branches. It's taken from the paper. 3 is // added, because the % operator in c can be negative. - int index = ((((Xx1 - 1) * Xx2) % 3) + 3) % 3; - - if (index == 0) { - fp2_copy(p->x, x1); - ep2_rhs(rhs, p); - fp2_srt(p->y, rhs); - } else if (index == 1) { - fp2_copy(p->x, x2); - ep2_rhs(rhs, p); - fp2_srt(p->y, rhs); - } else if (index == 2) { - fp2_copy(p->x, x3); - ep2_rhs(rhs, p); - fp2_srt(p->y, rhs); - } - - p->coord = 1; - - // Check for lexicografically greater than the negation - fp2_t ny; - fp2_null(ny); - fp2_new(ny); - fp2_neg(ny, p->y); - fp_write_bin(buf0, RLC_FP_BYTES, p->y[1]); - fp_write_bin(buf1, RLC_FP_BYTES, ny[1]); - - // Compare bytes since fp_cmp compares montgomery representation - if ((memcmp(buf0, buf1, RLC_FP_BYTES) > 0) != parity) { - ep2_neg(p, p); + const int index = ((((Xx1 - 1) * Xx2) % 3) + 3) % 3; + + p.x = (index == 0) ? x1 : (index == 1) ? x2 : x3; + rhs(r, p.x); + const bool haveRoot = blst_fp2_sqrt(&p.y, &r); + (void)haveRoot; + assert(haveRoot); // guaranteed by the SW construction + + // Normalize the sign of y against the parity of t + blst_fp2 ny = p.y; + blst_fp2_cneg(&ny, &ny, true); + blst_bendian_from_fp(buf0, &p.y.fp[1]); + blst_bendian_from_fp(buf1, &ny.fp[1]); + if ((memcmp(buf0, buf1, 48) > 0) != parity) { + p.y = ny; } + return true; +} - fp2_free(nt); - fp2_free(w); - fp2_free(b); - bn_free(s_n3); - bn_free(s_n3m1o2); - fp2_free(x1); - fp2_free(x2); - fp2_free(x3); - fp2_free(rhs); - - fp2_free(s_n3p); - fp2_free(s_n3m1o2p); - fp2_free(ny); +// Reduce a 64-byte big-endian value mod p into an fp element, matching +// relic's bn_read_bin + fp_prime_conv: split as hi*2^256 + lo with both +// halves < 2^256 < p. +void FpFromBE64Wide(blst_fp& out, const uint8_t* be64) +{ + uint8_t padded[48] = {0}; + blst_fp hi, lo, c256; + + memcpy(padded + 16, be64, 32); + blst_fp_from_bendian(&hi, padded); + memcpy(padded + 16, be64 + 32, 32); + blst_fp_from_bendian(&lo, padded); + + // 2^256 mod p == 2^256 (p is 381 bits) + memset(padded, 0, 48); + padded[15] = 0x01; + blst_fp_from_bendian(&c256, padded); + + blst_fp_mul(&out, &hi, &c256); + blst_fp_add(&out, &out, &lo); } +} // anon namespace + +namespace bls { +void ep2_map_legacy(blst_p2* p, const uint8_t* msg, size_t len) +{ + if (len != 32) { + throw std::invalid_argument( + "ep2_map_legacy requires a 32-byte message hash"); + } -void ep2_map_legacy(ep2_t p, const uint8_t *msg, int len) { - bn_t t00; - bn_t t01; - bn_t t10; - bn_t t11; - fp_t t00p; - fp_t t01p; - fp_t t10p; - fp_t t11p; - fp2_t t0p; - fp2_t t1p; - ep2_t p0; - ep2_t p1; - - bn_null(t00); - bn_null(t01); - bn_null(t10); - bn_null(t11); - fp_null(t00p); - fp_null(t01p); - fp_null(t10p); - fp_null(t11p); - fp2_null(t0p); - fp2_null(t1p); - ep2_null(p1); - ep2_null(p0); - - RLC_TRY { - uint8_t input[RLC_MD_LEN + 8]; - if (len != RLC_MD_LEN) { - RLC_THROW(ERR_CAUGHT); - } - memcpy(input, msg, len); - // b"G2_0_c0" - input[RLC_MD_LEN + 0] = 0x47; // G - input[RLC_MD_LEN + 1] = 0x32; // 2 - input[RLC_MD_LEN + 2] = 0x5f; // _ - input[RLC_MD_LEN + 3] = 0x30; // 0 - input[RLC_MD_LEN + 4] = 0x5f; // _ - input[RLC_MD_LEN + 5] = 0x63; // c - input[RLC_MD_LEN + 6] = 0x30; // 0 - - bn_new(t00); - bn_new(t01); - bn_new(t10); - bn_new(t11); - fp_new(t00p); - fp_new(t01p); - fp_new(t10p); - fp_new(t11p); - fp2_new(t0p); - fp2_new(t1p); - ep2_new(p1); - ep2_new(p0); - - uint8_t t00Bytes[RLC_MD_LEN * 2]; - uint8_t t01Bytes[RLC_MD_LEN * 2]; - uint8_t t10Bytes[RLC_MD_LEN * 2]; - uint8_t t11Bytes[RLC_MD_LEN * 2]; - - // b"G2_0_c0" - input[RLC_MD_LEN + 7] = 0x00; // 0 - md_map(t00Bytes, input, RLC_MD_LEN + 8); - input[RLC_MD_LEN + 7] = 1; // 1 - md_map(t00Bytes + RLC_MD_LEN, input, RLC_MD_LEN + 8); - - // b"G2_0_c1" - input[RLC_MD_LEN + 6] = 0x31; // b"1" - input[RLC_MD_LEN + 7] = 0; // 0 - - md_map(t01Bytes, input, RLC_MD_LEN + 8); - input[RLC_MD_LEN + 7] = 1; // 1 - md_map(t01Bytes + RLC_MD_LEN, input, RLC_MD_LEN + 8); - - // b"G2_1_c0" - input[RLC_MD_LEN + 3] = 0x31; // b"1" - input[RLC_MD_LEN + 6] = 0x30; // b"0" - input[RLC_MD_LEN + 7] = 0; // 0 - md_map(t10Bytes, input, RLC_MD_LEN + 8); - input[RLC_MD_LEN + 7] = 1; // 1 - md_map(t10Bytes + RLC_MD_LEN, input, RLC_MD_LEN + 8); - - // b"G2_1_c1" - input[RLC_MD_LEN + 6] = 0x31; // b"1" - input[RLC_MD_LEN + 7] = 0; // 0 - md_map(t11Bytes, input, RLC_MD_LEN + 8); - input[RLC_MD_LEN + 7] = 1; // 1 - md_map(t11Bytes + RLC_MD_LEN, input, RLC_MD_LEN + 8); - - bn_read_bin(t00, t00Bytes, RLC_MD_LEN * 2); - bn_read_bin(t01, t01Bytes, RLC_MD_LEN * 2); - bn_read_bin(t10, t10Bytes, RLC_MD_LEN * 2); - bn_read_bin(t11, t11Bytes, RLC_MD_LEN * 2); - - fp_prime_conv(t00p, t00); - fp_prime_conv(t01p, t01); - fp_prime_conv(t10p, t10); - fp_prime_conv(t11p, t11); - - fp_copy(t0p[0], t00p); - fp_copy(t0p[1], t01p); - fp_copy(t1p[0], t10p); - fp_copy(t1p[1], t11p); - - ep2_sw_encode(p0, t0p); - ep2_sw_encode(p1, t1p); - ep2_add(p0, p0, p1); - /* Now, multiply by cofactor to get the correct group. */ - ep2_mul_cof_b12(p, p0); + uint8_t input[32 + 8]; + memcpy(input, msg, 32); + + uint8_t t00Bytes[64], t01Bytes[64], t10Bytes[64], t11Bytes[64]; + + const auto draw = [&input](uint8_t* out, char i, char j) { + // tag: "G2__c" followed by a counter byte + input[32 + 0] = 0x47; // G + input[32 + 1] = 0x32; // 2 + input[32 + 2] = 0x5f; // _ + input[32 + 3] = (uint8_t)i; + input[32 + 4] = 0x5f; // _ + input[32 + 5] = 0x63; // c + input[32 + 6] = (uint8_t)j; + input[32 + 7] = 0; + blst_sha256(out, input, 32 + 8); + input[32 + 7] = 1; + blst_sha256(out + 32, input, 32 + 8); + }; + + draw(t00Bytes, '0', '0'); + draw(t01Bytes, '0', '1'); + draw(t10Bytes, '1', '0'); + draw(t11Bytes, '1', '1'); + + blst_fp2 t0, t1; + FpFromBE64Wide(t0.fp[0], t00Bytes); + FpFromBE64Wide(t0.fp[1], t01Bytes); + FpFromBE64Wide(t1.fp[0], t10Bytes); + FpFromBE64Wide(t1.fp[1], t11Bytes); + + blst_p2_affine a0, a1; + const bool has0 = ep2_sw_encode(a0, t0); + const bool has1 = ep2_sw_encode(a1, t1); + + blst_p2 sum; + memset(&sum, 0x00, sizeof(blst_p2)); // infinity + if (has0) { + blst_p2_from_affine(&sum, &a0); } - RLC_CATCH_ANY { - RLC_THROW(ERR_CAUGHT); + if (has1) { + blst_p2_add_or_double_affine(&sum, &sum, &a1); } - RLC_FINALLY { - fp2_free(t0p); - fp2_free(t1p); - fp_free(t00p); - fp_free(t01p); - fp_free(t10p); - fp_free(t11p); - bn_free(t00); - bn_free(t01); - bn_free(t10); - bn_free(t11); - ep2_free(p0); - ep2_free(p1); + + // Clear the cofactor by multiplying with h_eff (equivalent to the + // psi-based clearing the relic implementation used). + uint8_t heffLE[sizeof(H_EFF_BE)]; + for (size_t i = 0; i < sizeof(H_EFF_BE); i++) { + heffLE[i] = H_EFF_BE[sizeof(H_EFF_BE) - 1 - i]; } + blst_p2_mult(p, &sum, heffLE, 636); } +} // namespace bls diff --git a/src/privatekey.cpp b/src/privatekey.cpp index d07246d8575e..51eb8acd9653 100644 --- a/src/privatekey.cpp +++ b/src/privatekey.cpp @@ -12,6 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + +#include + #include "bls.hpp" #include "legacy.hpp" @@ -28,81 +32,65 @@ PrivateKey PrivateKey::FromSeedBIP32(const Bytes& seed) { PrivateKey::PRIVATE_KEY_SIZE); // Hash the seed into sk - md_hmac(hash, seed.begin(), (int)seed.size(), hmacKey, sizeof(hmacKey)); - - bn_t order; - bn_new(order); - g1_get_ord(order); + Util::md_hmac(hash, seed.begin(), seed.size(), hmacKey, sizeof(hmacKey)); // Make sure private key is less than the curve order - bn_t* skBn = Util::SecAlloc(1); - bn_new(*skBn); - bn_read_bin(*skBn, hash, PrivateKey::PRIVATE_KEY_SIZE); - bn_mod_basic(*skBn, *skBn, order); - PrivateKey k; - bn_copy(k.keydata, *skBn); + blst_scalar_from_be_bytes(k.keydata, hash, PrivateKey::PRIVATE_KEY_SIZE); - Util::SecFree(skBn); Util::SecFree(hash); return k; } +// BLS12-381 group order r, big-endian. +// Taken from depends/blst/src/consts.c: BLS12_381_r = { 0xffffffff00000001, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48 } +// (little-endian limbs of the same number, with the comment z^4 - z^2 + 1, group order). + +static const uint8_t ORDER_BE[32] = { + 0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48, 0x33, 0x39, 0xd8, 0x08, + 0x09, 0xa1, 0xd8, 0x05, 0x53, 0xbd, 0xa4, 0x02, 0xff, 0xfe, 0x5b, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01}; + // Construct a private key from a bytearray. -PrivateKey PrivateKey::FromBytes(const Bytes& bytes, bool modOrder) +PrivateKey PrivateKey::FromBytes(const Bytes &bytes, bool modOrder) { if (bytes.size() != PRIVATE_KEY_SIZE) { throw std::invalid_argument("PrivateKey::FromBytes: Invalid size"); } PrivateKey k; - bn_read_bin(k.keydata, bytes.begin(), PrivateKey::PRIVATE_KEY_SIZE); - bn_t ord; - bn_new(ord); - g1_get_ord(ord); - if (modOrder) { - bn_mod_basic(k.keydata, k.keydata, ord); - } else { - if (bn_cmp(k.keydata, ord) > 0) { + if (modOrder) + // this allows any bytes to be input and does proper mod order + blst_scalar_from_be_bytes(k.keydata, bytes.begin(), bytes.size()); + else { + // Values strictly greater than the group order are rejected; the + // order itself is accepted, matching the relic-based + // implementation's bn_cmp(keydata, order) > 0 check. + if (memcmp(bytes.begin(), ORDER_BE, PRIVATE_KEY_SIZE) > 0) { throw std::invalid_argument( "PrivateKey byte data must be less than the group order"); } + blst_scalar_from_bendian(k.keydata, bytes.begin()); } return k; } // Construct a private key from a bytearray. -PrivateKey PrivateKey::FromByteVector(const std::vector bytes, bool modOrder) +PrivateKey PrivateKey::FromByteVector( + const std::vector bytes, + bool modOrder) { return PrivateKey::FromBytes(Bytes(bytes), modOrder); } -// Construct a private key from a bytearray. -PrivateKey PrivateKey::RandomPrivateKey() -{ - bn_t *r = Util::SecAlloc(1); - bn_new(*r); - bn_rand(*r, RLC_POS, 256); - PrivateKey k; - bn_copy(k.keydata, *r); - bn_t ord; - bn_new(ord); - g1_get_ord(ord); - bn_mod_basic(k.keydata, k.keydata, ord); - Util::SecFree(r); - return k; -} - -PrivateKey::PrivateKey() { - AllocateKeyData(); -}; +PrivateKey::PrivateKey() { AllocateKeyData(); }; // Construct a private key from another private key. PrivateKey::PrivateKey(const PrivateKey &privateKey) { privateKey.CheckKeyData(); AllocateKeyData(); - bn_copy(keydata, privateKey.keydata); + memcpy(keydata, privateKey.keydata, sizeof(blst_scalar)); } PrivateKey::PrivateKey(PrivateKey &&k) @@ -111,14 +99,11 @@ PrivateKey::PrivateKey(PrivateKey &&k) k.InvalidateCaches(); } -PrivateKey::~PrivateKey() -{ - DeallocateKeyData(); -} +PrivateKey::~PrivateKey() { DeallocateKeyData(); } void PrivateKey::DeallocateKeyData() { - if(keydata != nullptr) { + if (keydata != nullptr) { Util::SecFree(keydata); keydata = nullptr; } @@ -131,16 +116,16 @@ void PrivateKey::InvalidateCaches() fG2CacheValid = false; } -PrivateKey& PrivateKey::operator=(const PrivateKey& other) +PrivateKey &PrivateKey::operator=(const PrivateKey &other) { CheckKeyData(); other.CheckKeyData(); InvalidateCaches(); - bn_copy(keydata, other.keydata); + memcpy(keydata, other.keydata, sizeof(blst_scalar)); return *this; } -PrivateKey& PrivateKey::operator=(PrivateKey&& other) +PrivateKey &PrivateKey::operator=(PrivateKey &&other) { DeallocateKeyData(); keydata = std::exchange(other.keydata, nullptr); @@ -148,28 +133,28 @@ PrivateKey& PrivateKey::operator=(PrivateKey&& other) return *this; } -const G1Element& PrivateKey::GetG1Element() const +const G1Element &PrivateKey::GetG1Element() const { if (!fG1CacheValid) { CheckKeyData(); - g1_st *p = Util::SecAlloc(1); - g1_mul_gen(p, keydata); + blst_p1 *p = Util::SecAlloc(1); + blst_sk_to_pk_in_g1(p, keydata); - g1Cache = G1Element::FromNative(p); + g1Cache = G1Element::FromNative(*p); Util::SecFree(p); fG1CacheValid = true; } return g1Cache; } -const G2Element& PrivateKey::GetG2Element() const +const G2Element &PrivateKey::GetG2Element() const { if (!fG2CacheValid) { CheckKeyData(); - g2_st *q = Util::SecAlloc(1); - g2_mul_gen(q, keydata); + blst_p2 *q = Util::SecAlloc(1); + blst_sk_to_pk_in_g2(q, keydata); - g2Cache = G2Element::FromNative(q); + g2Cache = G2Element::FromNative(*q); Util::SecFree(q); fG2CacheValid = true; } @@ -184,11 +169,15 @@ bool PrivateKey::HasKeyData() const G1Element operator*(const G1Element &a, const PrivateKey &k) { k.CheckKeyData(); - g1_st* ans = Util::SecAlloc(1); + + blst_p1 *ans = Util::SecAlloc(1); a.ToNative(ans); - g1_mul(ans, ans, k.keydata); - G1Element ret = G1Element::FromNative(ans); + byte *bte = Util::SecAlloc(32); + blst_lendian_from_scalar(bte, k.keydata); + blst_p1_mult(ans, ans, bte, 256); + G1Element ret = G1Element::FromNative(*ans); Util::SecFree(ans); + Util::SecFree(bte); return ret; } @@ -197,40 +186,40 @@ G1Element operator*(const PrivateKey &k, const G1Element &a) { return a * k; } G2Element operator*(const G2Element &a, const PrivateKey &k) { k.CheckKeyData(); - g2_st* ans = Util::SecAlloc(1); + blst_p2 *ans = Util::SecAlloc(1); a.ToNative(ans); - g2_mul(ans, ans, k.keydata); - G2Element ret = G2Element::FromNative(ans); + byte *bte = Util::SecAlloc(32); + blst_lendian_from_scalar(bte, k.keydata); + blst_p2_mult(ans, ans, bte, 256); + G2Element ret = G2Element::FromNative(*ans); Util::SecFree(ans); + Util::SecFree(bte); return ret; } G2Element operator*(const PrivateKey &k, const G2Element &a) { return a * k; } -PrivateKey operator*(const PrivateKey& k, const bn_t& a) +PrivateKey operator*(const PrivateKey& k, const blst_scalar& a) { k.CheckKeyData(); - bn_t order; - bn_new(order); - g2_get_ord(order); - PrivateKey ret; - bn_mul_comba(ret.keydata, k.keydata, a); - bn_mod_basic(ret.keydata, ret.keydata, order); + blst_sk_mul_n_check(ret.keydata, k.keydata, &a); return ret; } -PrivateKey operator*(const bn_t& a, const PrivateKey& k) { return a * k; } +PrivateKey operator*(const blst_scalar& a, const PrivateKey& k) { return k * a; } -G2Element PrivateKey::GetG2Power(const G2Element& element) const +G2Element PrivateKey::GetG2Power(const G2Element &element) const { CheckKeyData(); - g2_st* q = Util::SecAlloc(1); + blst_p2 *q = Util::SecAlloc(1); element.ToNative(q); - g2_mul(q, q, keydata); - - const G2Element ret = G2Element::FromNative(q); + byte *bte = Util::SecAlloc(32); + blst_lendian_from_scalar(bte, keydata); + blst_p2_mult(q, q, bte, 255); + const G2Element ret = G2Element::FromNative(*q); Util::SecFree(q); + Util::SecFree(bte); return ret; } @@ -240,30 +229,29 @@ PrivateKey PrivateKey::Aggregate(std::vector const &privateKeys) throw std::length_error("Number of private keys must be at least 1"); } - bn_t order; - bn_new(order); - g1_get_ord(order); - PrivateKey ret; assert(ret.IsZero()); for (size_t i = 0; i < privateKeys.size(); i++) { privateKeys[i].CheckKeyData(); - bn_add(ret.keydata, ret.keydata, privateKeys[i].keydata); - bn_mod_basic(ret.keydata, ret.keydata, order); + blst_sk_add_n_check(ret.keydata, ret.keydata, privateKeys[i].keydata); } return ret; } -bool PrivateKey::IsZero() const { +bool PrivateKey::IsZero() const +{ CheckKeyData(); - return bn_is_zero(keydata); + blst_scalar zro; + memset(&zro, 0x00, sizeof(blst_scalar)); + + return memcmp(keydata, &zro, sizeof(blst_scalar)) == 0; } bool operator==(const PrivateKey &a, const PrivateKey &b) { a.CheckKeyData(); b.CheckKeyData(); - return bn_cmp(a.keydata, b.keydata) == RLC_EQ; + return memcmp(a.keydata, b.keydata, sizeof(blst_scalar)) == 0; } bool operator!=(const PrivateKey &a, const PrivateKey &b) { return !(a == b); } @@ -274,17 +262,21 @@ void PrivateKey::Serialize(uint8_t *buffer) const throw std::runtime_error("PrivateKey::Serialize buffer invalid"); } CheckKeyData(); - bn_write_bin(buffer, PrivateKey::PRIVATE_KEY_SIZE, keydata); + // blst_bendian_from_scalar converts through a temporary limb vector and + // securely wipes it, which costs more than the serialization itself; + // the scalar's native bytes are little-endian, so copy and reverse. + blst_lendian_from_scalar(buffer, keydata); + std::reverse(buffer, buffer + PRIVATE_KEY_SIZE); } -std::vector PrivateKey::Serialize(const bool fLegacy) const +std::vector PrivateKey::Serialize() const { std::vector data(PRIVATE_KEY_SIZE); Serialize(data.data()); return data; } -std::array PrivateKey::SerializeToArray(bool fLegacy) const +std::array PrivateKey::SerializeToArray() const { std::array data{}; Serialize(data.data()); @@ -299,35 +291,34 @@ G2Element PrivateKey::SignG2( const bool fLegacy) const { CheckKeyData(); + if (fLegacy && len != BLS::MESSAGE_HASH_LEN) { + throw std::invalid_argument("legacy signing requires a 32-byte message hash"); + } - g2_t pt; - g2_null(pt); - g2_new(pt); - + blst_p2 *pt = Util::SecAlloc(1); if (fLegacy) { - ep2_map_legacy(pt, msg, BLS::MESSAGE_HASH_LEN); + ep2_map_legacy(pt, msg, len); } else { - ep2_map_dst(pt, msg, len, dst, dst_len); + blst_hash_to_g2(pt, msg, len, dst, dst_len, nullptr, 0); } - - g2_mul(pt, pt, keydata); - G2Element ret = G2Element::FromNative(pt); - g2_free(pt); + blst_sign_pk_in_g1(pt, pt, keydata); + G2Element ret = G2Element::FromNative(*pt); + Util::SecFree(pt); return ret; } void PrivateKey::AllocateKeyData() { assert(!keydata); - keydata = Util::SecAlloc(1); - keydata->alloc = RLC_BN_SIZE; - bn_zero(keydata); + keydata = Util::SecAlloc(1); + memset(keydata, 0x00, sizeof(blst_scalar)); } void PrivateKey::CheckKeyData() const { if (keydata == nullptr) { - throw std::runtime_error("PrivateKey::CheckKeyData keydata not initialized"); + throw std::runtime_error( + "PrivateKey::CheckKeyData keydata not initialized"); } } diff --git a/src/schemes.cpp b/src/schemes.cpp index af33f1f50eee..506ea9eee729 100644 --- a/src/schemes.cpp +++ b/src/schemes.cpp @@ -12,6 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "schemes.hpp" + +#include + #include #include #include @@ -19,9 +23,7 @@ #include "bls.hpp" #include "elements.hpp" -#include "schemes.hpp" #include "hdkeys.hpp" -#include "bn_helpers.hpp" using std::string; using std::vector; @@ -29,11 +31,8 @@ using std::vector; namespace bls { template -static void HashPubKeys(bn_t* computedTs, size_t nPubKeys, GetBytesFn getBytes) +static void HashPubKeys(blst_scalar* computedTs, size_t nPubKeys, GetBytesFn getBytes) { - BnGuard order; - g2_get_ord(order.val); - std::vector vecBuffer(nPubKeys * G1Element::SIZE); for (size_t i = 0; i < nPubKeys; i++) { @@ -53,18 +52,19 @@ static void HashPubKeys(bn_t* computedTs, size_t nPubKeys, GetBytesFn getBytes) std::memcpy(buffer + 4, pkHash, 32); Util::Hash256(hash, buffer, 4 + 32); - bn_read_bin(computedTs[i], hash, 32); - bn_mod_basic(computedTs[i], computedTs[i], order.val); + // reduces the hash mod the group order, like the former + // bn_read_bin + bn_mod + blst_scalar_from_be_bytes(&computedTs[i], hash, 32); } } -enum InvariantResult { BAD=false, GOOD=true, CONTINUE }; +enum InvariantResult { BAD = false, GOOD = true, CONTINUE }; // Enforce argument invariants for Agg Sig Verification InvariantResult VerifyAggregateSignatureArguments( const size_t nPubKeys, const size_t nMessages, - const G2Element &signature) + const G2Element& signature) { if (nPubKeys == 0) { return (nMessages == 0 && signature == G2Element() ? GOOD : BAD); @@ -78,79 +78,99 @@ InvariantResult VerifyAggregateSignatureArguments( /* These are all for the min-pubkey-size variant. TODO : analogs for min-signature-size */ -const std::string BasicSchemeMPL::CIPHERSUITE_ID = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_"; -const std::string AugSchemeMPL::CIPHERSUITE_ID = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_"; -const std::string PopSchemeMPL::CIPHERSUITE_ID = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; -const std::string PopSchemeMPL::POP_CIPHERSUITE_ID = "BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; +const std::string BasicSchemeMPL::CIPHERSUITE_ID = + "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_"; +const std::string AugSchemeMPL::CIPHERSUITE_ID = + "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_"; +const std::string PopSchemeMPL::CIPHERSUITE_ID = + "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; +const std::string PopSchemeMPL::POP_CIPHERSUITE_ID = + "BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"; -PrivateKey CoreMPL::KeyGen(const vector& seed) { +PrivateKey CoreMPL::KeyGen(const vector& seed) +{ return HDKeys::KeyGen(seed); } -PrivateKey CoreMPL::KeyGen(const Bytes& seed) { - return HDKeys::KeyGen(seed); -} +PrivateKey CoreMPL::KeyGen(const Bytes& seed) { return HDKeys::KeyGen(seed); } -vector CoreMPL::SkToPk(const PrivateKey &seckey) +vector CoreMPL::SkToPk(const PrivateKey& seckey) { return seckey.GetG1Element().Serialize(); } -G1Element CoreMPL::SkToG1(const PrivateKey &seckey) +G1Element CoreMPL::SkToG1(const PrivateKey& seckey) { return seckey.GetG1Element(); } -G2Element CoreMPL::Sign(const PrivateKey &seckey, const vector &message) +G2Element CoreMPL::Sign( + const PrivateKey& seckey, + const vector& message) { return CoreMPL::Sign(seckey, Bytes(message)); } G2Element CoreMPL::Sign(const PrivateKey& seckey, const Bytes& message) { - return seckey.SignG2(message.begin(), message.size(), (const uint8_t*)strCiphersuiteId.c_str(), strCiphersuiteId.length()); + return seckey.SignG2( + message.begin(), + message.size(), + (const uint8_t*)strCiphersuiteId.c_str(), + strCiphersuiteId.length()); } -bool CoreMPL::Verify(const vector &pubkey, - const vector &message, // unhashed - const vector &signature) +bool CoreMPL::Verify( + const vector& pubkey, + const vector& message, // unhashed + const vector& signature) { - return CoreMPL::Verify(G1Element::FromBytes(Bytes(pubkey)), - Bytes(message), - G2Element::FromBytes(Bytes(signature))); + return CoreMPL::Verify(Bytes(pubkey), Bytes(message), Bytes(signature)); } -bool CoreMPL::Verify(const Bytes& pubkey, const Bytes& message, const Bytes& signature) +bool CoreMPL::Verify( + const Bytes& pubkey, + const Bytes& message, + const Bytes& signature) { - return CoreMPL::Verify(G1Element::FromBytes(pubkey), message, G2Element::FromBytes(signature)); + G1Element pubkeyElement; + G2Element signatureElement; + try { + pubkeyElement = G1Element::FromBytes(pubkey); + signatureElement = G2Element::FromBytes(signature); + } catch (...) { + return false; + } + return CoreMPL::Verify(pubkeyElement, message, signatureElement); } -bool CoreMPL::Verify(const G1Element &pubkey, - const vector &message, // unhashed - const G2Element &signature) +bool CoreMPL::Verify( + const G1Element& pubkey, + const vector& message, // unhashed + const G2Element& signature) { return CoreMPL::Verify(pubkey, Bytes(message), signature); } -bool CoreMPL::Verify(const G1Element& pubkey, const Bytes& message, const G2Element& signature) +bool CoreMPL::Verify( + const G1Element& pubkey, + const Bytes& message, + const G2Element& signature) { + // Keep the relic-era semantics rather than blst_core_verify: elements are + // gated by IsValid() and the check is the product of pairings. const G2Element hashedPoint = G2Element::FromMessage(message, (const uint8_t*)strCiphersuiteId.c_str(), strCiphersuiteId.length()); - std::array g1s; - std::array g2s; - - G1Element::Generator().Negate().ToNative(g1s[0]); - if (!pubkey.IsValid()) { + if (!pubkey.IsValid() || pubkey == G1Element()) { return false; } - if (!signature.IsValid()) { + if (!signature.IsValid() || signature == G2Element()) { return false; } - pubkey.ToNative(g1s[1]); - signature.ToNative(g2s[0]); - hashedPoint.ToNative(g2s[1]); - return CoreMPL::NativeVerify(g1s.data(), g2s.data(), 2); + const std::vector g1s{G1Element::Generator().Negate(), pubkey}; + const std::vector g2s{signature, hashedPoint}; + return CoreMPL::NativeVerify(g1s, g2s); } std::array CoreMPL::Aggregate(const vector> &signatures) @@ -173,7 +193,7 @@ std::array CoreMPL::Aggregate(const vector& sig return CoreMPL::Aggregate(elements).SerializeToArray(); } -G2Element CoreMPL::Aggregate(const vector &signatures) +G2Element CoreMPL::Aggregate(const vector& signatures) { G2Element aggregated; for (const G2Element& signature : signatures) { @@ -182,7 +202,7 @@ G2Element CoreMPL::Aggregate(const vector &signatures) return aggregated; } -G1Element CoreMPL::Aggregate(const vector &publicKeys) +G1Element CoreMPL::Aggregate(const vector& publicKeys) { G1Element aggregated; for (const G1Element& publicKey : publicKeys) { @@ -193,13 +213,13 @@ G1Element CoreMPL::Aggregate(const vector &publicKeys) G2Element CoreMPL::AggregateSecure(std::vector const &vecPublicKeys, std::vector const &vecSignatures, - const Bytes& message, + const Bytes& /*message*/, const bool fLegacy) { if (vecSignatures.size() != vecPublicKeys.size()) { throw std::invalid_argument("LegacySchemeMPL::AggregateSigs sigs.size() != pubKeys.size()"); } - BnArrayGuard computedTs(vecPublicKeys.size()); + std::vector computedTs(vecPublicKeys.size()); std::vector, const G2Element*>> vecSorted(vecPublicKeys.size()); for (size_t i = 0; i < vecPublicKeys.size(); i++) { vecSorted[i] = std::make_pair(vecPublicKeys[i].SerializeToArray(fLegacy), &vecSignatures[i]); @@ -208,7 +228,7 @@ G2Element CoreMPL::AggregateSecure(std::vector const &vecPublicKeys, return std::memcmp(a.first.data(), b.first.data(), G1Element::SIZE) < 0; }); - HashPubKeys(computedTs.data, vecSorted.size(), + HashPubKeys(computedTs.data(), vecSorted.size(), [&](size_t i) { return vecSorted[i].first.data(); }); // Raise all signatures to power of the corresponding t's and aggregate the results into aggSig @@ -232,7 +252,16 @@ bool CoreMPL::VerifySecure(const std::vector& vecPublicKeys, const G2Element& signature, const Bytes& message, const bool fLegacy) { - BnArrayGuard computedTs(vecPublicKeys.size()); + for (const auto& pk : vecPublicKeys) { + if (!pk.IsValid() || pk == G1Element()) { + return false; + } + } + if (!signature.IsValid() || signature == G2Element()) { + return false; + } + + std::vector computedTs(vecPublicKeys.size()); std::vector> vecSorted(vecPublicKeys.size()); for (size_t i = 0; i < vecPublicKeys.size(); i++) { vecSorted[i] = vecPublicKeys[i].SerializeToArray(fLegacy); @@ -241,7 +270,7 @@ bool CoreMPL::VerifySecure(const std::vector& vecPublicKeys, return std::memcmp(a.data(), b.data(), G1Element::SIZE) < 0; }); - HashPubKeys(computedTs.data, vecSorted.size(), + HashPubKeys(computedTs.data(), vecSorted.size(), [&](size_t i) { return vecSorted[i].data(); }); G1Element publicKey; @@ -259,132 +288,178 @@ bool CoreMPL::VerifySecure(const std::vector& vecPublicKeys, return CoreMPL::VerifySecure(vecPublicKeys, signature, message, false); } -bool CoreMPL::AggregateVerify(const vector> &pubkeys, - const vector> &messages, // unhashed - const vector &signature) +bool CoreMPL::AggregateVerify( + const vector>& pubkeys, + const vector>& messages, // unhashed + const vector& signature) { const std::vector vecPubKeyBytes(pubkeys.begin(), pubkeys.end()); const std::vector vecMessagesBytes(messages.begin(), messages.end()); - return CoreMPL::AggregateVerify(vecPubKeyBytes, vecMessagesBytes, Bytes(signature)); + return CoreMPL::AggregateVerify( + vecPubKeyBytes, vecMessagesBytes, Bytes(signature)); } -bool CoreMPL::AggregateVerify(const vector& pubkeys, - const vector& messages, // unhashed - const Bytes& signature) +bool CoreMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, // unhashed + const Bytes& signature) { const size_t nPubKeys = pubkeys.size(); - const G2Element signatureElement = G2Element::FromBytes(signature); - const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signatureElement); + G2Element signatureElement; + try { + signatureElement = G2Element::FromBytes(signature); + } catch (...) { + return false; + } + const auto arg_check = VerifyAggregateSignatureArguments( + nPubKeys, messages.size(), signatureElement); if (arg_check != CONTINUE) { return arg_check; } vector pubkeyElements; pubkeyElements.reserve(nPubKeys); - for (size_t i = 0; i < nPubKeys; ++i) { - pubkeyElements.push_back(G1Element::FromBytes(pubkeys[i])); + try { + for (size_t i = 0; i < nPubKeys; ++i) { + pubkeyElements.push_back(G1Element::FromBytes(pubkeys[i])); + } + } catch (...) { + return false; } return CoreMPL::AggregateVerify(pubkeyElements, messages, signatureElement); } -bool CoreMPL::AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature) +bool CoreMPL::AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature) { - return CoreMPL::AggregateVerify(pubkeys, std::vector(messages.begin(), messages.end()), signature); + return CoreMPL::AggregateVerify( + pubkeys, + std::vector(messages.begin(), messages.end()), + signature); } -bool CoreMPL::AggregateVerify(const vector& pubkeys, - const vector &messages, - const G2Element& signature) +bool CoreMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature) { const size_t nPubKeys = pubkeys.size(); - const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); + const auto arg_check = + VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); if (arg_check != CONTINUE) { return arg_check; } - std::vector vecG1(nPubKeys + 1); - std::vector vecG2(nPubKeys + 1); - G1Element::Generator().Negate().ToNative(&vecG1[0]); - if (!signature.IsValid()) { + if (!signature.IsValid() || signature == G2Element()) { return false; } - signature.ToNative(&vecG2[0]); + std::vector vecG1; + std::vector vecG2; + vecG1.reserve(nPubKeys + 1); + vecG2.reserve(nPubKeys + 1); + vecG1.push_back(G1Element::Generator().Negate()); + vecG2.push_back(signature); for (size_t i = 0; i < nPubKeys; ++i) { - if (!pubkeys[i].IsValid()) { + if (!pubkeys[i].IsValid() || pubkeys[i] == G1Element()) { return false; } - pubkeys[i].ToNative(&vecG1[i + 1]); - G2Element::FromMessage(messages[i], (const uint8_t*)strCiphersuiteId.c_str(), strCiphersuiteId.length()).ToNative(&vecG2[i + 1]); + vecG1.push_back(pubkeys[i]); + vecG2.push_back(G2Element::FromMessage(messages[i], (const uint8_t*)strCiphersuiteId.c_str(), strCiphersuiteId.length())); } - return CoreMPL::NativeVerify((g1_t*)vecG1.data(), (g2_t*)vecG2.data(), nPubKeys + 1); + return CoreMPL::NativeVerify(vecG1, vecG2); } -bool CoreMPL::NativeVerify(g1_t *pubkeys, g2_t *mappedHashes, size_t length) +bool CoreMPL::NativeVerify(const std::vector& g1s, + const std::vector& g2s) { - gt_t target, candidate, tmpPairing; - fp12_zero(target); - fp_set_dig(target[0][0][0], 1); - fp12_zero(candidate); - fp_set_dig(candidate[0][0][0], 1); - - // prod e(pubkey[i], hash[i]) * e(-g1, aggSig) - // Performs pubKeys.size() pairings, 250 at a time - - for (size_t i = 0; i < length; i += 250) { - size_t numPairings = std::min((length - i), (size_t)250); - pc_map_sim(tmpPairing, pubkeys + i, mappedHashes + i, numPairings); - fp12_mul(candidate, candidate, tmpPairing); - } - - // 1 =? prod e(pubkey[i], hash[i]) * e(-g1, aggSig) - if (gt_cmp(target, candidate) != RLC_EQ || core_get()->code != RLC_OK) { - core_get()->code = RLC_OK; + // 1 =? prod e(g1s[i], g2s[i]) + // A pairing with the point at infinity on either side contributes the + // identity, matching relic's pc_map_sim. + if (g1s.size() != g2s.size()) { return false; } - BLS::CheckRelicErrors(); - return true; + std::vector ps; + std::vector qs; + ps.reserve(g1s.size()); + qs.reserve(g2s.size()); + for (size_t i = 0; i < g1s.size(); ++i) { + blst_p1 p; + blst_p2 q; + g1s[i].ToNative(&p); + g2s[i].ToNative(&q); + // Infinity is decided on the projective points: blst's affine form + // cannot tell (0, 0) apart from infinity. + if (blst_p1_is_inf(&p) || blst_p2_is_inf(&q)) { + continue; + } + blst_p1_to_affine(&ps.emplace_back(), &p); + blst_p2_to_affine(&qs.emplace_back(), &q); + } + + blst_fp12 candidate = *blst_fp12_one(); + if (!ps.empty()) { + // One shared Miller loop for all pairs, like relic's pc_map_sim. + std::vector pPtrs(ps.size()); + std::vector qPtrs(qs.size()); + for (size_t i = 0; i < ps.size(); ++i) { + pPtrs[i] = &ps[i]; + qPtrs[i] = &qs[i]; + } + blst_miller_loop_n(&candidate, qPtrs.data(), pPtrs.data(), ps.size()); + } + + blst_final_exp(&candidate, &candidate); + return blst_fp12_is_one(&candidate); } -PrivateKey CoreMPL::DeriveChildSk(const PrivateKey& sk, uint32_t index) { +PrivateKey CoreMPL::DeriveChildSk(const PrivateKey& sk, uint32_t index) +{ return HDKeys::DeriveChildSk(sk, index); } -PrivateKey CoreMPL::DeriveChildSkUnhardened(const PrivateKey& sk, uint32_t index) { +PrivateKey CoreMPL::DeriveChildSkUnhardened( + const PrivateKey& sk, + uint32_t index) +{ return HDKeys::DeriveChildSkUnhardened(sk, index); } -G1Element CoreMPL::DeriveChildPkUnhardened(const G1Element& pk, uint32_t index) { +G1Element CoreMPL::DeriveChildPkUnhardened(const G1Element& pk, uint32_t index) +{ return HDKeys::DeriveChildG1Unhardened(pk, index); } -bool BasicSchemeMPL::AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature) +bool BasicSchemeMPL::AggregateVerify( + const vector>& pubkeys, + const vector>& messages, + const vector& signature) { - const size_t nPubKeys = pubkeys.size(); - auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), G2Element::FromByteVector(signature)); - if (arg_check != CONTINUE) { - return arg_check; - } - - const std::set> setMessages(messages.begin(), messages.end()); - if (setMessages.size() != nPubKeys) { - return false; - } - return CoreMPL::AggregateVerify(pubkeys, messages, signature); + const std::vector vecPubKeyBytes(pubkeys.begin(), pubkeys.end()); + const std::vector vecMessagesBytes(messages.begin(), messages.end()); + return BasicSchemeMPL::AggregateVerify( + vecPubKeyBytes, vecMessagesBytes, Bytes(signature)); } -bool BasicSchemeMPL::AggregateVerify(const vector& pubkeys, - const vector& messages, - const Bytes& signature) +bool BasicSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, + const Bytes& signature) { const size_t nPubKeys = pubkeys.size(); - const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), G2Element::FromBytes(signature)); - if (arg_check != CONTINUE) return arg_check; + G2Element signatureElement; + try { + signatureElement = G2Element::FromBytes(signature); + } catch (...) { + return false; + } + const auto arg_check = VerifyAggregateSignatureArguments( + nPubKeys, messages.size(), signatureElement); + if (arg_check != CONTINUE) + return arg_check; std::set> setMessages; for (const auto& message : messages) { @@ -393,33 +468,49 @@ bool BasicSchemeMPL::AggregateVerify(const vector& pubkeys, if (setMessages.size() != nPubKeys) { return false; } - return CoreMPL::AggregateVerify(pubkeys, messages, signature); + + vector pubkeyElements; + pubkeyElements.reserve(nPubKeys); + try { + for (size_t i = 0; i < nPubKeys; ++i) { + pubkeyElements.push_back(G1Element::FromBytes(pubkeys[i])); + } + } catch (...) { + return false; + } + return CoreMPL::AggregateVerify(pubkeyElements, messages, signatureElement); } -bool BasicSchemeMPL::AggregateVerify(const vector &pubkeys, - const vector> &messages, - const G2Element &signature) +bool BasicSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature) { const size_t nPubKeys = pubkeys.size(); - const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); + const auto arg_check = + VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); if (arg_check != CONTINUE) { return arg_check; } - const std::set> setMessages(messages.begin(), messages.end()); + const std::set> setMessages( + messages.begin(), messages.end()); if (setMessages.size() != nPubKeys) { return false; } return CoreMPL::AggregateVerify(pubkeys, messages, signature); } -bool BasicSchemeMPL::AggregateVerify(const vector& pubkeys, - const vector &messages, - const G2Element& signature) +bool BasicSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature) { const size_t nPubKeys = pubkeys.size(); - const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); - if (arg_check != CONTINUE) return arg_check; + const auto arg_check = + VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); + if (arg_check != CONTINUE) + return arg_check; std::set> setMessages; for (const auto& message : messages) { @@ -431,7 +522,9 @@ bool BasicSchemeMPL::AggregateVerify(const vector& pubkeys, return CoreMPL::AggregateVerify(pubkeys, messages, signature); } -G2Element AugSchemeMPL::Sign(const PrivateKey &seckey, const vector &message) +G2Element AugSchemeMPL::Sign( + const PrivateKey& seckey, + const vector& message) { return AugSchemeMPL::Sign(seckey, message, seckey.GetG1Element()); } @@ -442,17 +535,19 @@ G2Element AugSchemeMPL::Sign(const PrivateKey& seckey, const Bytes& message) } // Used for prepending different augMessage -G2Element AugSchemeMPL::Sign(const PrivateKey &seckey, - const vector &message, - const G1Element &prepend_pk) +G2Element AugSchemeMPL::Sign( + const PrivateKey& seckey, + const vector& message, + const G1Element& prepend_pk) { return AugSchemeMPL::Sign(seckey, Bytes(message), prepend_pk); } // Used for prepending different augMessage -G2Element AugSchemeMPL::Sign(const PrivateKey& seckey, - const Bytes& message, - const G1Element& prepend_pk) +G2Element AugSchemeMPL::Sign( + const PrivateKey& seckey, + const Bytes& message, + const G1Element& prepend_pk) { vector augMessage = prepend_pk.Serialize(); augMessage.reserve(augMessage.size() + message.size()); @@ -460,9 +555,10 @@ G2Element AugSchemeMPL::Sign(const PrivateKey& seckey, return CoreMPL::Sign(seckey, augMessage); } -bool AugSchemeMPL::Verify(const vector &pubkey, - const vector &message, - const vector &signature) +bool AugSchemeMPL::Verify( + const vector& pubkey, + const vector& message, + const vector& signature) { vector augMessage(pubkey); augMessage.reserve(augMessage.size() + message.size()); @@ -470,9 +566,10 @@ bool AugSchemeMPL::Verify(const vector &pubkey, return CoreMPL::Verify(pubkey, augMessage, signature); } -bool AugSchemeMPL::Verify(const Bytes& pubkey, - const Bytes& message, - const Bytes& signature) +bool AugSchemeMPL::Verify( + const Bytes& pubkey, + const Bytes& message, + const Bytes& signature) { vector augMessage(pubkey.begin(), pubkey.end()); augMessage.reserve(augMessage.size() + message.size()); @@ -480,16 +577,18 @@ bool AugSchemeMPL::Verify(const Bytes& pubkey, return CoreMPL::Verify(pubkey, Bytes(augMessage), Bytes(signature)); } -bool AugSchemeMPL::Verify(const G1Element &pubkey, - const vector &message, - const G2Element &signature) +bool AugSchemeMPL::Verify( + const G1Element& pubkey, + const vector& message, + const G2Element& signature) { return AugSchemeMPL::Verify(pubkey, Bytes(message), signature); } -bool AugSchemeMPL::Verify(const G1Element& pubkey, - const Bytes& message, - const G2Element& signature) +bool AugSchemeMPL::Verify( + const G1Element& pubkey, + const Bytes& message, + const G2Element& signature) { vector augMessage = pubkey.Serialize(); augMessage.reserve(augMessage.size() + message.size()); @@ -497,21 +596,31 @@ bool AugSchemeMPL::Verify(const G1Element& pubkey, return CoreMPL::Verify(pubkey, augMessage, signature); } -bool AugSchemeMPL::AggregateVerify(const vector> &pubkeys, - const vector> &messages, - const vector &signature) +bool AugSchemeMPL::AggregateVerify( + const vector>& pubkeys, + const vector>& messages, + const vector& signature) { std::vector vecPubKeyBytes(pubkeys.begin(), pubkeys.end()); std::vector vecMessagesBytes(messages.begin(), messages.end()); - return AugSchemeMPL::AggregateVerify(vecPubKeyBytes, vecMessagesBytes, Bytes(signature)); + return AugSchemeMPL::AggregateVerify( + vecPubKeyBytes, vecMessagesBytes, Bytes(signature)); } -bool AugSchemeMPL::AggregateVerify(const vector& pubkeys, - const vector& messages, - const Bytes& signature) +bool AugSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, + const Bytes& signature) { size_t nPubKeys = pubkeys.size(); - auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), G2Element::FromBytes(signature)); + G2Element signatureElement; + try { + signatureElement = G2Element::FromBytes(signature); + } catch (...) { + return false; + } + auto arg_check = VerifyAggregateSignatureArguments( + nPubKeys, messages.size(), signatureElement); if (arg_check != CONTINUE) { return arg_check; } @@ -524,30 +633,34 @@ bool AugSchemeMPL::AggregateVerify(const vector& pubkeys, aug.insert(aug.end(), messages[i].begin(), messages[i].end()); } - std::vector vecAugMessageBytes(augMessages.begin(), augMessages.end()); + std::vector vecAugMessageBytes( + augMessages.begin(), augMessages.end()); return CoreMPL::AggregateVerify(pubkeys, vecAugMessageBytes, signature); } -bool AugSchemeMPL::AggregateVerify(const vector& pubkeys, - const vector>& messages, - const G2Element& signature) +bool AugSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector>& messages, + const G2Element& signature) { std::vector vecMessagesBytes(messages.begin(), messages.end()); return AugSchemeMPL::AggregateVerify(pubkeys, vecMessagesBytes, signature); } -bool AugSchemeMPL::AggregateVerify(const vector& pubkeys, - const vector& messages, - const G2Element& signature) +bool AugSchemeMPL::AggregateVerify( + const vector& pubkeys, + const vector& messages, + const G2Element& signature) { size_t nPubKeys = pubkeys.size(); - auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); + auto arg_check = + VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); if (arg_check != CONTINUE) { return arg_check; } vector> augMessages(nPubKeys); - for (int i = 0; i < nPubKeys; ++i) { + for (size_t i = 0; i < nPubKeys; ++i) { vector& aug = augMessages[i]; vector&& pubkey = pubkeys[i].Serialize(); aug.reserve(pubkey.size() + messages[i].size()); @@ -558,84 +671,142 @@ bool AugSchemeMPL::AggregateVerify(const vector& pubkeys, return CoreMPL::AggregateVerify(pubkeys, augMessages, signature); } -G2Element PopSchemeMPL::PopProve(const PrivateKey &seckey) -{ - const G1Element& pk = seckey.GetG1Element(); - const G2Element hashedKey = G2Element::FromMessage(pk.SerializeToArray(), (const uint8_t *)POP_CIPHERSUITE_ID.c_str(), POP_CIPHERSUITE_ID.length()); - return seckey.GetG2Power(hashedKey); -} +bool AugSchemeMPL::VerifySecure(const std::vector& vecPublicKeys, + const G2Element& signature, + const Bytes& message) { + // AugSchemeMPL::Sign hashes H(pk_i || msg) per signer. We cannot + // combine into a single pubkey because each signer's hash is different. + // Instead, pass T-weighted individual pubkeys with their augmented + // messages to CoreMPL::AggregateVerify. + for (const auto& pk : vecPublicKeys) { + if (!pk.IsValid() || pk == G1Element()) { + return false; + } + } + if (!signature.IsValid() || signature == G2Element()) { + return false; + } + std::vector computedTs(vecPublicKeys.size()); + std::vector> vecSorted(vecPublicKeys.size()); + for (size_t i = 0; i < vecPublicKeys.size(); i++) { + vecSorted[i] = vecPublicKeys[i].SerializeToArray(false); + } + std::sort(vecSorted.begin(), vecSorted.end(), [](const auto& a, const auto& b) -> bool { + return std::memcmp(a.data(), b.data(), G1Element::SIZE) < 0; + }); + + HashPubKeys(computedTs.data(), vecSorted.size(), + [&](size_t i) { return vecSorted[i].data(); }); + + std::vector weightedPks(vecSorted.size()); + std::vector> augMessages(vecSorted.size()); + for (size_t i = 0; i < vecSorted.size(); ++i) { + G1Element g1 = G1Element::FromBytes(Bytes(vecSorted[i]), false); + weightedPks[i] = g1 * computedTs[i]; + augMessages[i].reserve(G1Element::SIZE + message.size()); + augMessages[i].insert(augMessages[i].end(), vecSorted[i].begin(), vecSorted[i].end()); + augMessages[i].insert(augMessages[i].end(), message.begin(), message.end()); + } + + return CoreMPL::AggregateVerify(weightedPks, augMessages, signature); +} -bool PopSchemeMPL::PopVerify(const G1Element &pubkey, const G2Element &signature_proof) +G2Element PopSchemeMPL::PopProve(const PrivateKey& seckey) { - const G2Element hashedPoint = G2Element::FromMessage(pubkey.SerializeToArray(), (const uint8_t*)POP_CIPHERSUITE_ID.c_str(), POP_CIPHERSUITE_ID.length()); + std::array pubkey_bytes = seckey.GetG1Element().SerializeToArray(); - g1_t g1s[2]; - g2_t g2s[2]; + return seckey.SignG2( + pubkey_bytes.data(), + pubkey_bytes.size(), + (const uint8_t*)POP_CIPHERSUITE_ID.c_str(), + POP_CIPHERSUITE_ID.length()); +} - if (!pubkey.IsValid()) { +bool PopSchemeMPL::PopVerify( + const G1Element& pubkey, + const G2Element& signature_proof) +{ + // Same semantics as CoreMPL::Verify (and the relic implementation): the + // elements are gated by IsValid() and the check is the product of + // pairings rather than blst_core_verify. + if (!pubkey.IsValid() || pubkey == G1Element()) { return false; } - if (!signature_proof.IsValid()) { + if (!signature_proof.IsValid() || signature_proof == G2Element()) { return false; } - G1Element::Generator().Negate().ToNative(g1s[0]); - pubkey.ToNative(g1s[1]); - signature_proof.ToNative(g2s[0]); - hashedPoint.ToNative(g2s[1]); - - return CoreMPL::NativeVerify(g1s, g2s, 2); + const std::array pubkey_bytes = pubkey.SerializeToArray(); + const G2Element hashedPoint = G2Element::FromMessage(Bytes(pubkey_bytes), (const uint8_t*)POP_CIPHERSUITE_ID.c_str(), POP_CIPHERSUITE_ID.length()); + const std::vector g1s{G1Element::Generator().Negate(), pubkey}; + const std::vector g2s{signature_proof, hashedPoint}; + return CoreMPL::NativeVerify(g1s, g2s); } -bool PopSchemeMPL::PopVerify(const vector &pubkey, const vector &proof) +bool PopSchemeMPL::PopVerify( + const vector& pubkey, + const vector& proof) { return PopSchemeMPL::PopVerify(Bytes(pubkey), Bytes(proof)); } bool PopSchemeMPL::PopVerify(const Bytes& pubkey, const Bytes& proof) { - const G2Element hashedPoint = G2Element::FromMessage(pubkey, (const uint8_t*)POP_CIPHERSUITE_ID.c_str(), POP_CIPHERSUITE_ID.length()); - - g1_t g1s[2]; - g2_t g2s[2]; - - G1Element::Generator().Negate().ToNative(g1s[0]); - G1Element::FromBytes(pubkey).ToNative(g1s[1]); - G2Element::FromBytes(proof).ToNative(g2s[0]); - hashedPoint.ToNative(g2s[1]); - - return CoreMPL::NativeVerify(g1s, g2s, 2); + G1Element pk; + G2Element proofElement; + try { + pk = G1Element::FromBytes(pubkey); + proofElement = G2Element::FromBytes(proof); + } catch (...) { + return false; + } + return PopSchemeMPL::PopVerify(pk, proofElement); } -bool PopSchemeMPL::FastAggregateVerify(const vector &pubkeys, - const vector &message, - const G2Element &signature) +bool PopSchemeMPL::FastAggregateVerify( + const vector& pubkeys, + const vector& message, + const G2Element& signature) { - return PopSchemeMPL::FastAggregateVerify(pubkeys, Bytes(message), signature); + return PopSchemeMPL::FastAggregateVerify( + pubkeys, Bytes(message), signature); } -bool PopSchemeMPL::FastAggregateVerify(const vector& pubkeys, - const Bytes& message, - const G2Element& signature) +bool PopSchemeMPL::FastAggregateVerify( + const vector& pubkeys, + const Bytes& message, + const G2Element& signature) { if (pubkeys.size() == 0) { return false; } - // No VerifyAggregateSignatureArguments checks required here as we have exactly one pubkey and one message. + if (!signature.IsValid() || signature == G2Element()) { + return false; + } + for (const auto& pk : pubkeys) { + if (!pk.IsValid() || pk == G1Element()) { + return false; + } + } + // No VerifyAggregateSignatureArguments checks required here as we have + // exactly one pubkey and one message. return CoreMPL::Verify(CoreMPL::Aggregate(pubkeys), message, signature); } -bool PopSchemeMPL::FastAggregateVerify(const vector> &pubkeys, - const vector &message, - const vector &signature) +bool PopSchemeMPL::FastAggregateVerify( + const vector>& pubkeys, + const vector& message, + const vector& signature) { const std::vector vecPubKeyBytes(pubkeys.begin(), pubkeys.end()); - return PopSchemeMPL::FastAggregateVerify(vecPubKeyBytes, Bytes(message), Bytes(signature)); + return PopSchemeMPL::FastAggregateVerify( + vecPubKeyBytes, Bytes(message), Bytes(signature)); } -bool PopSchemeMPL::FastAggregateVerify(const vector& pubkeys, - const Bytes& message, - const Bytes& signature) +bool PopSchemeMPL::FastAggregateVerify( + const vector& pubkeys, + const Bytes& message, + const Bytes& signature) { const size_t nPubKeys = pubkeys.size(); if (nPubKeys == 0) { @@ -643,11 +814,18 @@ bool PopSchemeMPL::FastAggregateVerify(const vector& pubkeys, } vector pkelements; - for (size_t i = 0; i < nPubKeys; ++i) { - pkelements.push_back(G1Element::FromBytes(pubkeys[i])); + G2Element signatureElement; + try { + for (size_t i = 0; i < nPubKeys; ++i) { + pkelements.push_back(G1Element::FromBytes(pubkeys[i])); + } + signatureElement = G2Element::FromBytes(signature); + } catch (...) { + return false; } - return PopSchemeMPL::FastAggregateVerify(pkelements, message, G2Element::FromBytes(signature)); + return PopSchemeMPL::FastAggregateVerify( + pkelements, message, signatureElement); } G2Element LegacySchemeMPL::Sign(const PrivateKey& seckey, const Bytes& message) @@ -657,15 +835,19 @@ G2Element LegacySchemeMPL::Sign(const PrivateKey& seckey, const Bytes& message) bool LegacySchemeMPL::Verify(const G1Element &pubkey, const Bytes& message, const G2Element &signature) { - g1_t g1s[2]; - g2_t g2s[2]; - - G1Element::Generator().Negate().ToNative(g1s[0]); - pubkey.ToNative(g1s[1]); - signature.ToNative(g2s[0]); - G2Element::FromMessage(message, nullptr, 0, true).ToNative(g2s[1]); - - return CoreMPL::NativeVerify(g1s, g2s, 2); + // the legacy scheme is defined on 32-byte message hashes + if (message.size() != BLS::MESSAGE_HASH_LEN) { + return false; + } + if (!pubkey.IsValid() || pubkey == G1Element()) { + return false; + } + if (!signature.IsValid() || signature == G2Element()) { + return false; + } + const std::vector g1s{G1Element::Generator().Negate(), pubkey}; + const std::vector g2s{signature, G2Element::FromMessage(message, nullptr, 0, true)}; + return CoreMPL::NativeVerify(g1s, g2s); } G2Element LegacySchemeMPL::AggregateSecure(std::vector const &vecPublicKeys, @@ -688,17 +870,27 @@ bool LegacySchemeMPL::AggregateVerify(const vector &pubkeys, const auto arg_check = VerifyAggregateSignatureArguments(nPubKeys, messages.size(), signature); if (arg_check != CONTINUE) return arg_check; - std::vector vecG1(nPubKeys + 1); - std::vector vecG2(nPubKeys + 1); - G1Element::Generator().Negate().ToNative(&vecG1[0]); - signature.ToNative(&vecG2[0]); - + if (!signature.IsValid() || signature == G2Element()) { + return false; + } + std::vector vecG1; + std::vector vecG2; + vecG1.reserve(nPubKeys + 1); + vecG2.reserve(nPubKeys + 1); + vecG1.push_back(G1Element::Generator().Negate()); + vecG2.push_back(signature); for (size_t i = 0; i < nPubKeys; ++i) { - pubkeys[i].ToNative(&vecG1[i + 1]); - G2Element::FromMessage(messages[i], nullptr, 0, true).ToNative(&vecG2[i + 1]); + // the legacy scheme is defined on 32-byte message hashes + if (messages[i].size() != BLS::MESSAGE_HASH_LEN) { + return false; + } + if (!pubkeys[i].IsValid() || pubkeys[i] == G1Element()) { + return false; + } + vecG1.push_back(pubkeys[i]); + vecG2.push_back(G2Element::FromMessage(messages[i], nullptr, 0, true)); } - - return CoreMPL::NativeVerify((g1_t*)vecG1.data(), (g2_t*)vecG2.data(), nPubKeys + 1); + return CoreMPL::NativeVerify(vecG1, vecG2); } } // end namespace bls diff --git a/src/test-bench.cpp b/src/test-bench.cpp index 20bbbb443952..0cc476790624 100644 --- a/src/test-bench.cpp +++ b/src/test-bench.cpp @@ -13,22 +13,27 @@ // limitations under the License. #include + #include "bls.hpp" #include "test-utils.hpp" -extern "C" { -#include "relic.h" -} - using std::string; using std::vector; -using std::cout; -using std::endl; using namespace bls; +std::vector wjbgetRandomSeed() +{ + uint8_t buf[32]; + + for (int i = 0; i < 32; i++) buf[i] = rand(); -void benchSigs() { + std::vector ret(buf, buf + 32); + return ret; +} + +void benchSigs() +{ string testName = "Signing"; const int numIters = 5000; PrivateKey sk = BasicSchemeMPL().KeyGen(getRandomSeed()); @@ -42,21 +47,22 @@ void benchSigs() { endStopwatch(testName, start, numIters); } -void benchVerification() { +void benchVerification() +{ string testName = "Verification"; const int numIters = 1000; PrivateKey sk = BasicSchemeMPL().KeyGen(getRandomSeed()); G1Element pk = sk.GetG1Element(); - std::vector sigs; + vector pkBytes = pk.Serialize(); for (int i = 0; i < numIters; i++) { uint8_t message[4]; Util::IntToFourBytes(message, i); vector messageBytes(message, message + 4); - sigs.push_back(BasicSchemeMPL().Sign(sk, messageBytes)); + G2Element sig = BasicSchemeMPL().Sign(sk, messageBytes); + sigs.push_back(sig); } - auto start = startStopwatch(); for (int i = 0; i < numIters; i++) { uint8_t message[4]; @@ -68,7 +74,8 @@ void benchVerification() { endStopwatch(testName, start, numIters); } -void benchBatchVerification() { +void benchBatchVerification() +{ const int numIters = 10000; vector> sig_bytes; @@ -116,7 +123,8 @@ void benchBatchVerification() { endStopwatch("Batch verification", start, numIters); } -void benchSerialize() { +void benchSerialize() +{ const int numIters = 5000000; PrivateKey sk = BasicSchemeMPL().KeyGen(getRandomSeed()); G1Element pk = sk.GetG1Element(); @@ -142,7 +150,8 @@ void benchSerialize() { endStopwatch("Serialize G2Element", start, numIters); } -void benchSerializeToArray() { +void benchSerializeToArray() +{ const int numIters = 5000000; PrivateKey sk = BasicSchemeMPL().KeyGen(getRandomSeed()); G1Element pk = sk.GetG1Element(); @@ -168,7 +177,8 @@ void benchSerializeToArray() { endStopwatch("SerializeToArray G2Element", start, numIters); } -int main(int argc, char* argv[]) { +int main() +{ benchSigs(); benchVerification(); benchBatchVerification(); diff --git a/src/test-vectors.hpp b/src/test-vectors.hpp new file mode 100644 index 000000000000..430d7ec877e5 --- /dev/null +++ b/src/test-vectors.hpp @@ -0,0 +1,575 @@ +// Copyright (c) 2026 The Dash Core developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef SRC_TEST_VECTORS_HPP_ +#define SRC_TEST_VECTORS_HPP_ + +// Reference consensus vectors. +// +// GenerateReferenceVectors() deterministically exercises the public dashbls +// API - legacy and basic serialization (including malformed input), legacy +// signing, secure aggregation, threshold signing, extended keys and the +// private key edge cases - and emits one "name=value" line per result. +// +// test-vectors/reference.txt holds the output of the relic-based library; +// runtest compares the current library against it line by line, and +// tools/vectorgen.cpp regenerates it. Only the public API is used so the +// same code builds against any backend. + +#include +#include +#include +#include +#include +#include + +#include "bls.hpp" + +namespace bls_test_vectors { + +using namespace bls; +using std::vector; + +struct Emitter { + std::vector lines; + + static std::string hex(const uint8_t* p, size_t n) + { + static const char* digits = "0123456789abcdef"; + std::string s; + s.reserve(n * 2); + for (size_t i = 0; i < n; i++) { + s.push_back(digits[p[i] >> 4]); + s.push_back(digits[p[i] & 0x0f]); + } + return s; + } + + void raw(const std::string& line) { lines.push_back(line); } + void dump(const std::string& name, const vector& v) { lines.push_back(name + "=" + hex(v.data(), v.size())); } + template + void dump(const std::string& name, const std::array& v) { lines.push_back(name + "=" + hex(v.data(), N)); } + void dumpb(const std::string& name, bool v) { lines.push_back(name + "=" + (v ? "1" : "0")); } + void dumpu(const std::string& name, uint32_t v) + { + char buf[16]; + snprintf(buf, sizeof(buf), "%08x", v); + lines.push_back(name + "=" + buf); + } + void exc(const std::string& name) { lines.push_back(name + "=EXC"); } +}; + +inline vector seedN(int i) +{ + vector s(32); + for (int j = 0; j < 32; j++) s[j] = (uint8_t)(0x11 * (i + 1) + j * 7); + return s; +} + +inline vector hashN(int i) +{ + vector h(32); + for (int j = 0; j < 32; j++) h[j] = (uint8_t)(0xA5 ^ (i * 31 + j * 13)); + return h; +} + +inline std::string tag(const char* base, int i) +{ + char buf[96]; + snprintf(buf, sizeof(buf), "%s.%d", base, i); + return std::string(buf); +} + +// ---------------------------------------------------------------- section A/B +inline void KeysAndSignatures(Emitter& e) +{ + LegacySchemeMPL legacy; + BasicSchemeMPL basic; + + for (int i = 0; i < 8; i++) { + PrivateKey sk = basic.KeyGen(seedN(i)); + e.dump(tag("A.sk", i), sk.Serialize()); + + G1Element pk = sk.GetG1Element(); + e.dump(tag("A.pk.basic", i), pk.Serialize(false)); + e.dump(tag("A.pk.legacy", i), pk.Serialize(true)); + e.dumpu(tag("A.fp.basic", i), pk.GetFingerprint(false)); + e.dumpu(tag("A.fp.legacy", i), pk.GetFingerprint(true)); + e.dump(tag("A.skG2.basic", i), sk.GetG2Element().Serialize(false)); + e.dump(tag("A.skG2.legacy", i), sk.GetG2Element().Serialize(true)); + + // round-trips through both codecs + e.dump(tag("A.pk.rt.legacy", i), + G1Element::FromBytes(Bytes(pk.Serialize(true)), true).Serialize(true)); + e.dump(tag("A.pk.rt.basic", i), + G1Element::FromBytes(Bytes(pk.Serialize(false)), false).Serialize(false)); + + // legacy sign over a 32-byte hash; serialize under both codecs + vector h = hashN(i); + G2Element lsig = legacy.Sign(sk, Bytes(h)); + e.dump(tag("B.lsig.legacy", i), lsig.Serialize(true)); + e.dump(tag("B.lsig.basic", i), lsig.Serialize(false)); + e.dumpb(tag("B.lverify", i), legacy.Verify(pk, Bytes(h), lsig)); + // wrong message must fail + vector h2 = hashN(i + 100); + e.dumpb(tag("B.lverify.bad", i), legacy.Verify(pk, Bytes(h2), lsig)); + // legacy sig round-trip through legacy codec + e.dump(tag("B.lsig.rt", i), + G2Element::FromBytes(Bytes(lsig.Serialize(true)), true).Serialize(true)); + + // basic scheme (arbitrary-length message) + vector msg = {(uint8_t)i, 1, 2, 3, 200, 255}; + G2Element bsig = basic.Sign(sk, msg); + e.dump(tag("B.bsig.basic", i), bsig.Serialize(false)); + e.dump(tag("B.bsig.legacy", i), bsig.Serialize(true)); + e.dumpb(tag("B.bverify", i), basic.Verify(pk, msg, bsig)); + + // EIP-2333 derivation + e.dump(tag("A.child.hard", i), basic.DeriveChildSk(sk, 0x8000002a).Serialize()); + e.dump(tag("A.child.soft", i), basic.DeriveChildSkUnhardened(sk, 1337).Serialize()); + } +} + +// ---------------------------------------------------------------- section C/D +inline void SecureAggregation(Emitter& e) +{ + LegacySchemeMPL legacy; + BasicSchemeMPL basic; + + for (int n : {1, 2, 3, 10}) { + vector sks; + vector pks; + vector lsigs, bsigs; + vector h = hashN(n); + for (int i = 0; i < n; i++) { + sks.push_back(basic.KeyGen(seedN(200 + n * 16 + i))); + pks.push_back(sks.back().GetG1Element()); + lsigs.push_back(legacy.Sign(sks.back(), Bytes(h))); + bsigs.push_back(basic.Sign(sks.back(), Bytes(h))); + } + G2Element lagg = legacy.AggregateSecure(pks, lsigs, Bytes(h)); + e.dump(tag("C.aggsec.legacy", n), lagg.Serialize(true)); + e.dumpb(tag("C.versec.legacy", n), legacy.VerifySecure(pks, lagg, Bytes(h))); + + G2Element bagg = basic.AggregateSecure(pks, bsigs, Bytes(h)); + e.dump(tag("C.aggsec.basic", n), bagg.Serialize(false)); + e.dumpb(tag("C.versec.basic", n), basic.VerifySecure(pks, bagg, Bytes(h))); + + // cross checks must fail + e.dumpb(tag("C.versec.legacy.bad", n), + legacy.VerifySecure(pks, lagg, Bytes(hashN(n + 50)))); + + // plain aggregation + e.dump(tag("C.agg.G2", n), basic.Aggregate(bsigs).Serialize(false)); + e.dump(tag("C.agg.G1", n), basic.Aggregate(pks).Serialize(false)); + e.dump(tag("C.agg.sk", n), PrivateKey::Aggregate(sks).Serialize()); + } + + // legacy multi-message AggregateVerify + { + int n = 4; + vector sks; + vector pks; + vector sigs; + vector> msgs; + for (int i = 0; i < n; i++) { + sks.push_back(basic.KeyGen(seedN(300 + i))); + pks.push_back(sks.back().GetG1Element()); + msgs.push_back(hashN(300 + i)); + sigs.push_back(legacy.Sign(sks.back(), Bytes(msgs.back()))); + } + G2Element agg = basic.Aggregate(sigs); // plain point sum + vector msgRefs; + for (auto& m : msgs) msgRefs.push_back(Bytes(m)); + e.dump("D.lagg", agg.Serialize(true)); + e.dumpb("D.laggverify", legacy.AggregateVerify(pks, msgRefs, agg)); + vector badRefs; + badRefs.push_back(Bytes(msgs[1])); + for (size_t i = 1; i < msgs.size(); i++) badRefs.push_back(Bytes(msgs[i])); + e.dumpb("D.laggverify.bad", legacy.AggregateVerify(pks, badRefs, agg)); + } +} + +// ------------------------------------------------------------------ section E +inline void ThresholdVectors(Emitter& e) +{ + BasicSchemeMPL basic; + const int m = 3, n = 5; + + // polynomial coefficients (the "master" keys) + vector coeffs; + vector vvec; + vector sigCoeffs; + vector h = hashN(77); + for (int i = 0; i < m; i++) { + coeffs.push_back(basic.KeyGen(seedN(400 + i))); + vvec.push_back(coeffs.back().GetG1Element()); + sigCoeffs.push_back(Threshold::Sign(coeffs[i], Bytes(h))); + } + e.dump("E.mastersig", Threshold::Sign(coeffs[0], Bytes(h)).Serialize(true)); + e.dumpb("E.masterverify", + Threshold::Verify(vvec[0], Bytes(h), Threshold::Sign(coeffs[0], Bytes(h)))); + + vector> ids; + for (int i = 0; i < n; i++) ids.push_back(hashN(500 + i)); + + vector skShares; + vector sigShares; + for (int i = 0; i < n; i++) { + PrivateKey sh = Threshold::PrivateKeyShare(coeffs, Bytes(ids[i])); + skShares.push_back(sh); + e.dump(tag("E.skshare", i), sh.Serialize()); + G1Element pkShare = Threshold::PublicKeyShare(vvec, Bytes(ids[i])); + e.dump(tag("E.pkshare", i), pkShare.Serialize(true)); + e.dumpb(tag("E.sharematch", i), pkShare == sh.GetG1Element()); + G2Element sigShare = Threshold::SignatureShare(sigCoeffs, Bytes(ids[i])); + e.dump(tag("E.sigshare.poly", i), sigShare.Serialize(true)); + G2Element sigShare2 = Threshold::Sign(sh, Bytes(h)); + e.dump(tag("E.sigshare.sign", i), sigShare2.Serialize(true)); + sigShares.push_back(sigShare2); + } + + // recover from first m shares + vector mSk(skShares.begin(), skShares.begin() + m); + vector mSig(sigShares.begin(), sigShares.begin() + m); + vector mIds; + for (int i = 0; i < m; i++) mIds.push_back(Bytes(ids[i])); + + PrivateKey skRec = Threshold::PrivateKeyRecover(mSk, mIds); + e.dump("E.skrecover", skRec.Serialize()); + e.dumpb("E.skrecover.match", skRec == coeffs[0]); + + vector mPk; + for (int i = 0; i < m; i++) mPk.push_back(skShares[i].GetG1Element()); + e.dump("E.pkrecover", Threshold::PublicKeyRecover(mPk, mIds).Serialize(true)); + + G2Element sigRec = Threshold::SignatureRecover(mSig, mIds); + e.dump("E.sigrecover", sigRec.Serialize(true)); + e.dumpb("E.sigrecover.verify", Threshold::Verify(vvec[0], Bytes(h), sigRec)); + + // recovery from a different share subset must give the same signature + vector mSig2(sigShares.begin() + 1, sigShares.begin() + 1 + m); + vector mIds2; + for (int i = 1; i < 1 + m; i++) mIds2.push_back(Bytes(ids[i])); + e.dumpb("E.sigrecover.same", + Threshold::SignatureRecover(mSig2, mIds2) == sigRec); +} + +// ------------------------------------------------------------------ section F +inline void ExtendedKeys(Emitter& e) +{ + vector seed = seedN(600); + ExtendedPrivateKey esk = ExtendedPrivateKey::FromSeed(Bytes(seed)); + e.dump("F.esk", esk.Serialize()); + e.dump("F.esk.pk.legacy", esk.GetPublicKey().Serialize(true)); + e.dump("F.esk.pk.basic", esk.GetPublicKey().Serialize(false)); + e.dump("F.esk.chaincode", esk.GetChainCode().Serialize()); + + // legacy derivation chain (fLegacy defaults true on these APIs) + ExtendedPrivateKey c1l = esk.PrivateChild(1, true); + ExtendedPrivateKey c2l = c1l.PrivateChild(0x8000002a, true); + e.dump("F.child.legacy", c2l.Serialize()); + e.dump("F.child.legacy.sk", c2l.GetPrivateKey().Serialize()); + + // modern derivation chain + ExtendedPrivateKey c1b = esk.PrivateChild(1, false); + ExtendedPrivateKey c2b = c1b.PrivateChild(0x8000002a, false); + e.dump("F.child.basic", c2b.Serialize()); + e.dump("F.child.basic.sk", c2b.GetPrivateKey().Serialize()); + + // extended public keys and public derivation + ExtendedPublicKey epkl = esk.GetExtendedPublicKey(true); + e.dump("F.epk.legacy", epkl.Serialize(true)); + ExtendedPublicKey epkb = esk.GetExtendedPublicKey(false); + e.dump("F.epk.basic", epkb.Serialize(false)); + e.dump("F.epk.child.legacy", epkl.PublicChild(1, true).Serialize(true)); + e.dump("F.epk.child.basic", epkb.PublicChild(1, false).Serialize(false)); + e.dumpb("F.pubpriv.match.legacy", + epkl.PublicChild(1, true).GetPublicKey() == + esk.PrivateChild(1, true).GetPublicKey()); + + // round-trips + e.dump("F.esk.rt", + ExtendedPrivateKey::FromBytes(Bytes(esk.Serialize())).Serialize()); + e.dump("F.epk.rt.legacy", + ExtendedPublicKey::FromBytes(Bytes(epkl.Serialize(true)), true).Serialize(true)); +} + +// ------------------------------------------------------------------ section G +inline void PrivateKeyEdges(Emitter& e) +{ + // in-range key round-trip, both modOrder values + PrivateKey sk = BasicSchemeMPL().KeyGen(seedN(700)); + vector raw = sk.Serialize(); + e.dump("G.inrange.mod0", PrivateKey::FromBytes(Bytes(raw), false).Serialize()); + e.dump("G.inrange.mod1", PrivateKey::FromBytes(Bytes(raw), true).Serialize()); + + // value >= group order: modOrder=true reduces, modOrder=false throws + vector big(32, 0xff); + try { e.dump("G.big.mod1", PrivateKey::FromBytes(Bytes(big), true).Serialize()); } + catch (const std::exception&) { e.exc("G.big.mod1"); } + try { e.dump("G.big.mod0", PrivateKey::FromBytes(Bytes(big), false).Serialize()); } + catch (const std::exception&) { e.exc("G.big.mod0"); } + + // the group order itself, and order-1 + // r = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 + vector order = { + 0x73, 0xed, 0xa7, 0x53, 0x29, 0x9d, 0x7d, 0x48, 0x33, 0x39, 0xd8, + 0x08, 0x09, 0xa1, 0xd8, 0x05, 0x53, 0xbd, 0xa4, 0x02, 0xff, 0xfe, + 0x5b, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01}; + try { e.dump("G.order.mod1", PrivateKey::FromBytes(Bytes(order), true).Serialize()); } + catch (const std::exception&) { e.exc("G.order.mod1"); } + try { e.dump("G.order.mod0", PrivateKey::FromBytes(Bytes(order), false).Serialize()); } + catch (const std::exception&) { e.exc("G.order.mod0"); } + vector orderm1 = order; + orderm1[31] = 0x00; + try { e.dump("G.orderm1.mod0", PrivateKey::FromBytes(Bytes(orderm1), false).Serialize()); } + catch (const std::exception&) { e.exc("G.orderm1.mod0"); } + + // zero key + vector zero(32, 0x00); + try { + PrivateKey z = PrivateKey::FromBytes(Bytes(zero), false); + e.dump("G.zero.sk", z.Serialize()); + e.dump("G.zero.pk", z.GetG1Element().Serialize(false)); + } catch (const std::exception&) { e.exc("G.zero.sk"); } + + // FromSeedBIP32 + e.dump("G.bip32seed", PrivateKey::FromSeedBIP32(Bytes(seedN(701))).Serialize()); + + // DH key exchange: sk_a * pk_b == sk_b * pk_a + PrivateKey a = BasicSchemeMPL().KeyGen(seedN(702)); + PrivateKey b = BasicSchemeMPL().KeyGen(seedN(703)); + G1Element dh = a * b.GetG1Element(); + e.dump("G.dh", dh.Serialize(false)); + e.dumpb("G.dh.sym", dh == (b * a.GetG1Element())); +} + +// ------------------------------------------------------------------ section H +// Crafted byte strings through every decode path. For each: either the +// round-trip hex (proving accept + canonical re-encoding) or EXC. +inline void decodeProbe(Emitter& e, const std::string& name, const vector& in, bool fLegacy) +{ + bool isG1 = in.size() == 48; + try { + if (isG1) { + G1Element el = G1Element::FromBytes(Bytes(in), fLegacy); + e.dump(name + ".ser", el.Serialize(fLegacy)); + e.dumpb(name + ".valid", el.IsValid()); + } else { + G2Element el = G2Element::FromBytes(Bytes(in), fLegacy); + e.dump(name + ".ser", el.Serialize(fLegacy)); + e.dumpb(name + ".valid", el.IsValid()); + } + } catch (const std::exception&) { e.exc(name); } +} + +inline void decodeProbeUnchecked(Emitter& e, const std::string& name, const vector& in, bool fLegacy) +{ + bool isG1 = in.size() == 48; + try { + if (isG1) { + G1Element el = G1Element::FromBytesUnchecked(Bytes(in), fLegacy); + e.dump(name + ".ser", el.Serialize(fLegacy)); + e.dumpb(name + ".valid", el.IsValid()); + } else { + G2Element el = G2Element::FromBytesUnchecked(Bytes(in), fLegacy); + e.dump(name + ".ser", el.Serialize(fLegacy)); + e.dumpb(name + ".valid", el.IsValid()); + } + } catch (const std::exception&) { e.exc(name); } +} + +inline vector fromHex(const char* hex) +{ + vector out; + for (size_t i = 0; hex[i] && hex[i + 1]; i += 2) { + auto nyb = [](char c) -> int { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + return c - 'A' + 10; + }; + out.push_back((uint8_t)((nyb(hex[i]) << 4) | nyb(hex[i + 1]))); + } + return out; +} + +inline void EdgeDecodes(Emitter& e) +{ + BasicSchemeMPL basic; + PrivateKey sk = basic.KeyGen(seedN(800)); + G1Element pk = sk.GetG1Element(); + G2Element sig = LegacySchemeMPL().Sign(sk, Bytes(hashN(800))); + + // 1. canonical infinity, both sizes, both modes + vector inf48(48, 0); + inf48[0] = 0xc0; + vector inf96(96, 0); + inf96[0] = 0xc0; + decodeProbe(e, "H.g1.inf.basic", inf48, false); + decodeProbe(e, "H.g1.inf.legacy", inf48, true); + decodeProbe(e, "H.g2.inf.basic", inf96, false); + decodeProbe(e, "H.g2.inf.legacy", inf96, true); + + // 2. non-canonical infinity (0xc0 with a trailing nonzero byte) + vector badInf48 = inf48; + badInf48[47] = 0x01; + vector badInf96 = inf96; + badInf96[95] = 0x01; + decodeProbe(e, "H.g1.badinf.basic", badInf48, false); + decodeProbe(e, "H.g1.badinf.legacy", badInf48, true); + decodeProbe(e, "H.g2.badinf.basic", badInf96, false); + decodeProbe(e, "H.g2.badinf.legacy", badInf96, true); + + // 3. all zeros + decodeProbe(e, "H.g1.zeros.basic", vector(48, 0), false); + decodeProbe(e, "H.g1.zeros.legacy", vector(48, 0), true); + decodeProbe(e, "H.g2.zeros.basic", vector(96, 0), false); + decodeProbe(e, "H.g2.zeros.legacy", vector(96, 0), true); + decodeProbeUnchecked(e, "H.g1.zeros.legacy.unchk", vector(48, 0), true); + decodeProbeUnchecked(e, "H.g2.zeros.legacy.unchk", vector(96, 0), true); + + // 4. x >= field prime (0xff filler), with/without legacy sign bit + vector ff48(48, 0xff); + vector ff96(96, 0xff); + decodeProbe(e, "H.g1.ff.basic", ff48, false); + decodeProbe(e, "H.g1.ff.legacy", ff48, true); + decodeProbe(e, "H.g2.ff.basic", ff96, false); + decodeProbe(e, "H.g2.ff.legacy", ff96, true); + vector ff48low = ff48; + ff48low[0] = 0x1f; // below prime top byte range but x still >= p + decodeProbe(e, "H.g1.fflow.legacy", ff48low, true); + + // 5. legacy bytes fed to the modern decoder and vice versa + decodeProbe(e, "H.g1.legacyAsBasic", pk.Serialize(true), false); + decodeProbe(e, "H.g1.basicAsLegacy", pk.Serialize(false), true); + decodeProbe(e, "H.g2.legacyAsBasic", sig.Serialize(true), false); + decodeProbe(e, "H.g2.basicAsLegacy", sig.Serialize(false), true); + + // 6. valid encodings with flipped sign bit (the negated point) + vector pkl = pk.Serialize(true); + pkl[0] ^= 0x80; + decodeProbe(e, "H.g1.negated.legacy", pkl, true); + vector pkb = pk.Serialize(false); + pkb[0] ^= 0x20; + decodeProbe(e, "H.g1.negated.basic", pkb, false); + + // 7. on-curve but non-subgroup points (found by scanning small x with a + // blst helper; each x satisfies y^2 = x^3 + 4 (+4i) with the point + // outside the r-torsion). Encodings below use y = the "smaller" root + // (sign bit 0), in each codec's byte layout. + // G1: x = 4 -> not in subgroup. + vector nsG1(48, 0); + nsG1[47] = 0x04; + decodeProbe(e, "H.g1.nonsub.legacy", nsG1, true); + decodeProbeUnchecked(e, "H.g1.nonsub.legacy.unchk", nsG1, true); + vector nsG1b = nsG1; + nsG1b[0] |= 0x80; // modern compression flag + decodeProbe(e, "H.g1.nonsub.basic", nsG1b, false); + decodeProbeUnchecked(e, "H.g1.nonsub.basic.unchk", nsG1b, false); + // G2: x = (1, 0) -> not in subgroup (legacy layout: c0 || c1). + vector nsG2(96, 0); + nsG2[47] = 0x01; + decodeProbe(e, "H.g2.nonsub.legacy", nsG2, true); + decodeProbeUnchecked(e, "H.g2.nonsub.legacy.unchk", nsG2, true); + // modern layout: c1 || c0 with flags on byte 0 + vector nsG2b(96, 0); + nsG2b[95] = 0x01; + nsG2b[0] |= 0x80; + decodeProbe(e, "H.g2.nonsub.basic", nsG2b, false); + decodeProbeUnchecked(e, "H.g2.nonsub.basic.unchk", nsG2b, false); + + // 8. x not on curve (no square root exists): x = 1 for G1 + vector noc(48, 0); + noc[47] = 0x01; + decodeProbe(e, "H.g1.nocurve.legacy", noc, true); + vector nocb = noc; + nocb[0] |= 0x80; + decodeProbe(e, "H.g1.nocurve.basic", nocb, false); + + // 9. modern G2 with the reserved top bits of byte 48 set + vector flag48 = sig.Serialize(false); + flag48[48] |= 0xe0; + decodeProbe(e, "H.g2.flag48.basic", flag48, false); + + // 10. wrong length + try { + G1Element::FromBytes(Bytes(vector(47, 0)), false); + e.raw("H.len47=NOEXC"); + } catch (const std::exception&) { e.exc("H.len47"); } + + // 11. legacy sign bit set on degenerate x values (exercises the + // sqrt-failure and x>=p fallback paths with stored sign = 1) + vector s1(48, 0); + s1[0] = 0x80; + s1[47] = 0x01; // x = 1, not on curve + decodeProbe(e, "H.g1.nocurve.sign.legacy", s1, true); + vector sp(48, 0xff); + sp[0] = 0x9f; // sign bit + x = 0x1fff... >= p + decodeProbe(e, "H.g1.overp.sign.legacy", sp, true); + vector g2s(96, 0); + g2s[0] = 0x80; + g2s[47] = 0x02; // x = (2, 0), sign bit set + decodeProbe(e, "H.g2.x2.sign.legacy", g2s, true); + vector g2s3(96, 0); + g2s3[0] = 0x80; + g2s3[47] = 0x03; // x = (3, 0), sign bit set + decodeProbe(e, "H.g2.x3.sign.legacy", g2s3, true); + vector g2nc(96, 0); + g2nc[47] = 0x02; // x = (2, 0), sign bit clear + decodeProbe(e, "H.g2.x2.legacy", g2nc, true); + vector g2sp(96, 0xff); + g2sp[0] = 0x9f; // c0 >= p (sign set), c1 >= p + decodeProbe(e, "H.g2.overp.sign.legacy", g2sp, true); +} + +// ------------------------------------------------------------------ section I +// Verification semantics with infinity elements and empty inputs. +inline void VerifyEdges(Emitter& e) +{ + BasicSchemeMPL basic; + LegacySchemeMPL legacy; + vector msg = {9, 9, 9}; + vector h = hashN(900); + + e.dumpb("I.basic.verify.infinf", basic.Verify(G1Element(), msg, G2Element())); + e.dumpb("I.legacy.verify.infinf", legacy.Verify(G1Element(), Bytes(h), G2Element())); + + PrivateKey sk = basic.KeyGen(seedN(900)); + G2Element sig = basic.Sign(sk, msg); + e.dumpb("I.basic.verify.infpk", basic.Verify(G1Element(), msg, sig)); + e.dumpb("I.basic.verify.infsig", basic.Verify(sk.GetG1Element(), msg, G2Element())); + + // AggregateVerify argument invariants + e.dumpb("I.aggver.empty.infsig", + basic.AggregateVerify(vector{}, vector{}, G2Element())); + e.dumpb("I.aggver.empty.realsig", + basic.AggregateVerify(vector{}, vector{}, sig)); + e.dumpb("I.aggver.mismatch", + basic.AggregateVerify(vector{sk.GetG1Element()}, vector{}, sig)); + + // VerifySecure with an infinity pubkey in the list + vector pks = {sk.GetG1Element(), G1Element()}; + e.dumpb("I.versec.withinf", basic.VerifySecure(pks, sig, Bytes(h))); +} + + +inline std::vector GenerateReferenceVectors() +{ + Emitter e; + e.raw("# dashbls reference vectors v1"); + KeysAndSignatures(e); + SecureAggregation(e); + ThresholdVectors(e); + ExtendedKeys(e); + PrivateKeyEdges(e); + EdgeDecodes(e); + VerifyEdges(e); + e.raw("# end"); + return e.lines; +} + +} // namespace bls_test_vectors + +#endif // SRC_TEST_VECTORS_HPP_ diff --git a/src/test.cpp b/src/test.cpp index 0bc920edf594..d6572cbe111d 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -19,18 +19,25 @@ #include "bls.hpp" #include -extern "C" { -#include "relic.h" -} #include "test-utils.hpp" -using std::cout; -using std::endl; +#include "test-vectors.hpp" + +#include +#include + using std::string; using std::vector; using namespace bls; -void TestHKDF(string ikm_hex, string salt_hex, string info_hex, string prk_expected_hex, string okm_expected_hex, int L) { +void TestHKDF( + string ikm_hex, + string salt_hex, + string info_hex, + string prk_expected_hex, + string okm_expected_hex, + int L) +{ vector ikm = Util::HexToBytes(ikm_hex); vector salt = Util::HexToBytes(salt_hex); vector info = Util::HexToBytes(info_hex); @@ -42,42 +49,45 @@ void TestHKDF(string ikm_hex, string salt_hex, string info_hex, string prk_expec HKDF256::Expand(okm, L, prk, info.data(), info.size()); REQUIRE(32 == prk_expected.size()); - REQUIRE(L == okm_expected.size()); + REQUIRE(L == (int)okm_expected.size()); - for (size_t i=0; i < 32; i++) { + for (size_t i = 0; i < 32; i++) { REQUIRE(prk[i] == prk_expected[i]); } - for (size_t i=0; i < L; i++) { + for (int i = 0; i < L; i++) { REQUIRE(okm[i] == okm_expected[i]); } delete[] okm; } -TEST_CASE("class PrivateKey") { +TEST_CASE("class PrivateKey") +{ uint8_t buffer[PrivateKey::PRIVATE_KEY_SIZE]; memcpy(buffer, getRandomSeed().data(), PrivateKey::PRIVATE_KEY_SIZE); - SECTION("Copy {constructor|assignment operator}") { - PrivateKey pk1 = PrivateKey::RandomPrivateKey(); - PrivateKey pk2 = PrivateKey::RandomPrivateKey(); + SECTION("Copy {constructor|assignment operator}") + { + PrivateKey pk1 = PrivateKey::FromByteVector(getRandomSeed(), true); + PrivateKey pk2 = PrivateKey::FromByteVector(getRandomSeed(), true); PrivateKey pk3 = PrivateKey(pk2); REQUIRE(!pk1.IsZero()); REQUIRE(!pk2.IsZero()); REQUIRE(!pk3.IsZero()); REQUIRE(pk1 != pk2); REQUIRE(pk3 == pk2); - REQUIRE(pk2.GetG1Element().IsValid()); // cache previous g1 - REQUIRE(pk2.GetG2Element().IsValid()); // cache previous g2 + REQUIRE(pk2.GetG1Element().IsValid()); // cache previous g1 + REQUIRE(pk2.GetG2Element().IsValid()); // cache previous g2 pk2 = pk1; REQUIRE(pk1 == pk2); REQUIRE(pk1.GetG1Element() == pk2.GetG1Element()); REQUIRE(pk1.GetG2Element() == pk2.GetG2Element()); REQUIRE(pk3 != pk2); } - SECTION("Move {constructor|assignment operator}") { - PrivateKey pk1 = PrivateKey::RandomPrivateKey(); + SECTION("Move {constructor|assignment operator}") + { + PrivateKey pk1 = PrivateKey::FromByteVector(getRandomSeed(), true); std::vector vec1 = pk1.Serialize(); - PrivateKey pk2 = PrivateKey::RandomPrivateKey(); + PrivateKey pk2 = PrivateKey::FromByteVector(getRandomSeed(), true); std::vector vec2 = pk2.Serialize(); PrivateKey pk3 = PrivateKey(std::move(pk2)); REQUIRE(!pk1.IsZero()); @@ -94,48 +104,71 @@ TEST_CASE("class PrivateKey") { REQUIRE_THROWS(pk2.IsZero()); REQUIRE_THROWS(pk3.IsZero()); } - SECTION("Equality operators") { - PrivateKey pk1 = PrivateKey::RandomPrivateKey(); - PrivateKey pk2 = PrivateKey::RandomPrivateKey(); + SECTION("Equality operators") + { + PrivateKey pk1 = PrivateKey::FromByteVector(getRandomSeed(), true); + PrivateKey pk2 = PrivateKey::FromByteVector(getRandomSeed(), true); PrivateKey pk3 = pk2; REQUIRE(pk1 != pk2); REQUIRE(pk1 != pk3); REQUIRE(pk2 == pk3); } - SECTION("(De)Serialization") { - PrivateKey pk1 = PrivateKey::RandomPrivateKey(); + SECTION("(De)Serialization") + { + PrivateKey pk1 = PrivateKey::FromByteVector(getRandomSeed(), true); pk1.Serialize(buffer); - REQUIRE(memcmp(buffer, pk1.Serialize().data(), PrivateKey::PRIVATE_KEY_SIZE) == 0); + REQUIRE( + memcmp( + buffer, pk1.Serialize().data(), PrivateKey::PRIVATE_KEY_SIZE) == + 0); PrivateKey pk2 = PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true); REQUIRE(pk1 == pk2); - REQUIRE_THROWS(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE - 1), true)); - REQUIRE_THROWS(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE + 1), true)); - REQUIRE_NOTHROW(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true)); - bn_t order; - bn_new(order); - g1_get_ord(order); - bn_write_bin(buffer, PrivateKey::PRIVATE_KEY_SIZE, order); + REQUIRE_THROWS(PrivateKey::FromBytes( + Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE - 1), true)); + REQUIRE_THROWS(PrivateKey::FromBytes( + Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE + 1), true)); + REQUIRE_NOTHROW(PrivateKey::FromBytes( + Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true)); + // the group order r itself is accepted (bn_cmp > 0 semantics) + const vector order = Util::HexToBytes( + "73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); + memcpy(buffer, order.data(), PrivateKey::PRIVATE_KEY_SIZE); REQUIRE_NOTHROW(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), false)); REQUIRE_NOTHROW(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true)); - bn_add(order, order, order); - bn_write_bin(buffer, PrivateKey::PRIVATE_KEY_SIZE, order); + // 2 * r is above the order and must be rejected without modOrder + const vector order2 = Util::HexToBytes( + "e7db4ea6533afa906673b0101343b00aa77b4805fffcb7fdfffffffe00000002"); + memcpy(buffer, order2.data(), PrivateKey::PRIVATE_KEY_SIZE); REQUIRE_THROWS(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), false)); REQUIRE_NOTHROW(PrivateKey::FromBytes(Bytes(buffer, PrivateKey::PRIVATE_KEY_SIZE), true)); + // The hardcoded order must agree with blst's own, which is only + // reachable through blst_scalar_fr_check (true iff below r): r itself + // is not a valid Fr element, r - 1 is. + blst_scalar s; + blst_scalar_from_bendian(&s, order.data()); + REQUIRE(!blst_scalar_fr_check(&s)); + vector orderm1 = order; + orderm1[31] = 0x00; + blst_scalar_from_bendian(&s, orderm1.data()); + REQUIRE(blst_scalar_fr_check(&s)); } SECTION("BIP32 Seed") { uint8_t aliceSeed[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; PrivateKey pk1 = PrivateKey::FromSeedBIP32(Bytes(aliceSeed, 10)); REQUIRE(pk1.HasKeyData()); - vector privateKey = pk1.Serialize(true); + vector privateKey = pk1.Serialize(); vector knownPrivateKey = Util::HexToBytes("46891c2cec49593c81921e473db7480029e0fc1eb933c6b93d81f5370eb19fbd"); REQUIRE(privateKey == knownPrivateKey); G1Element pubKey1 = pk1.GetG1Element(); vector pubKey1Bytes = pubKey1.Serialize(true); + vector pubKey2Bytes = pubKey1.Serialize(false); vector knownPublicKey = Util::HexToBytes("1790635de8740e9a6a6b15fb6b72f3a16afa0973d971979b6ba54761d6e2502c50db76f4d26143f05459a42cfd520d44"); REQUIRE(pubKey1Bytes == knownPublicKey); + REQUIRE(pubKey2Bytes != pubKey1Bytes); } - SECTION("keydata checks") { - PrivateKey pk1 = PrivateKey::RandomPrivateKey(); + SECTION("keydata checks") + { + PrivateKey pk1 = PrivateKey::FromByteVector(getRandomSeed(), true); G1Element g1 = pk1.GetG1Element(); G2Element g2 = pk1.GetG2Element(); PrivateKey pk2 = std::move(pk1); @@ -154,69 +187,86 @@ TEST_CASE("class PrivateKey") { REQUIRE_THROWS(pk1 != pk2); REQUIRE_THROWS(pk1.Serialize(buffer)); REQUIRE_THROWS(pk1.Serialize()); - REQUIRE_THROWS(pk1.SignG2(buffer, sizeof(buffer), buffer, sizeof(buffer))); + REQUIRE_THROWS( + pk1.SignG2(buffer, sizeof(buffer), buffer, sizeof(buffer))); } } -TEST_CASE("HKDF") { +TEST_CASE("HKDF") +{ // https://tools.ietf.org/html/rfc5869 test vectors - SECTION("Test case 2") { - TestHKDF("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - "000102030405060708090a0b0c", - "f0f1f2f3f4f5f6f7f8f9", - "077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5", - "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865", - 42 - ); - } - SECTION("Test case 2") { - TestHKDF("000102030405060708090a0b0c0d0e0f" - "101112131415161718191a1b1c1d1e1f" - "202122232425262728292a2b2c2d2e2f" - "303132333435363738393a3b3c3d3e3f" - "404142434445464748494a4b4c4d4e4f", // 80 octets - "0x606162636465666768696a6b6c6d6e6f" - "707172737475767778797a7b7c7d7e7f" - "808182838485868788898a8b8c8d8e8f" - "909192939495969798999a9b9c9d9e9f" - "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", // 80 octets - "0xb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" - "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" - "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" - "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", // 80 octets - "0x06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244", // 32 octets - "0xb11e398dc80327a1c8e7f78c596a4934" - "4f012eda2d4efad8a050cc4c19afa97c" - "59045a99cac7827271cb41c65e590e09" - "da3275600c2f09b8367793a9aca3db71" - "cc30c58179ec3e87c14c01d5c1f3434f" - "1d87", // 82 octets - 82 - ); - } - SECTION("Test case 3") { - TestHKDF("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", - "", - "", - "19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04", - "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8", - 42 - ); - } - SECTION("Works with multiple of 32") { - // This generates exactly 64 bytes. Uses a 32 byte key and 4 byte salt as in EIP2333. - TestHKDF("8704f9ac024139fe62511375cf9bc534c0507dcf00c41603ac935cd5943ce0b4b88599390de14e743ca2f56a73a04eae13aa3f3b969b39d8701e0d69a6f8d42f", - "53d8e19b", - "", - "eb01c9cd916653df76ffa61b6ab8a74e254ebfd9bfc43e624cc12a72b0373dee", - "8faabea85fc0c64e7ca86217cdc6dcdc88551c3244d56719e630a3521063082c46455c2fd5483811f9520a748f0099c1dfcfa52c54e1c22b5cdf70efb0f3c676", - 64 - ); + SECTION("Test case 2") + { + TestHKDF( + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "000102030405060708090a0b0c", + "f0f1f2f3f4f5f6f7f8f9", + "077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5", + "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34" + "007208d5b887185865", + 42); + } + SECTION("Test case 2") + { + TestHKDF( + "000102030405060708090a0b0c0d0e0f" + "101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f" + "303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f", // 80 octets + "0x606162636465666768696a6b6c6d6e6f" + "707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f" + "909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", // 80 octets + "0xb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", // 80 octets + "0x06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc24" + "4", // 32 octets + "0xb11e398dc80327a1c8e7f78c596a4934" + "4f012eda2d4efad8a050cc4c19afa97c" + "59045a99cac7827271cb41c65e590e09" + "da3275600c2f09b8367793a9aca3db71" + "cc30c58179ec3e87c14c01d5c1f3434f" + "1d87", // 82 octets + 82); + } + SECTION("Test case 3") + { + TestHKDF( + "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", + "", + "", + "19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04", + "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d" + "201395faa4b61a96c8", + 42); + } + SECTION("Works with multiple of 32") + { + // This generates exactly 64 bytes. Uses a 32 byte key and 4 byte salt + // as in EIP2333. + TestHKDF( + "8704f9ac024139fe62511375cf9bc534c0507dcf00c41603ac935cd5943ce0b4b8" + "8599390de14e743ca2f56a73a04eae13aa3f3b969b39d8701e0d69a6f8d42f", + "53d8e19b", + "", + "eb01c9cd916653df76ffa61b6ab8a74e254ebfd9bfc43e624cc12a72b0373dee", + "8faabea85fc0c64e7ca86217cdc6dcdc88551c3244d56719e630a3521063082c46" + "455c2fd5483811f9520a748f0099c1dfcfa52c54e1c22b5cdf70efb0f3c676", + 64); } } -void TestEIP2333(string seedHex, string masterSkHex, string childSkHex, uint32_t childIndex) { +void TestEIP2333( + string seedHex, + string masterSkHex, + string childSkHex, + uint32_t childIndex) +{ auto masterSk = Util::HexToBytes(masterSkHex); auto childSk = Util::HexToBytes(childSkHex); @@ -230,60 +280,73 @@ void TestEIP2333(string seedHex, string masterSkHex, string childSkHex, uint32_t REQUIRE(calculatedMaster.size() == 32); REQUIRE(calculatedChild.size() == 32); - for (int i=0; i<32; i++) { + for (int i = 0; i < 32; i++) { REQUIRE(calculatedMaster[i] == masterSk[i]); } - for (int i=0; i<32; i++) { + for (int i = 0; i < 32; i++) { REQUIRE(calculatedChild[i] == childSk[i]); } } -TEST_CASE("EIP-2333 hardened HD keys") { - // The comments in the test cases correspond to integers that are converted to - // bytes using python int.to_bytes(32, "big").hex(), since the EIP spec provides ints, but c++ - // does not support bigint by default - SECTION("EIP-2333 Test case 1"){ - TestEIP2333("3141592653589793238462643383279502884197169399375105820974944592", - // 36167147331491996618072159372207345412841461318189449162487002442599770291484 - "4ff5e145590ed7b71e577bb04032396d1619ff41cb4e350053ed2dce8d1efd1c", - // 41787458189896526028601807066547832426569899195138584349427756863968330588237 - "5c62dcf9654481292aafa3348f1d1b0017bbfb44d6881d26d2b17836b38f204d", - 3141592653 - ); - } - SECTION("EIP-2333 Test case 2"){ - TestEIP2333("0x0099FF991111002299DD7744EE3355BBDD8844115566CC55663355668888CC00", - // 13904094584487173309420026178174172335998687531503061311232927109397516192843 - "1ebd704b86732c3f05f30563dee6189838e73998ebc9c209ccff422adee10c4b", - // 12482522899285304316694838079579801944734479969002030150864436005368716366140 - "1b98db8b24296038eae3f64c25d693a269ef1e4d7ae0f691c572a46cf3c0913c", - 4294967295 - ); - } - SECTION("EIP-2333 Test case 3"){ - TestEIP2333("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", - // 44010626067374404458092393860968061149521094673473131545188652121635313364506 - "614d21b10c0e4996ac0608e0e7452d5720d95d20fe03c59a3321000a42432e1a", - // 4011524214304750350566588165922015929937602165683407445189263506512578573606 - "08de7136e4afc56ae3ec03b20517d9c1232705a747f588fd17832f36ae337526", - 42 - ); - } - SECTION("EIP-2333 Test vector with intermediate values"){ - TestEIP2333("c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04", - // 5399117110774477986698372024995405256382522670366369834617409486544348441851 - "0x0befcabff4a664461cc8f190cdd51c05621eb2837c71a1362df5b465a674ecfb", - // 11812940737387919040225825939013910852517748782307378293770044673328955938106 - "1a1de3346883401f1e3b2281be5774080edb8e5ebe6f776b0f7af9fea942553a", - 0 - ); +TEST_CASE("EIP-2333 hardened HD keys") +{ + // The comments in the test cases correspond to integers that are converted + // to bytes using python int.to_bytes(32, "big").hex(), since the EIP spec + // provides ints, but c++ does not support bigint by default + SECTION("EIP-2333 Test case 1") + { + TestEIP2333( + "3141592653589793238462643383279502884197169399375105820974944592", + // 36167147331491996618072159372207345412841461318189449162487002442599770291484 + "4ff5e145590ed7b71e577bb04032396d1619ff41cb4e350053ed2dce8d1efd1c", + // 41787458189896526028601807066547832426569899195138584349427756863968330588237 + "5c62dcf9654481292aafa3348f1d1b0017bbfb44d6881d26d2b17836b38f204d", + 3141592653); + } + SECTION("EIP-2333 Test case 2") + { + TestEIP2333( + "0x0099FF991111002299DD7744EE3355BBDD8844115566CC55663355668888CC0" + "0", + // 13904094584487173309420026178174172335998687531503061311232927109397516192843 + "1ebd704b86732c3f05f30563dee6189838e73998ebc9c209ccff422adee10c4b", + // 12482522899285304316694838079579801944734479969002030150864436005368716366140 + "1b98db8b24296038eae3f64c25d693a269ef1e4d7ae0f691c572a46cf3c0913c", + 4294967295); + } + SECTION("EIP-2333 Test case 3") + { + TestEIP2333( + "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa" + "3", + // 44010626067374404458092393860968061149521094673473131545188652121635313364506 + "614d21b10c0e4996ac0608e0e7452d5720d95d20fe03c59a3321000a42432e1a", + // 4011524214304750350566588165922015929937602165683407445189263506512578573606 + "08de7136e4afc56ae3ec03b20517d9c1232705a747f588fd17832f36ae337526", + 42); + } + SECTION("EIP-2333 Test vector with intermediate values") + { + TestEIP2333( + "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f" + "09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04", + // 5399117110774477986698372024995405256382522670366369834617409486544348441851 + "0x0befcabff4a664461cc8f190cdd51c05621eb2837c71a1362df5b465a674ecf" + "b", + // 11812940737387919040225825939013910852517748782307378293770044673328955938106 + "1a1de3346883401f1e3b2281be5774080edb8e5ebe6f776b0f7af9fea942553a", + 0); } } -TEST_CASE("Unhardened HD keys") { - SECTION("Should match derivation through private and public keys"){ - const vector seed = {1, 50, 6, 244, 24, 199, 1, 25, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}; +TEST_CASE("Unhardened HD keys") +{ + SECTION("Should match derivation through private and public keys") + { + const vector seed = {1, 50, 6, 244, 24, 199, 1, 25, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29}; PrivateKey sk = BasicSchemeMPL().KeyGen(seed); G1Element pk = sk.GetG1Element(); @@ -293,15 +356,20 @@ TEST_CASE("Unhardened HD keys") { REQUIRE(childSk.GetG1Element() == childPk); - PrivateKey grandchildSk = BasicSchemeMPL().DeriveChildSkUnhardened(childSk, 12142); - G1Element grandcihldPk = BasicSchemeMPL().DeriveChildPkUnhardened(childPk, 12142); + PrivateKey grandchildSk = + BasicSchemeMPL().DeriveChildSkUnhardened(childSk, 12142); + G1Element grandchildPk = + BasicSchemeMPL().DeriveChildPkUnhardened(childPk, 12142); - REQUIRE(grandchildSk.GetG1Element() == grandcihldPk); + REQUIRE(grandchildSk.GetG1Element() == grandchildPk); } - SECTION("Should derive public child from parent") { - const vector seed = {2, 50, 6, 244, 24, 199, 1, 25, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}; + SECTION("Should derive public child from parent") + { + const vector seed = {2, 50, 6, 244, 24, 199, 1, 25, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29}; PrivateKey sk = BasicSchemeMPL().KeyGen(seed); G1Element pk = sk.GetG1Element(); @@ -316,10 +384,17 @@ TEST_CASE("Unhardened HD keys") { } } -TEST_CASE("IETF test vectors") { - SECTION ("Pyecc vector") { - string sig1BasicHex = "96ba34fac33c7f129d602a0bc8a3d43f9abc014eceaab7359146b4b150e57b808645738f35671e9e10e0d862a30cab70074eb5831d13e6a5b162d01eebe687d0164adbd0a864370a7c222a2768d7704da254f1bf1823665bc2361f9dd8c00e99"; - string sk = "0x0101010101010101010101010101010101010101010101010101010101010101"; +TEST_CASE("IETF test vectors") +{ + SECTION("Pyecc vector") + { + string sig1BasicHex = + "96ba34fac33c7f129d602a0bc8a3d43f9abc014eceaab7359146b4b150e57b8086" + "45738f35671e9e10e0d862a30cab70074eb5831d13e6a5b162d01eebe687d0164a" + "dbd0a864370a7c222a2768d7704da254f1bf1823665bc2361f9dd8c00e99"; + string sk = + "0x010101010101010101010101010101010101010101010101010101010101010" + "1"; vector msg = {3, 1, 4, 1, 5, 9}; auto skobj = PrivateKey::FromBytes(Bytes(Util::HexToBytes(sk))); G2Element sig = BasicSchemeMPL().Sign(skobj, msg); @@ -331,9 +406,10 @@ TEST_CASE("IETF test vectors") { } } - -TEST_CASE("Chia test vectors") { - SECTION("Chia test vectors 1 (Basic)") { +TEST_CASE("Chia test vectors") +{ + SECTION("Chia test vectors 1 (Basic)") + { vector seed1(32, 0x00); // All 0s vector seed2(32, 0x01); // All 1s vector message1 = {7, 8, 9}; @@ -343,7 +419,6 @@ TEST_CASE("Chia test vectors") { G1Element pk1 = sk1.GetG1Element(); G2Element sig1 = BasicSchemeMPL().Sign(sk1, message1); - PrivateKey sk2 = BasicSchemeMPL().KeyGen(seed2); G1Element pk2 = sk2.GetG1Element(); G2Element sig2 = BasicSchemeMPL().Sign(sk2, message2); @@ -366,20 +441,26 @@ TEST_CASE("Chia test vectors") { REQUIRE( Util::HexStr(sig2.Serialize()) == - "a9c4d3e689b82c7ec7e838dac2380cb014f9a08f6cd6ba044c263746e39a8f7a60ffee4afb7" - "8f146c2e421360784d58f0029491e3bd8ab84f0011d258471ba4e87059de295d9aba845c044e" + "a9c4d3e689b82c7ec7e838dac2380cb014f9a08f6cd6ba044c263746e39a8f7a60" + "ffee4afb7" + "8f146c2e421360784d58f0029491e3bd8ab84f0011d258471ba4e87059de295d9a" + "ba845c044e" "e83f6cf2411efd379ef38bf4cf41d5f3c0ae1205d"); G2Element aggSig1 = BasicSchemeMPL().Aggregate({sig1, sig2}); REQUIRE( Util::HexStr(aggSig1.Serialize()) == - "aee003c8cdaf3531b6b0ca354031b0819f7586b5846796615aee8108fec75ef838d181f9d24" - "4a94d195d7b0231d4afcf06f27f0cc4d3c72162545c240de7d5034a7ef3a2a03c0159de982fb" + "aee003c8cdaf3531b6b0ca354031b0819f7586b5846796615aee8108fec75ef838" + "d181f9d24" + "4a94d195d7b0231d4afcf06f27f0cc4d3c72162545c240de7d5034a7ef3a2a03c0" + "159de982fb" "c2e7790aeb455e27beae91d64e077c70b5506dea3"); - REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message1, message2}, aggSig1)); - REQUIRE(!BasicSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message1, message2}, sig1)); + REQUIRE(BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{message1, message2}, aggSig1)); + REQUIRE(!BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{message1, message2}, sig1)); REQUIRE(!BasicSchemeMPL().Verify(pk1, message1, sig2)); REQUIRE(!BasicSchemeMPL().Verify(pk1, message2, sig1)); @@ -393,15 +474,21 @@ TEST_CASE("Chia test vectors") { G2Element aggSig2 = BasicSchemeMPL().Aggregate({sig3, sig4, sig5}); - REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk1, pk2}, vector>{message3, message4, message5}, aggSig2)); + REQUIRE(BasicSchemeMPL().AggregateVerify( + {pk1, pk1, pk2}, + vector>{message3, message4, message5}, + aggSig2)); REQUIRE( Util::HexStr(aggSig2.Serialize()) == - "a0b1378d518bea4d1100adbc7bdbc4ff64f2c219ed6395cd36fe5d2aa44a4b8e710b607afd9" - "65e505a5ac3283291b75413d09478ab4b5cfbafbeea366de2d0c0bcf61deddaa521f6020460f" + "a0b1378d518bea4d1100adbc7bdbc4ff64f2c219ed6395cd36fe5d2aa44a4b8e71" + "0b607afd9" + "65e505a5ac3283291b75413d09478ab4b5cfbafbeea366de2d0c0bcf61deddaa52" + "1f6020460f" "d547ab37659ae207968b545727beba0a3c5572b9c"); } - SECTION("Chia test vector 2 (Augmented, aggregate of aggregates)") { + SECTION("Chia test vector 2 (Augmented, aggregate of aggregates)") + { vector message1 = {1, 2, 3, 40}; vector message2 = {5, 6, 70, 201}; vector message3 = {9, 10, 11, 12, 13}; @@ -423,20 +510,26 @@ TEST_CASE("Chia test vectors") { G2Element sig5 = AugSchemeMPL().Sign(sk1, message1); G2Element sig6 = AugSchemeMPL().Sign(sk1, message4); - G2Element aggSigL = AugSchemeMPL().Aggregate({sig1, sig2}); G2Element aggSigR = AugSchemeMPL().Aggregate({sig3, sig4, sig5}); G2Element aggSig = AugSchemeMPL().Aggregate({aggSigL, aggSigR, sig6}); - REQUIRE(AugSchemeMPL().AggregateVerify({pk1, pk2, pk2, pk1, pk1, pk1}, vector>{message1, message2, message1, message3, message1, message4}, aggSig)); + REQUIRE(AugSchemeMPL().AggregateVerify( + {pk1, pk2, pk2, pk1, pk1, pk1}, + vector>{ + message1, message2, message1, message3, message1, message4}, + aggSig)); REQUIRE( Util::HexStr(aggSig.Serialize()) == - "a1d5360dcb418d33b29b90b912b4accde535cf0e52caf467a005dc632d9f7af44b6c4e9acd4" - "6eac218b28cdb07a3e3bc087df1cd1e3213aa4e11322a3ff3847bbba0b2fd19ddc25ca964871" + "a1d5360dcb418d33b29b90b912b4accde535cf0e52caf467a005dc632d9f7af44b" + "6c4e9acd4" + "6eac218b28cdb07a3e3bc087df1cd1e3213aa4e11322a3ff3847bbba0b2fd19ddc" + "25ca964871" "997b9bceeab37a4c2565876da19382ea32a962200"); } - SECTION("Chia test vector 3 (PoP)") { + SECTION("Chia test vector 3 (PoP)") + { vector message1 = {1, 2, 3, 40, 50}; vector seed1(32, 0x04); // All 4s @@ -446,13 +539,16 @@ TEST_CASE("Chia test vectors") { G2Element pop = PopSchemeMPL().PopProve(sk1); REQUIRE(PopSchemeMPL().PopVerify(sk1.GetG1Element(), pop)); - REQUIRE(Util::HexStr(pop.Serialize()) == "84f709159435f0dc73b3e8bf6c78d85282d19231555a8ee3b6e2573aaf66872d9203fefa1ef" - "700e34e7c3f3fb28210100558c6871c53f1ef6055b9f06b0d1abe22ad584ad3b957f3018a8f5" - "8227c6c716b1e15791459850f2289168fa0cf9115"); + REQUIRE( + Util::HexStr(pop.Serialize()) == + "84f709159435f0dc73b3e8bf6c78d85282d19231555a8ee3b6e2573aaf66872d92" + "03fefa1ef" + "700e34e7c3f3fb28210100558c6871c53f1ef6055b9f06b0d1abe22ad584ad3b95" + "7f3018a8f5" + "8227c6c716b1e15791459850f2289168fa0cf9115"); } } - TEST_CASE("Key generation") { SECTION("Should generate a keypair from a seed") @@ -463,12 +559,10 @@ TEST_CASE("Key generation") REQUIRE_THROWS(BasicSchemeMPL().KeyGen(seed1)); PrivateKey sk = BasicSchemeMPL().KeyGen(seed2); G1Element pk = sk.GetG1Element(); - REQUIRE(core_get()->code == RLC_OK); REQUIRE(pk.GetFingerprint() == 0x8ee7ba56); } } - TEST_CASE("Error handling") { SECTION("Should throw on a bad private key") @@ -478,7 +572,8 @@ TEST_CASE("Error handling") uint8_t* skData = Util::SecAlloc(G2Element::SIZE); sk1.Serialize(skData); skData[0] = 255; - REQUIRE_THROWS(PrivateKey::FromBytes(Bytes(skData, PrivateKey::PRIVATE_KEY_SIZE))); + REQUIRE_THROWS( + PrivateKey::FromBytes(Bytes(skData, PrivateKey::PRIVATE_KEY_SIZE))); Util::SecFree(skData); } @@ -487,7 +582,8 @@ TEST_CASE("Error handling") vector buf(G1Element::SIZE, 0); for (int i = 0; i < 0xFF; i++) { buf[0] = (uint8_t)i; - if (i == 0xc0) { // Infinity prefix shouldn't throw here as we have only zero values + if (i == 0xc0) { // Infinity prefix shouldn't throw here as we have + // only zero values REQUIRE_NOTHROW(G1Element::FromByteVector(buf)); } else { REQUIRE_THROWS(G1Element::FromByteVector(buf)); @@ -500,47 +596,20 @@ TEST_CASE("Error handling") vector buf(G2Element::SIZE, 0); for (int i = 0; i < 0xFF; i++) { buf[0] = (uint8_t)i; - if (i == 0xc0) { // Infinity prefix shouldn't throw here as we have only zero values + if (i == 0xc0) { // Infinity prefix shouldn't throw here as we have + // only zero values REQUIRE_NOTHROW(G2Element::FromByteVector(buf)); } else { REQUIRE_THROWS(G2Element::FromByteVector(buf)); } } - // Trigger "G2 element must always have 48th byte start with 0b000" error case + // Trigger "G2 element must always have 48th byte start with 0b000" + // error case buf[48] = 0xFF; REQUIRE_THROWS(G2Element::FromByteVector(buf)); } - - SECTION("Error handling should be thread safe") - { - core_get()->code = 10; - REQUIRE(core_get()->code == 10); - - ctx_t* ctx1 = core_get(); - - // spawn a thread and make sure it uses a different/same context depending on relic's multithreading setup - std::thread([&]() { -#if MULTI != RELIC_NONE - REQUIRE(ctx1 != core_get()); - REQUIRE(core_get()->code == RLC_OK); -#else - REQUIRE(ctx1 == core_get()); - REQUIRE(core_get()->code != RLC_OK); -#endif - core_get()->code = 1; - }).join(); - -#if MULTI != RELIC_NONE - REQUIRE(core_get()->code == 10); -#else - REQUIRE(core_get()->code == 1); -#endif - // reset so that future test cases don't fail - core_get()->code = RLC_OK; - } } - TEST_CASE("Util tests") { SECTION("Should convert an int to four bytes") @@ -558,7 +627,6 @@ TEST_CASE("Util tests") } } - TEST_CASE("Signature tests") { SECTION("Should use copy constructor") @@ -572,7 +640,8 @@ TEST_CASE("Signature tests") uint8_t skBytes[PrivateKey::PRIVATE_KEY_SIZE]; sk2.Serialize(skBytes); - PrivateKey sk4 = PrivateKey::FromBytes(Bytes(skBytes, PrivateKey::PRIVATE_KEY_SIZE)); + PrivateKey sk4 = + PrivateKey::FromBytes(Bytes(skBytes, PrivateKey::PRIVATE_KEY_SIZE)); G1Element pk2 = G1Element(pk1); G2Element sig1 = BasicSchemeMPL().Sign(sk4, message1); @@ -581,7 +650,8 @@ TEST_CASE("Signature tests") REQUIRE(BasicSchemeMPL().Verify(pk2, message1, sig2)); } - SECTION("Should sign with the zero key") { + SECTION("Should sign with the zero key") + { vector sk0(32, 0); PrivateKey sk = PrivateKey::FromByteVector(sk0); REQUIRE(sk.GetG1Element() == G1Element()); // Infinity @@ -632,7 +702,8 @@ TEST_CASE("Signature tests") uint8_t* skData = Util::SecAlloc(G2Element::SIZE); sk1.Serialize(skData); - PrivateKey sk2 = PrivateKey::FromBytes(Bytes(skData, PrivateKey::PRIVATE_KEY_SIZE)); + PrivateKey sk2 = + PrivateKey::FromBytes(Bytes(skData, PrivateKey::PRIVATE_KEY_SIZE)); REQUIRE(sk1 == sk2); auto pkData = pk1.Serialize(); @@ -654,7 +725,6 @@ TEST_CASE("Signature tests") SECTION("Should not verify aggregate with same message under BasicScheme") { vector message = {100, 2, 254, 88, 90, 45, 23}; - uint8_t hash[BLS::MESSAGE_HASH_LEN]; vector seed(32, 0x50); vector seed2(32, 0x70); @@ -669,13 +739,17 @@ TEST_CASE("Signature tests") G2Element sig2 = BasicSchemeMPL().Sign(sk2, message); G2Element aggSig = BasicSchemeMPL().Aggregate({sig1, sig2}); - REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message}, aggSig) == false); + REQUIRE( + BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, + vector>{message, message}, + aggSig) == false); } - SECTION("Should verify aggregate with same message under AugScheme/PopScheme") + SECTION( + "Should verify aggregate with same message under AugScheme/PopScheme") { vector message = {100, 2, 254, 88, 90, 45, 23}; - uint8_t hash[BLS::MESSAGE_HASH_LEN]; vector seed(32, 0x50); vector seed2(32, 0x70); @@ -689,19 +763,21 @@ TEST_CASE("Signature tests") G2Element sig1Aug = AugSchemeMPL().Sign(sk1, message); G2Element sig2Aug = AugSchemeMPL().Sign(sk2, message); G2Element aggSigAug = AugSchemeMPL().Aggregate({sig1Aug, sig2Aug}); - REQUIRE(AugSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message}, aggSigAug)); + REQUIRE(AugSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{message, message}, aggSigAug)); G2Element sig1Pop = PopSchemeMPL().Sign(sk1, message); G2Element sig2Pop = PopSchemeMPL().Sign(sk2, message); G2Element aggSigPop = PopSchemeMPL().Aggregate({sig1Pop, sig2Pop}); - REQUIRE(PopSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message}, aggSigPop)); + REQUIRE(PopSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{message, message}, aggSigPop)); } SECTION("Should Aug aggregate many G2Elements, diff message") { vector pks; vector sigs; - vector > ms; + vector> ms; for (uint8_t i = 0; i < 80; i++) { vector message = {0, 100, 2, 45, 64, 12, 12, 63, i}; @@ -720,8 +796,8 @@ TEST_CASE("Signature tests") SECTION("Aggregate Verification of zero items with infinity should pass") { vector pks_as_g1; - vector > pks_as_bytes; - vector > msgs; + vector> pks_as_bytes; + vector> msgs; vector sigs; sigs.push_back(G2Element()); @@ -731,22 +807,65 @@ TEST_CASE("Signature tests") REQUIRE(aggSig == G2Element()); REQUIRE(AugSchemeMPL().AggregateVerify(pks_as_g1, msgs, aggSig)); - REQUIRE(AugSchemeMPL().AggregateVerify(pks_as_bytes, msgs, aggSig.Serialize())); + REQUIRE(AugSchemeMPL().AggregateVerify( + pks_as_bytes, msgs, aggSig.Serialize())); REQUIRE(BasicSchemeMPL().AggregateVerify(pks_as_g1, msgs, aggSig)); - REQUIRE(BasicSchemeMPL().AggregateVerify(pks_as_bytes, msgs, aggSig.Serialize())); + REQUIRE(BasicSchemeMPL().AggregateVerify( + pks_as_bytes, msgs, aggSig.Serialize())); - // FastAggregateVerify takes one message, and requires at least one key + // FastAggregateVerify takes one message, and requires at least one key vector msg; REQUIRE(pks_as_g1.size() == 0); - REQUIRE(PopSchemeMPL().FastAggregateVerify(pks_as_g1, msg, aggSig) == false); + REQUIRE( + PopSchemeMPL().FastAggregateVerify(pks_as_g1, msg, aggSig) == + false); REQUIRE(pks_as_bytes.size() == 0); - REQUIRE(PopSchemeMPL().FastAggregateVerify(pks_as_bytes, msg, aggSig.Serialize()) == false); + REQUIRE( + PopSchemeMPL().FastAggregateVerify( + pks_as_bytes, msg, aggSig.Serialize()) == false); + } + SECTION("Verification with identity pubkey or signature should fail") + { + // Single verify: identity pubkey must be rejected + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = BasicSchemeMPL().Sign(sk, msg); + REQUIRE(BasicSchemeMPL().Verify(G1Element(), msg, sig) == false); + + // Single verify: identity signature must be rejected + auto pk = sk.GetG1Element(); + REQUIRE(BasicSchemeMPL().Verify(pk, msg, G2Element()) == false); + + // AggregateVerify: identity pubkey in non-empty list must be rejected + vector pks = {G1Element()}; + vector msgs_b = {Bytes(msg)}; + REQUIRE(BasicSchemeMPL().AggregateVerify(pks, msgs_b, sig) == false); + + // AggregateVerify: identity signature with non-empty pubkeys must be rejected + pks = {pk}; + REQUIRE(BasicSchemeMPL().AggregateVerify(pks, msgs_b, G2Element()) == false); + } + SECTION("Aggregate same sig element") + { + vector message = {100, 2, 254, 88, 90, 45, 23}; + + vector seed(32, 0x50); + + PrivateKey sk1 = BasicSchemeMPL().KeyGen(seed); + + G1Element pk1 = sk1.GetG1Element(); + + G2Element sig1Aug = AugSchemeMPL().Sign(sk1, message); + G2Element aggSigAug = AugSchemeMPL().Aggregate({sig1Aug, sig1Aug}); + REQUIRE(AugSchemeMPL().AggregateVerify( + {pk1, pk1}, vector>{message, message}, aggSigAug)); } } -TEST_CASE("Agg sks") { +TEST_CASE("Agg sks") +{ SECTION("Should create aggregates with agg sk (basic scheme)") { const vector message = {100, 2, 254, 88, 90, 45, 23}; @@ -771,7 +890,6 @@ TEST_CASE("Agg sks") { const G2Element aggSig2 = BasicSchemeMPL().Sign(aggSk, message); - const G2Element aggSig = BasicSchemeMPL().Aggregate({sig1, sig2}); REQUIRE(aggSig == aggSig2); @@ -780,8 +898,16 @@ TEST_CASE("Agg sks") { REQUIRE(BasicSchemeMPL().Verify(aggPubKey, message, aggSig2)); // Verify aggregate with both keys (Fails since not distinct) - REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message}, aggSig) == false); - REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message}, aggSig2) == false); + REQUIRE( + BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, + vector>{message, message}, + aggSig) == false); + REQUIRE( + BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, + vector>{message, message}, + aggSig2) == false); // Try the same with distinct message, and same sk vector message2 = {200, 29, 54, 8, 9, 29, 155, 55}; @@ -803,12 +929,17 @@ TEST_CASE("Agg sks") { REQUIRE(pkFinal != aggPubKey); // Cannot verify with aggPubKey (since we have multiple messages) - REQUIRE(BasicSchemeMPL().AggregateVerify({aggPubKey, pk2}, vector>{message, message2}, aggSigFinal)); + REQUIRE(BasicSchemeMPL().AggregateVerify( + {aggPubKey, pk2}, + vector>{message, message2}, + aggSigFinal)); } } -TEST_CASE("Advanced") { - SECTION("Should aggregate with multiple levels, degenerate") { +TEST_CASE("Advanced") +{ + SECTION("Should aggregate with multiple levels, degenerate") + { vector message1 = {100, 2, 254, 88, 90, 45, 23}; PrivateKey sk1 = AugSchemeMPL().KeyGen(getRandomSeed()); G1Element pk1 = sk1.GetG1Element(); @@ -827,7 +958,8 @@ TEST_CASE("Advanced") { REQUIRE(AugSchemeMPL().AggregateVerify(pks, ms, aggSig)); } - SECTION("Should aggregate with multiple levels, different messages") { + SECTION("Should aggregate with multiple levels, different messages") + { vector message1 = {100, 2, 254, 88, 90, 45, 23}; vector message2 = {192, 29, 2, 0, 0, 45, 23}; vector message3 = {52, 29, 2, 0, 0, 45, 102}; @@ -865,25 +997,24 @@ TEST_CASE("Advanced") { SECTION("README") { // Example seed, used to generate private key. Always use - // a secure RNG with sufficient entropy to generate a seed (at least 32 bytes). - vector seed = {0, 50, 6, 244, 24, 199, 1, 25, 52, 88, 192, - 19, 18, 12, 89, 6, 220, 18, 102, 58, 209, 82, - 12, 62, 89, 110, 182, 9, 44, 20, 254, 22}; + // a secure RNG with sufficient entropy to generate a seed (at least 32 + // bytes). + vector seed = {0, 50, 6, 244, 24, 199, 1, 25, + 52, 88, 192, 19, 18, 12, 89, 6, + 220, 18, 102, 58, 209, 82, 12, 62, + 89, 110, 182, 9, 44, 20, 254, 22}; PrivateKey sk = AugSchemeMPL().KeyGen(seed); G1Element pk = sk.GetG1Element(); - vector message = {1, 2, 3, 4, 5}; // Message is passed in as a byte vector + vector message = { + 1, 2, 3, 4, 5}; // Message is passed in as a byte vector G2Element signature = AugSchemeMPL().Sign(sk, message); vector skBytes = sk.Serialize(); vector pkBytes = pk.Serialize(); vector signatureBytes = signature.Serialize(); - cout << Util::HexStr(skBytes) << endl; // 32 bytes - cout << Util::HexStr(pkBytes) << endl; // 48 bytes - cout << Util::HexStr(signatureBytes) << endl; // 96 bytes - // Takes array of 32 bytes PrivateKey skc = PrivateKey::FromByteVector(skBytes); @@ -913,7 +1044,8 @@ TEST_CASE("Advanced") { // Signatures can be noninteractively combined by anyone G2Element aggSig = AugSchemeMPL().Aggregate({sig1, sig2}); - REQUIRE(AugSchemeMPL().AggregateVerify({pk1, pk2}, vector>{message, message2}, aggSig)); + REQUIRE(AugSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{message, message2}, aggSig)); seed[0] = 3; PrivateKey sk3 = AugSchemeMPL().KeyGen(seed); @@ -921,14 +1053,17 @@ TEST_CASE("Advanced") { vector message3 = {100, 2, 254, 88, 90, 45, 23}; G2Element sig3 = AugSchemeMPL().Sign(sk3, message3); - // Arbitrary trees of aggregates G2Element aggSigFinal = AugSchemeMPL().Aggregate({aggSig, sig3}); - REQUIRE(AugSchemeMPL().AggregateVerify({pk1, pk2, pk3}, vector>{message, message2, message3}, aggSigFinal)); + REQUIRE(AugSchemeMPL().AggregateVerify( + {pk1, pk2, pk3}, + vector>{message, message2, message3}, + aggSigFinal)); - // If the same message is signed, you can use Proof of Posession (PopScheme) for efficiency - // A proof of possession MUST be passed around with the PK to ensure security. + // If the same message is signed, you can use Proof of Posession + // (PopScheme) for efficiency A proof of possession MUST be passed + // around with the PK to ensure security. G2Element popSig1 = PopSchemeMPL().Sign(sk1, message); G2Element popSig2 = PopSchemeMPL().Sign(sk2, message); @@ -940,9 +1075,11 @@ TEST_CASE("Advanced") { REQUIRE(PopSchemeMPL().PopVerify(pk1, pop1)); REQUIRE(PopSchemeMPL().PopVerify(pk2, pop2)); REQUIRE(PopSchemeMPL().PopVerify(pk3, pop3)); - G2Element popSigAgg = PopSchemeMPL().Aggregate({popSig1, popSig2, popSig3}); + G2Element popSigAgg = + PopSchemeMPL().Aggregate({popSig1, popSig2, popSig3}); - REQUIRE(PopSchemeMPL().FastAggregateVerify({pk1, pk2, pk3}, message, popSigAgg)); + REQUIRE(PopSchemeMPL().FastAggregateVerify( + {pk1, pk2, pk3}, message, popSigAgg)); // Aggregate public key, indistinguishable from a single public key G1Element popAggPk = pk1 + pk2 + pk3; @@ -952,17 +1089,20 @@ TEST_CASE("Advanced") { PrivateKey aggSk = PrivateKey::Aggregate({sk1, sk2, sk3}); REQUIRE(PopSchemeMPL().Sign(aggSk, message) == popSigAgg); - PrivateKey masterSk = AugSchemeMPL().KeyGen(seed); PrivateKey child = AugSchemeMPL().DeriveChildSk(masterSk, 152); PrivateKey grandchild = AugSchemeMPL().DeriveChildSk(child, 952); G1Element masterPk = masterSk.GetG1Element(); - PrivateKey childU = AugSchemeMPL().DeriveChildSkUnhardened(masterSk, 22); - PrivateKey grandchildU = AugSchemeMPL().DeriveChildSkUnhardened(childU, 0); + PrivateKey childU = + AugSchemeMPL().DeriveChildSkUnhardened(masterSk, 22); + PrivateKey grandchildU = + AugSchemeMPL().DeriveChildSkUnhardened(childU, 0); - G1Element childUPk = AugSchemeMPL().DeriveChildPkUnhardened(masterPk, 22); - G1Element grandchildUPk = AugSchemeMPL().DeriveChildPkUnhardened(childUPk, 0); + G1Element childUPk = + AugSchemeMPL().DeriveChildPkUnhardened(masterPk, 22); + G1Element grandchildUPk = + AugSchemeMPL().DeriveChildPkUnhardened(childUPk, 0); REQUIRE(grandchildUPk == grandchildU.GetG1Element()); } @@ -984,12 +1124,16 @@ TEST_CASE("Advanced") { G2Element g2Bytes = G2Element::FromBytes(Bytes(vecG2Element)); REQUIRE(g2Vector == g2Bytes); - G1Element g1MessageVector = G1Element::FromMessage(vecHash, vecHash.data(), vecHash.size()); - G1Element g1MessageBytes = G1Element::FromMessage(Bytes(vecHash), vecHash.data(), vecHash.size()); + G1Element g1MessageVector = + G1Element::FromMessage(vecHash, vecHash.data(), vecHash.size()); + G1Element g1MessageBytes = G1Element::FromMessage( + Bytes(vecHash), vecHash.data(), vecHash.size()); REQUIRE(g1MessageVector == g1MessageBytes); - G2Element g2MessageVector = G2Element::FromMessage(vecHash, vecHash.data(), vecHash.size()); - G2Element g2MessageBytes = G2Element::FromMessage(Bytes(vecHash), vecHash.data(), vecHash.size()); + G2Element g2MessageVector = + G2Element::FromMessage(vecHash, vecHash.data(), vecHash.size()); + G2Element g2MessageBytes = G2Element::FromMessage( + Bytes(vecHash), vecHash.data(), vecHash.size()); REQUIRE(g2MessageVector == g2MessageBytes); G1Element g1_1 = pk1.GetG1Element(); @@ -997,29 +1141,41 @@ TEST_CASE("Advanced") { G1Element g1_3 = pk3.GetG1Element(); G2Element g2BasicSignVector1 = BasicSchemeMPL().Sign(pk1, vecHash); - G2Element g2BasicSignBytes1 = BasicSchemeMPL().Sign(pk1, Bytes(vecHash)); + G2Element g2BasicSignBytes1 = + BasicSchemeMPL().Sign(pk1, Bytes(vecHash)); REQUIRE(g2BasicSignVector1 == g2BasicSignBytes1); G2Element g2BasicSign2 = BasicSchemeMPL().Sign(pk2, Bytes(vecHash)); - G2Element g2BasicSign3 = BasicSchemeMPL().Sign(pk3, Bytes(vecG2Element)); + G2Element g2BasicSign3 = + BasicSchemeMPL().Sign(pk3, Bytes(vecG2Element)); REQUIRE(g2BasicSignVector1 != g2BasicSign2); - REQUIRE(BasicSchemeMPL().Verify(Bytes(g1_1.Serialize()), Bytes(vecHash), Bytes(g2BasicSignVector1.Serialize()))); - REQUIRE(BasicSchemeMPL().Verify(g1_1, Bytes(vecHash), g2BasicSignVector1)); + REQUIRE(BasicSchemeMPL().Verify( + Bytes(g1_1.Serialize()), + Bytes(vecHash), + Bytes(g2BasicSignVector1.Serialize()))); + REQUIRE( + BasicSchemeMPL().Verify(g1_1, Bytes(vecHash), g2BasicSignVector1)); - vector> vecG1Vector = {g1_1.Serialize(), g1_3.Serialize()}; - vector> vecG2Vector = {g2BasicSignVector1.Serialize(), g2BasicSign3.Serialize()}; + vector> vecG1Vector = { + g1_1.Serialize(), g1_3.Serialize()}; + vector> vecG2Vector = { + g2BasicSignVector1.Serialize(), g2BasicSign3.Serialize()}; vector> vecHashes = {vecHash, vecG2Element}; auto aggVector = BasicSchemeMPL().Aggregate(vecG2Vector); - auto aggBytes = BasicSchemeMPL().Aggregate(vector{vecG2Vector.begin(), vecG2Vector.end()}); + auto aggBytes = BasicSchemeMPL().Aggregate( + vector{vecG2Vector.begin(), vecG2Vector.end()}); REQUIRE(aggVector == aggBytes); - REQUIRE(BasicSchemeMPL().AggregateVerify(vector{vecG1Vector.begin(), vecG1Vector.end()}, - vector{vecHashes.begin(), vecHashes.end()}, - Bytes(aggVector))); - REQUIRE(BasicSchemeMPL().AggregateVerify({g1_1, g1_3}, - vector{vecHashes.begin(), vecHashes.end()}, - G2Element::FromBytes(aggVector))); + + REQUIRE(BasicSchemeMPL().AggregateVerify( + vector{vecG1Vector.begin(), vecG1Vector.end()}, + vector{vecHashes.begin(), vecHashes.end()}, + Bytes(aggVector))); + REQUIRE(BasicSchemeMPL().AggregateVerify( + {g1_1, g1_3}, + vector{vecHashes.begin(), vecHashes.end()}, + G2Element::FromBytes(aggVector))); G2Element g2AugSignVector1 = AugSchemeMPL().Sign(pk1, vecHash); G2Element g2AugSignBytes1 = AugSchemeMPL().Sign(pk1, Bytes(vecHash)); @@ -1027,40 +1183,53 @@ TEST_CASE("Advanced") { REQUIRE(g2AugSignVector1 == g2AugSignBytes1); REQUIRE(g2AugSignVector1 != g2AugSign2); - REQUIRE(AugSchemeMPL().Verify(Bytes(g1_1.Serialize()), Bytes(vecHash), Bytes(g2AugSignVector1.Serialize()))); + REQUIRE(AugSchemeMPL().Verify( + Bytes(g1_1.Serialize()), + Bytes(vecHash), + Bytes(g2AugSignVector1.Serialize()))); REQUIRE(AugSchemeMPL().Verify(g1_1, Bytes(vecHash), g2AugSignVector1)); - vector> vecG1AugVector = {g1_1.Serialize(), g1_2.Serialize()}; - vector> vecG2AugVector = {g2AugSignVector1.Serialize(), g2AugSign2.Serialize()}; + vector> vecG1AugVector = { + g1_1.Serialize(), g1_2.Serialize()}; + vector> vecG2AugVector = { + g2AugSignVector1.Serialize(), g2AugSign2.Serialize()}; auto aggAugVector = AugSchemeMPL().Aggregate(vecG2AugVector); - auto aggAugBytes = AugSchemeMPL().Aggregate(vector{vecG2AugVector.begin(), vecG2AugVector.end()}); + auto aggAugBytes = AugSchemeMPL().Aggregate( + vector{vecG2AugVector.begin(), vecG2AugVector.end()}); REQUIRE(aggAugVector == aggAugBytes); - REQUIRE(AugSchemeMPL().AggregateVerify(vector{vecG1AugVector.begin(), vecG1AugVector.end()}, - vector{vecHashes.begin(), vecHashes.end()}, - Bytes(aggAugVector))); - REQUIRE(AugSchemeMPL().AggregateVerify({g1_1, g1_2}, - vector{vecHashes.begin(), vecHashes.end()}, - G2Element::FromBytes(aggAugVector))); + REQUIRE(AugSchemeMPL().AggregateVerify( + vector{vecG1AugVector.begin(), vecG1AugVector.end()}, + vector{vecHashes.begin(), vecHashes.end()}, + Bytes(aggAugVector))); + REQUIRE(AugSchemeMPL().AggregateVerify( + {g1_1, g1_2}, + vector{vecHashes.begin(), vecHashes.end()}, + G2Element::FromBytes(aggAugVector))); G2Element proof = PopSchemeMPL().PopProve(pk1); REQUIRE(PopSchemeMPL().PopVerify(g1_1, proof)); - REQUIRE(PopSchemeMPL().PopVerify(Bytes(g1_1.Serialize()), Bytes(proof.Serialize()))); + REQUIRE(PopSchemeMPL().PopVerify( + Bytes(g1_1.Serialize()), Bytes(proof.Serialize()))); G2Element g2Pop1 = PopSchemeMPL().Sign(pk1, vecHash); G2Element g2Pop2 = PopSchemeMPL().Sign(pk2, vecHash); G2Element g2PopAgg = PopSchemeMPL().Aggregate({g2Pop1, g2Pop2}); vecG1Vector = {g1_1.Serialize(), g1_2.Serialize()}; - REQUIRE(PopSchemeMPL().FastAggregateVerify({g1_1, g1_2}, Bytes(vecHash), g2PopAgg)); - REQUIRE(PopSchemeMPL().FastAggregateVerify(vector{vecG1Vector.begin(), vecG1Vector.end()}, - Bytes(vecHash), Bytes(g2PopAgg.Serialize()))); + REQUIRE(PopSchemeMPL().FastAggregateVerify( + {g1_1, g1_2}, Bytes(vecHash), g2PopAgg)); + REQUIRE(PopSchemeMPL().FastAggregateVerify( + vector{vecG1Vector.begin(), vecG1Vector.end()}, + Bytes(vecHash), + Bytes(g2PopAgg.Serialize()))); } } - -TEST_CASE("Schemes") { - SECTION("Basic Scheme") { +TEST_CASE("Schemes") +{ + SECTION("Basic Scheme") + { vector seed1(32, 0x04); vector seed2(32, 0x05); std::array msg1 = {7, 8, 9}; @@ -1073,7 +1242,6 @@ TEST_CASE("Schemes") { G2Element sig1 = BasicSchemeMPL().Sign(sk1, msg1); vector sig1v = BasicSchemeMPL().Sign(sk1, msg1).Serialize(); - REQUIRE(BasicSchemeMPL().Verify(pk1v, msg1, sig1v)); PrivateKey sk2 = BasicSchemeMPL().KeyGen(seed2); @@ -1093,7 +1261,8 @@ TEST_CASE("Schemes") { REQUIRE(BasicSchemeMPL().Verify(pk2v, msg1, sig1v) == false); G2Element aggsig = BasicSchemeMPL().Aggregate({sig1, sig2}); - auto aggsigv = BasicSchemeMPL().Aggregate(vector>{sig1v, sig2v}); + auto aggsigv = + BasicSchemeMPL().Aggregate(vector>{sig1v, sig2v}); REQUIRE(BasicSchemeMPL().AggregateVerify({pk1, pk2}, msgs, aggsig)); REQUIRE(BasicSchemeMPL().AggregateVerify({pk1v, pk2v}, msgs, aggsigv)); } @@ -1132,7 +1301,8 @@ TEST_CASE("Schemes") { REQUIRE(AugSchemeMPL().Verify(pk2v, msg1, sig1v) == false); G2Element aggsig = AugSchemeMPL().Aggregate({sig1, sig2}); - auto aggsigv = AugSchemeMPL().Aggregate(vector>{sig1v, sig2v}); + auto aggsigv = + AugSchemeMPL().Aggregate(vector>{sig1v, sig2v}); REQUIRE(AugSchemeMPL().AggregateVerify({pk1, pk2}, msgs, aggsig)); REQUIRE(AugSchemeMPL().AggregateVerify({pk1v, pk2v}, msgs, Bytes(aggsigv.data(), aggsigv.size()))); } @@ -1171,7 +1341,8 @@ TEST_CASE("Schemes") { REQUIRE(PopSchemeMPL().Verify(pk2v, msg1, sig1v) == false); G2Element aggsig = PopSchemeMPL().Aggregate({sig1, sig2}); - auto aggsigv = PopSchemeMPL().Aggregate(vector>{sig1v, sig2v}); + auto aggsigv = + PopSchemeMPL().Aggregate(vector>{sig1v, sig2v}); REQUIRE(PopSchemeMPL().AggregateVerify({pk1, pk2}, msgs, aggsig)); REQUIRE(PopSchemeMPL().AggregateVerify({pk1v, pk2v}, msgs, Bytes(aggsigv.data(), aggsigv.size()))); @@ -1186,8 +1357,8 @@ TEST_CASE("Schemes") { G2Element sig2_same = PopSchemeMPL().Sign(sk2, msg1); vector sig2v_same = PopSchemeMPL().Sign(sk2, msg1).Serialize(); G2Element aggsig_same = PopSchemeMPL().Aggregate({sig1, sig2_same}); - auto aggsigv_same = - PopSchemeMPL().Aggregate(vector>{sig1v, sig2v_same}); + auto aggsigv_same = PopSchemeMPL().Aggregate( + vector>{sig1v, sig2v_same}); REQUIRE( PopSchemeMPL().FastAggregateVerify({pk1, pk2}, msg1, aggsig_same)); REQUIRE(PopSchemeMPL().FastAggregateVerify( @@ -1245,8 +1416,7 @@ TEST_CASE("Schemes") { legacySigs.push_back(legacyScheme.Sign(sk, message)); } - G2Element legacySecureAggSig; - REQUIRE_NOTHROW(legacySecureAggSig = legacyScheme.AggregateSecure(legacyPks, legacySigs, message)); + G2Element legacySecureAggSig = legacyScheme.AggregateSecure(legacyPks, legacySigs, message); REQUIRE(legacyScheme.VerifySecure(legacyPks, legacySecureAggSig, message)); } @@ -1368,9 +1538,11 @@ TEST_CASE("Legacy HD keys") { .GetPublicKey(); REQUIRE(sk3.GetG1Element() == pk4); - G2Element sig = LegacySchemeMPL().Sign(sk3, Bytes(seed)); + // the legacy scheme signs 32-byte message hashes + std::vector hash(32, 0x42); + G2Element sig = LegacySchemeMPL().Sign(sk3, Bytes(hash)); - REQUIRE(LegacySchemeMPL().Verify(sk3.GetG1Element(), Bytes(seed), sig)); + REQUIRE(LegacySchemeMPL().Verify(sk3.GetG1Element(), Bytes(hash), sig)); } SECTION("Should prevent hardened pk derivation") { @@ -1402,7 +1574,8 @@ TEST_CASE("Legacy HD keys") { cout << epk.GetPublicKey() << endl; cout << epk.GetChainCode() << endl; - G2Element sig1 = LegacySchemeMPL().Sign(esk.GetPrivateKey(), Bytes(seed)); + std::vector hash(32, 0x42); + G2Element sig1 = LegacySchemeMPL().Sign(esk.GetPrivateKey(), Bytes(hash)); cout << sig1 << endl; } @@ -1518,7 +1691,8 @@ TEST_CASE("Threshold Signatures") { TEST_CASE("CheckValid") { - SECTION("Valid points should succeed") { + SECTION("Valid points should succeed") + { vector seed(32, 0x05); vector msg1 = {10, 11, 12}; @@ -1540,37 +1714,464 @@ TEST_CASE("CheckValid") G1Element::FromBytes(Bytes(Util::HexToBytes(badPointHex)))); // FromBytesUnchecked does not throw - G1Element pk = + G1Element bad_pk = G1Element::FromBytesUnchecked(Bytes(Util::HexToBytes(badPointHex))); - REQUIRE(pk.IsValid() == false); - REQUIRE_THROWS(pk.CheckValid()); + REQUIRE(bad_pk.IsValid() == false); + REQUIRE_THROWS(bad_pk.CheckValid()); vector seed(32, 0x05); vector msg1 = {10, 11, 12}; PrivateKey sk1 = BasicSchemeMPL().KeyGen(seed); - G1Element pk1 = BasicSchemeMPL().SkToG1(sk1); + G1Element good_pk = BasicSchemeMPL().SkToG1(sk1); + REQUIRE(good_pk.IsValid() == true); G2Element sig1 = AugSchemeMPL().Sign(sk1, msg1); - REQUIRE(AugSchemeMPL().Verify(pk, msg1, sig1) == false); + REQUIRE(AugSchemeMPL().Verify(bad_pk, msg1, sig1) == false); + REQUIRE(AugSchemeMPL().Verify(good_pk, msg1, sig1) == true); } - SECTION("Invalid G2 points should not succeed") { - g2_t point_native; - g2_set_infty(point_native); - fp2_rand(point_native->x); - fp2_rand(point_native->y); - fp2_rand(point_native->z); + SECTION("Invalid G2 points should not succeed") + { + blst_p2 point_native; + memset(&point_native, 0, sizeof(blst_p2)); + + // fixed garbage coordinates: not on the curve and not infinity + memset(&(point_native.x), 0x11, sizeof(point_native.x)); + memset(&(point_native.y), 0x22, sizeof(point_native.y)); + memset(&(point_native.z), 0x33, sizeof(point_native.z)); G2Element point = G2Element::FromNative(point_native); REQUIRE(point.IsValid() == false); REQUIRE_THROWS(point.CheckValid()); auto badSer = point.Serialize(); - std::cout < pks = {G1Element()}; + vector msgs = {Bytes(msg)}; + REQUIRE(LegacySchemeMPL().AggregateVerify(pks, msgs, sig) == false); + } + + SECTION("AggregateVerify rejects identity signature with non-empty pubkeys") + { + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto msg = getRandomSeed(); + vector pks = {pk}; + vector msgs = {Bytes(msg)}; + REQUIRE(LegacySchemeMPL().AggregateVerify(pks, msgs, G2Element()) == false); + } + + SECTION("Verify rejects malformed non-identity pubkey") + { + string badPointHex = + "8d5d0fb73b9c92df4eab4216e48c3e358578b4cc30f82c268bd6fef3bd34b558628daf1afef798d4c3b0fcd8b28c8973"; + G1Element badPk = G1Element::FromBytesUnchecked(Bytes(Util::HexToBytes(badPointHex))); + REQUIRE(badPk.IsValid() == false); + + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = LegacySchemeMPL().Sign(sk, Bytes(msg)); + REQUIRE(LegacySchemeMPL().Verify(badPk, Bytes(msg), sig) == false); + } + + SECTION("Verify rejects malformed non-identity signature") + { + // Build an invalid G2 element from native coordinates: + // (-x, y) of the generator: not on the curve + blst_p2 point_native = *blst_p2_generator(); + blst_fp2_cneg(&point_native.x, &point_native.x, true); + G2Element badSig = G2Element::FromNative(point_native); + REQUIRE(badSig.IsValid() == false); + + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto msg = getRandomSeed(); + REQUIRE(LegacySchemeMPL().Verify(pk, Bytes(msg), badSig) == false); + } + + SECTION("AggregateVerify rejects malformed non-identity pubkey") + { + string badPointHex = + "8d5d0fb73b9c92df4eab4216e48c3e358578b4cc30f82c268bd6fef3bd34b558628daf1afef798d4c3b0fcd8b28c8973"; + G1Element badPk = G1Element::FromBytesUnchecked(Bytes(Util::HexToBytes(badPointHex))); + + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = LegacySchemeMPL().Sign(sk, Bytes(msg)); + vector pks = {badPk}; + vector msgs = {Bytes(msg)}; + REQUIRE(LegacySchemeMPL().AggregateVerify(pks, msgs, sig) == false); + } +} + +TEST_CASE("VerifySecure calls CoreMPL::AggregateVerify directly") +{ + SECTION("BasicSchemeMPL VerifySecure round-trips correctly") + { + auto sk1 = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto sk2 = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto pk1 = sk1.GetG1Element(); + auto pk2 = sk2.GetG1Element(); + auto msg = getRandomSeed(); + + auto sig1 = BasicSchemeMPL().Sign(sk1, msg); + auto sig2 = BasicSchemeMPL().Sign(sk2, msg); + + vector pks = {pk1, pk2}; + vector sigs = {sig1, sig2}; + auto aggSig = BasicSchemeMPL().AggregateSecure(pks, sigs, Bytes(msg)); + + REQUIRE(BasicSchemeMPL().VerifySecure(pks, aggSig, Bytes(msg))); + } + + SECTION("AugSchemeMPL VerifySecure round-trips correctly") + { + auto sk1 = AugSchemeMPL().KeyGen(getRandomSeed()); + auto sk2 = AugSchemeMPL().KeyGen(getRandomSeed()); + auto pk1 = sk1.GetG1Element(); + auto pk2 = sk2.GetG1Element(); + auto msg = getRandomSeed(); + + auto sig1 = AugSchemeMPL().Sign(sk1, msg); + auto sig2 = AugSchemeMPL().Sign(sk2, msg); + + vector pks = {pk1, pk2}; + vector sigs = {sig1, sig2}; + auto aggSig = AugSchemeMPL().AggregateSecure(pks, sigs, Bytes(msg)); + + REQUIRE(AugSchemeMPL().VerifySecure(pks, aggSig, Bytes(msg))); + } + + SECTION("BasicSchemeMPL VerifySecure rejects identity pubkey") + { + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = BasicSchemeMPL().Sign(sk, msg); + + vector pks = {G1Element()}; + REQUIRE(BasicSchemeMPL().VerifySecure(pks, sig, Bytes(msg)) == false); + } + + SECTION("BasicSchemeMPL VerifySecure rejects identity signature") + { + auto sk1 = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto sk2 = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + + vector pks = {sk1.GetG1Element(), sk2.GetG1Element()}; + REQUIRE(BasicSchemeMPL().VerifySecure(pks, G2Element(), Bytes(msg)) == false); + } + + SECTION("AugSchemeMPL VerifySecure rejects identity pubkey") + { + auto sk = AugSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = AugSchemeMPL().Sign(sk, msg); + + vector pks = {G1Element()}; + REQUIRE(AugSchemeMPL().VerifySecure(pks, sig, Bytes(msg)) == false); + } + + SECTION("AugSchemeMPL VerifySecure rejects identity signature") + { + auto sk1 = AugSchemeMPL().KeyGen(getRandomSeed()); + auto sk2 = AugSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + + vector pks = {sk1.GetG1Element(), sk2.GetG1Element()}; + REQUIRE(AugSchemeMPL().VerifySecure(pks, G2Element(), Bytes(msg)) == false); + } +} + +TEST_CASE("PopSchemeMPL::PopVerify bytes overload consistent error handling") +{ + SECTION("Malformed pubkey bytes returns false instead of throwing") + { + vector badPk(G1Element::SIZE, 0xff); + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto pop = PopSchemeMPL().PopProve(sk); + auto popBytes = pop.Serialize(); + REQUIRE_NOTHROW(PopSchemeMPL().PopVerify(Bytes(badPk), Bytes(popBytes))); + REQUIRE(PopSchemeMPL().PopVerify(Bytes(badPk), Bytes(popBytes)) == false); + } + + SECTION("Malformed proof bytes returns false instead of throwing") + { + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto pkBytes = pk.Serialize(); + vector badProof(G2Element::SIZE, 0xff); + REQUIRE_NOTHROW(PopSchemeMPL().PopVerify(Bytes(pkBytes), Bytes(badProof))); + REQUIRE(PopSchemeMPL().PopVerify(Bytes(pkBytes), Bytes(badProof)) == false); + } + + SECTION("Valid proof still verifies through bytes overload") + { + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto pop = PopSchemeMPL().PopProve(sk); + auto pkBytes = pk.Serialize(); + auto popBytes = pop.Serialize(); + REQUIRE(PopSchemeMPL().PopVerify(Bytes(pkBytes), Bytes(popBytes))); + } +} + +TEST_CASE("Bytes overloads return false on malformed input instead of throwing") +{ + SECTION("CoreMPL::Verify with malformed pubkey bytes") + { + vector badPk(G1Element::SIZE, 0xff); + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = BasicSchemeMPL().Sign(sk, msg); + auto sigBytes = sig.Serialize(); + REQUIRE_NOTHROW(BasicSchemeMPL().Verify(Bytes(badPk), Bytes(msg), Bytes(sigBytes))); + REQUIRE(BasicSchemeMPL().Verify(Bytes(badPk), Bytes(msg), Bytes(sigBytes)) == false); + } + + SECTION("CoreMPL::Verify with malformed signature bytes") + { + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto pkBytes = pk.Serialize(); + auto msg = getRandomSeed(); + vector badSig(G2Element::SIZE, 0xff); + REQUIRE_NOTHROW(BasicSchemeMPL().Verify(Bytes(pkBytes), Bytes(msg), Bytes(badSig))); + REQUIRE(BasicSchemeMPL().Verify(Bytes(pkBytes), Bytes(msg), Bytes(badSig)) == false); + } + + SECTION("CoreMPL::AggregateVerify with malformed pubkey bytes") + { + vector badPk(G1Element::SIZE, 0xff); + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = BasicSchemeMPL().Sign(sk, msg); + auto sigBytes = sig.Serialize(); + vector pks = {Bytes(badPk)}; + vector msgs = {Bytes(msg)}; + REQUIRE_NOTHROW(BasicSchemeMPL().AggregateVerify(pks, msgs, Bytes(sigBytes))); + REQUIRE(BasicSchemeMPL().AggregateVerify(pks, msgs, Bytes(sigBytes)) == false); + } + + SECTION("CoreMPL::AggregateVerify with malformed signature bytes") + { + auto sk = BasicSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto pkBytes = pk.Serialize(); + auto msg = getRandomSeed(); + vector badSig(G2Element::SIZE, 0xff); + vector pks = {Bytes(pkBytes)}; + vector msgs = {Bytes(msg)}; + REQUIRE_NOTHROW(BasicSchemeMPL().AggregateVerify(pks, msgs, Bytes(badSig))); + REQUIRE(BasicSchemeMPL().AggregateVerify(pks, msgs, Bytes(badSig)) == false); + } + + SECTION("FastAggregateVerify with malformed pubkey bytes") + { + vector badPk(G1Element::SIZE, 0xff); + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = PopSchemeMPL().Sign(sk, msg); + auto sigBytes = sig.Serialize(); + vector pks = {Bytes(badPk)}; + REQUIRE_NOTHROW(PopSchemeMPL().FastAggregateVerify(pks, Bytes(msg), Bytes(sigBytes))); + REQUIRE(PopSchemeMPL().FastAggregateVerify(pks, Bytes(msg), Bytes(sigBytes)) == false); + } + + SECTION("AugSchemeMPL::AggregateVerify with malformed signature bytes") + { + auto sk = AugSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto pkBytes = pk.Serialize(); + auto msg = getRandomSeed(); + vector badSig(G2Element::SIZE, 0xff); + vector pks = {Bytes(pkBytes)}; + vector msgs = {Bytes(msg)}; + REQUIRE_NOTHROW(AugSchemeMPL().AggregateVerify(pks, msgs, Bytes(badSig))); + REQUIRE(AugSchemeMPL().AggregateVerify(pks, msgs, Bytes(badSig)) == false); + } +} + +TEST_CASE("PopSchemeMPL::PopVerify rejects identity elements") +{ + SECTION("PopVerify rejects identity pubkey") + { + REQUIRE(PopSchemeMPL().PopVerify(G1Element(), G2Element()) == false); + } + + SECTION("PopVerify rejects identity proof with valid pubkey") + { + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + REQUIRE(PopSchemeMPL().PopVerify(pk, G2Element()) == false); + } +} + +TEST_CASE("FastAggregateVerify rejects identity elements") +{ + SECTION("Identity pubkey in list is rejected") + { + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto msg = getRandomSeed(); + auto sig = PopSchemeMPL().Sign(sk, msg); + vector pks = {pk, G1Element()}; + REQUIRE(PopSchemeMPL().FastAggregateVerify(pks, Bytes(msg), sig) == false); + } + + SECTION("All identity pubkeys rejected") + { + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto msg = getRandomSeed(); + auto sig = PopSchemeMPL().Sign(sk, msg); + vector pks = {G1Element()}; + REQUIRE(PopSchemeMPL().FastAggregateVerify(pks, Bytes(msg), sig) == false); + } + + SECTION("Identity signature rejected") + { + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto msg = getRandomSeed(); + vector pks = {pk}; + REQUIRE(PopSchemeMPL().FastAggregateVerify(pks, Bytes(msg), G2Element()) == false); + } + + SECTION("Malformed non-identity signature rejected") + { + // (-x, y) of the generator: not on the curve + blst_p2 point_native = *blst_p2_generator(); + blst_fp2_cneg(&point_native.x, &point_native.x, true); + G2Element badSig = G2Element::FromNative(point_native); + REQUIRE(badSig.IsValid() == false); + + auto sk = PopSchemeMPL().KeyGen(getRandomSeed()); + auto pk = sk.GetG1Element(); + auto msg = getRandomSeed(); + vector pks = {pk}; + REQUIRE(PopSchemeMPL().FastAggregateVerify(pks, Bytes(msg), badSig) == false); + } +} + +TEST_CASE("G1 zeros-only check masks the flag bits of the first byte") +{ + // 0x85 || 47 zero bytes encodes x = 5 * 2^376, not an all-zero payload. + // relic decompressed it to an on-curve point outside the subgroup, so the + // unchecked decoder must do the same and the checked one must reject it + // for that reason, as the G2 decoder already does. + std::vector in(48, 0); + in[0] = 0x85; + G1Element u = G1Element::FromBytesUnchecked(Bytes(in)); + REQUIRE(!u.IsValid()); + REQUIRE(u.Serialize() == in); + REQUIRE_THROWS(G1Element::FromBytes(Bytes(in))); +} + +TEST_CASE("IsValid rejects points off the curve") +{ + // (4x, 8y, z) of the generator is not on the curve but passes blst's + // subgroup test, which assumes a curve point + uint8_t be[48] = {0}; + blst_fp four, eight; + be[47] = 4; + blst_fp_from_bendian(&four, be); + be[47] = 8; + blst_fp_from_bendian(&eight, be); + + blst_p1 off1 = *blst_p1_generator(); + blst_fp_mul(&off1.x, &off1.x, &four); + blst_fp_mul(&off1.y, &off1.y, &eight); + REQUIRE(!G1Element::FromNative(off1).IsValid()); + + blst_p2 off2 = *blst_p2_generator(); + blst_fp2 four2, eight2; + memset(&four2, 0, sizeof(four2)); + memset(&eight2, 0, sizeof(eight2)); + four2.fp[0] = four; + eight2.fp[0] = eight; + blst_fp2_mul(&off2.x, &off2.x, &four2); + blst_fp2_mul(&off2.y, &off2.y, &eight2); + REQUIRE(!G2Element::FromNative(off2).IsValid()); +} + +TEST_CASE("Degenerate legacy signatures do not verify") +{ + // A legacy G2 decode of x = (0, 0) with no square root leaves the point + // (0, 0, 1): not infinity, but (0, 0) in affine form. IsValid() rejects + // it before the pairing product. + std::vector h(32, 0x11); + G1Element g = G1Element::Generator(); + std::vector pp(96, 0); // c0 = p, c1 = p, both read as zero + const std::vector p = Util::HexToBytes( + "1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab"); + std::copy(p.begin(), p.end(), pp.begin()); + std::copy(p.begin(), p.end(), pp.begin() + 48); + for (const std::vector& in : {std::vector(96, 0), pp}) { + G2Element bad = G2Element::FromBytes(Bytes(in), true); + REQUIRE(!LegacySchemeMPL().Verify(G1Element(), Bytes(h), bad)); + REQUIRE(!LegacySchemeMPL().Verify(g, Bytes(h), bad)); + std::vector pks{g, g.Negate()}; + std::vector msgs{Bytes(h), Bytes(h)}; + REQUIRE(!LegacySchemeMPL().AggregateVerify(pks, msgs, bad)); + } +} + +TEST_CASE("Legacy verification rejects messages that are not 32 bytes") +{ + PrivateKey sk = BasicSchemeMPL().KeyGen(std::vector(32, 0x55)); + std::vector h(32, 0x11); + G2Element sig = LegacySchemeMPL().Sign(sk, Bytes(h)); + REQUIRE(LegacySchemeMPL().Verify(sk.GetG1Element(), Bytes(h), sig)); + std::vector h31(31, 0x11), h33(33, 0x11); + REQUIRE(!LegacySchemeMPL().Verify(sk.GetG1Element(), Bytes(h31), sig)); + REQUIRE(!LegacySchemeMPL().Verify(sk.GetG1Element(), Bytes(h33), sig)); + REQUIRE_THROWS(LegacySchemeMPL().Sign(sk, Bytes(h31))); +} + +TEST_CASE("Secure aggregation rejects an infinity public key") +{ + BasicSchemeMPL basic; + vector seed1(32, 0x11); + vector seed2(32, 0x22); + vector msg(32, 0x33); + PrivateKey sk1 = basic.KeyGen(seed1); + PrivateKey sk2 = basic.KeyGen(seed2); + vector pks = {sk1.GetG1Element(), sk2.GetG1Element()}; + vector sigs = {basic.Sign(sk1, msg), basic.Sign(sk2, msg)}; + + // positive control first, then only the second key changes + G2Element agg = basic.AggregateSecure(pks, sigs, Bytes(msg)); + REQUIRE(basic.VerifySecure(pks, agg, Bytes(msg))); + pks[1] = G1Element(); + REQUIRE(!basic.VerifySecure(pks, agg, Bytes(msg))); +} + TEST_CASE("CheckValid for Legacy") { SECTION("Invalid G1 points should throw in CheckValid but not in FromBytes") @@ -1620,6 +2221,114 @@ TEST_CASE("CheckValid for Legacy") } } +// Locates test-vectors/reference.txt: an environment variable overrides +// the path the build system compiled in; source-tree-relative paths cover +// running the binary by hand. +static std::string ReferenceVectorsPath() +{ + std::vector candidates; + if (const char* env = std::getenv("DASHBLS_REFERENCE_VECTORS")) { + candidates.push_back(env); + } +#ifdef DASHBLS_REFERENCE_VECTORS + candidates.push_back(DASHBLS_REFERENCE_VECTORS); +#endif + candidates.push_back("test-vectors/reference.txt"); + candidates.push_back("../test-vectors/reference.txt"); + candidates.push_back("../../test-vectors/reference.txt"); + for (const auto& c : candidates) { + if (std::ifstream(c).good()) return c; + } + std::string tried; + for (const auto& c : candidates) tried += "\n " + c; + FAIL("reference vectors not found; tried:" << tried); + return ""; +} + +TEST_CASE("Reference vectors") +{ + // Every consensus-visible behavior of the library, compared line by line + // against the output of the relic-based implementation. + const std::string path = ReferenceVectorsPath(); + INFO("reference file: " << path); + + std::vector expected; + std::ifstream in(path); + for (std::string line; std::getline(in, line);) { + if (line.empty() || line[0] == '#') continue; + expected.push_back(line); + } + REQUIRE(expected.size() > 300); + + std::vector actual; + for (const auto& line : bls_test_vectors::GenerateReferenceVectors()) { + if (line.empty() || line[0] == '#') continue; + actual.push_back(line); + } + + REQUIRE(actual.size() == expected.size()); + for (size_t i = 0; i < expected.size(); i++) { + INFO("vector " << i + 1 << " of " << expected.size()); + REQUIRE(actual[i] == expected[i]); + } +} + +TEST_CASE("GTElement") +{ + SECTION("GTElement serialization") + { + vector seed(32, 0x05); + blst_p1_affine p1_affine; + + PrivateKey sk1 = BasicSchemeMPL().KeyGen(seed); + G1Element pk1 = BasicSchemeMPL().SkToG1(sk1); + pk1.CheckValid(); + pk1.ToAffine(&p1_affine); + GTElement gt1 = GTElement::FromAffine(p1_affine); + + auto outbuf = gt1.Serialize(); + + auto gt2 = GTElement::FromBytesUnchecked(outbuf); + + REQUIRE(gt1 == gt2); + } + + SECTION("GTElement pairing") + { + vector seed(32, 0x05), seed2(32, 0x06); + vector msg1 = {7, 8, 9}; + vector msg2 = {10, 11, 12}; + + auto sk1 = BasicSchemeMPL().KeyGen(seed); + auto sk2 = BasicSchemeMPL().KeyGen(seed2); + + auto pk1 = sk1.GetG1Element(); + auto pk2 = sk2.GetG1Element(); + + auto sig1 = BasicSchemeMPL().Sign(sk1, msg1); + auto sig2 = BasicSchemeMPL().Sign(sk2, msg2); + + auto aggsig = BasicSchemeMPL().Aggregate({sig1, sig2}); + + REQUIRE(BasicSchemeMPL().AggregateVerify( + {pk1, pk2}, vector>{msg1, msg2}, aggsig)); + + auto pair1 = pk1.Pair(G2Element::FromMessage( + msg1, + (const uint8_t*)BasicSchemeMPL::CIPHERSUITE_ID.c_str(), + BasicSchemeMPL::CIPHERSUITE_ID.length())); + auto pair2 = pk2.Pair(G2Element::FromMessage( + msg2, + (const uint8_t*)BasicSchemeMPL::CIPHERSUITE_ID.c_str(), + BasicSchemeMPL::CIPHERSUITE_ID.length())); + auto pair = pair1 * pair2; + + auto agg_sig_pair = G1Element::Generator().Pair(aggsig); + + REQUIRE(pair == agg_sig_pair); + } +} + int main(int argc, char* argv[]) { int result = Catch::Session().run(argc, argv); diff --git a/src/threshold.cpp b/src/threshold.cpp index 4561dccdc3a6..8526832b7718 100644 --- a/src/threshold.cpp +++ b/src/threshold.cpp @@ -7,75 +7,9 @@ #include "threshold.hpp" #include "schemes.hpp" -#include "bn_helpers.hpp" static std::unique_ptr pThresholdScheme(new bls::LegacySchemeMPL); -/** - * Inverts a prime field element using the Euclidean Extended Algorithm, - * using bns and a custom prime modulus. - * - * @param[out] c - the result. - * @param[in] a - the prime field element to invert. - * @param[in] p - the custom prime modulus. - */ -static void fp_inv_exgcd_bn(bn_t c, const bn_t u_in, const bn_t p) { - bn_t u, v, g1, g2, q, r; - - bn_null(u); - bn_null(v); - bn_null(g1); - bn_null(g2); - bn_null(q); - bn_null(r); - - RLC_TRY { - bn_new(u); - bn_new(v); - bn_new(g1); - bn_new(g2); - bn_new(q); - bn_new(r); - - /* u = a, v = p, g1 = 1, g2 = 0. */ - bn_copy(u, u_in); - bn_copy(v, p); - bn_set_dig(g1, 1); - bn_zero(g2); - - /* While (u != 1. */ - while (bn_cmp_dig(u, 1) != RLC_EQ) { - /* q = [v/u], r = v mod u. */ - bn_div_rem(q, r, v, u); - /* v = u, u = r. */ - bn_copy(v, u); - bn_copy(u, r); - /* r = g2 - q * g1. */ - bn_mul(r, q, g1); - bn_sub(r, g2, r); - /* g2 = g1, g1 = r. */ - bn_copy(g2, g1); - bn_copy(g1, r); - } - - if (bn_sign(g1) == RLC_NEG) { - bn_add(g1, g1, p); - } - bn_copy(c, g1); - } - RLC_CATCH_ANY { - RLC_THROW(ERR_CAUGHT); - } - RLC_FINALLY { - bn_free(u); - bn_free(v); - bn_free(g1); - bn_free(g2); - bn_free(q); - bn_free(r); - }; -} - namespace bls { namespace Poly { @@ -90,43 +24,32 @@ namespace bls { } // end namespace Poly struct PolyOpsBase { - bn_t order; - bn_t iv; - - PolyOpsBase() { - bn_new(order); - gt_get_ord(order); - bn_new(iv); + static bool IsZero(const blst_scalar& a) { + std::array zero{}; + return memcmp(&a, &zero, sizeof(blst_scalar)) == 0; } - ~PolyOpsBase() { - bn_free(iv); - bn_free(order); + void MulFP(blst_scalar& r, const blst_scalar& a, const blst_scalar& b) { + blst_sk_mul_n_check(&r, &a, &b); } - void MulFP(bn_t& r, const bn_t& a, const bn_t& b) { - bn_mul(r, a, b); - ModOrder(r); + void AddFP(blst_scalar& r, const blst_scalar& a, const blst_scalar& b) { + blst_sk_add_n_check(&r, &a, &b); } - void AddFP(bn_t& r, const bn_t& a, const bn_t& b) { - bn_add(r, a, b); - ModOrder(r); + void SubFP(blst_scalar& r, const blst_scalar& a, const blst_scalar& b) { + blst_sk_sub_n_check(&r, &a, &b); } - void SubFP(bn_t& r, const bn_t& a, const bn_t& b) { - bn_sub(r, a, b); - ModOrder(r); + void DivFP(blst_scalar& r, const blst_scalar& a, const blst_scalar& b) { + blst_scalar iv; + blst_sk_inverse(&iv, &b); + blst_sk_mul_n_check(&r, &a, &iv); } - void DivFP(bn_t& r, const bn_t& a, const bn_t& b) { - fp_inv_exgcd_bn(iv, b, order); - bn_mul(r, a, iv); - ModOrder(r); - } - - void ModOrder(bn_t& r) { - bn_mod(r, r, order); + void ScalarFromBytes(blst_scalar& r, const uint8_t* bytes) { + // reduces mod the group order, like bn_read_bin + bn_mod + blst_scalar_from_be_bytes(&r, bytes, Poly::nIdSize); } }; @@ -139,7 +62,7 @@ namespace bls { return PrivateKey::Aggregate({a, b}); } - PrivateKey Mul(const PrivateKey& a, const bn_t& b) { + PrivateKey Mul(const PrivateKey& a, const blst_scalar& b) { return a * b; } }; @@ -150,7 +73,7 @@ namespace bls { return a + b; } - G1Element Mul(const G1Element& a, const bn_t& b) { + G1Element Mul(const G1Element& a, const blst_scalar& b) { return a * b; } }; @@ -161,7 +84,7 @@ namespace bls { return a + b; } - G2Element Mul(const G2Element& a, bn_t& b) { + G2Element Mul(const G2Element& a, const blst_scalar& b) { return a * b; } }; @@ -174,13 +97,12 @@ namespace bls { throw std::length_error("At least 2 coefficients required"); } - BnGuard x; - bn_read_bin(x.val, id.begin(), Poly::nIdSize); - ops.ModOrder(x.val); + blst_scalar x; + ops.ScalarFromBytes(x, id.begin()); BLSType y = vecIn.back(); for (int i = (int) vecIn.size() - 2; i >= 0; i--) { - y = ops.Mul(y, x.val); + y = ops.Mul(y, x); y = ops.Add(y, vecIn[i]); } @@ -205,35 +127,34 @@ namespace bls { */ const size_t k = vec.size(); - BnArrayGuard delta(k); - BnArrayGuard ids2(k); + std::vector delta(k); + std::vector ids2(k); for (size_t i = 0; i < k; i++) { - bn_read_bin(ids2[i], ids[i].begin(), Poly::nIdSize); - ops.ModOrder(ids2[i]); + ops.ScalarFromBytes(ids2[i], ids[i].begin()); } - BnGuard a, b, v; + blst_scalar a, b, v; - bn_copy(a.val, ids2[0]); + a = ids2[0]; for (size_t i = 1; i < k; i++) { - ops.MulFP(a.val, a.val, ids2[i]); + ops.MulFP(a, a, ids2[i]); } - if (bn_is_zero(a.val)) { + if (PolyOpsBase::IsZero(a)) { throw std::invalid_argument("Zero id"); } for (size_t i = 0; i < k; i++) { - bn_copy(b.val, ids2[i]); + b = ids2[i]; for (size_t j = 0; j < k; j++) { if (j != i) { - ops.SubFP(v.val, ids2[j], ids2[i]); - if (bn_is_zero(v.val)) { + ops.SubFP(v, ids2[j], ids2[i]); + if (PolyOpsBase::IsZero(v)) { throw std::invalid_argument("Duplicate id"); } - ops.MulFP(b.val, b.val, v.val); + ops.MulFP(b, b, v); } } - ops.DivFP(delta[i], a.val, b.val); + ops.DivFP(delta[i], a, b); } /* @@ -270,7 +191,7 @@ namespace bls { G2Element Threshold::SignatureRecover(const std::vector& sigs, const std::vector& ids) { return Poly::LagrangeInterpolate(sigs, ids); } - + G2Element Threshold::Sign(const PrivateKey& privateKey, const Bytes& vecMessage) { return pThresholdScheme->Sign(privateKey, vecMessage); } diff --git a/test-vectors/reference.txt b/test-vectors/reference.txt new file mode 100644 index 000000000000..3494cfe385e5 --- /dev/null +++ b/test-vectors/reference.txt @@ -0,0 +1,324 @@ +# dashbls reference vectors v1 +A.sk.0=542b7d7900f6335cba45d5d7a53d59d73f26f230905bfcd6ad91ebb85eaa008a +A.pk.basic.0=9331005927ff67f0bd41be6037dcc07feea679be922e915c9be2a229c38fe5d178527877a6a66126ef4a8619277c58f0 +A.pk.legacy.0=1331005927ff67f0bd41be6037dcc07feea679be922e915c9be2a229c38fe5d178527877a6a66126ef4a8619277c58f0 +A.fp.basic.0=d4ddc775 +A.fp.legacy.0=ca704224 +A.skG2.basic.0=9131d5ad87990f02258898a22680b72d1762a084fd23f793b94477473deb23dbaf5e3a0635aa8bd373136c0bf84d4dbd03d21a5719c4b680b72be4649635262df36794ceeea24865dd55705e4370ef96346efe7795b37f27eb8ae49f134fcad0 +A.skG2.legacy.0=03d21a5719c4b680b72be4649635262df36794ceeea24865dd55705e4370ef96346efe7795b37f27eb8ae49f134fcad01131d5ad87990f02258898a22680b72d1762a084fd23f793b94477473deb23dbaf5e3a0635aa8bd373136c0bf84d4dbd +A.pk.rt.legacy.0=1331005927ff67f0bd41be6037dcc07feea679be922e915c9be2a229c38fe5d178527877a6a66126ef4a8619277c58f0 +A.pk.rt.basic.0=9331005927ff67f0bd41be6037dcc07feea679be922e915c9be2a229c38fe5d178527877a6a66126ef4a8619277c58f0 +B.lsig.legacy.0=8a3b9450bb7620dc07ff10a553ad8e55805aaf1270de68bda5c3ef581945748a3732d0bf6c44e277a92f077b53fb0cc8091006a639d501de9236351b8e6e60da58281ec4a1edab1b26b698e7150c89952ced7dec9d2a95dc492d31f68b6c47ea +B.lsig.basic.0=a91006a639d501de9236351b8e6e60da58281ec4a1edab1b26b698e7150c89952ced7dec9d2a95dc492d31f68b6c47ea0a3b9450bb7620dc07ff10a553ad8e55805aaf1270de68bda5c3ef581945748a3732d0bf6c44e277a92f077b53fb0cc8 +B.lverify.0=1 +B.lverify.bad.0=0 +B.lsig.rt.0=8a3b9450bb7620dc07ff10a553ad8e55805aaf1270de68bda5c3ef581945748a3732d0bf6c44e277a92f077b53fb0cc8091006a639d501de9236351b8e6e60da58281ec4a1edab1b26b698e7150c89952ced7dec9d2a95dc492d31f68b6c47ea +B.bsig.basic.0=8d3631d71a4f57c50f8108adb0cada2be41fba7bb1eced6e2b1757204f4103bbe41b0205cddd12a0c1f723633751eef517dc82561728b2b3482e74a4bbac58ac8851dad5247d11ad9b549690805fd078e02f39a6688e7db82f3a077c2f7dd4ab +B.bsig.legacy.0=17dc82561728b2b3482e74a4bbac58ac8851dad5247d11ad9b549690805fd078e02f39a6688e7db82f3a077c2f7dd4ab0d3631d71a4f57c50f8108adb0cada2be41fba7bb1eced6e2b1757204f4103bbe41b0205cddd12a0c1f723633751eef5 +B.bverify.0=1 +A.child.hard.0=13673dc18365d4d8d67005749ed2fba3c92dac9a259f3dac769288177d2de1ac +A.child.soft.0=43f1ad49de1fac8a337f01f27c48720cf0e453cb48cd8112c4c6aecf191c393b +A.sk.1=0d80059486148cf5dd43d6c2b42d41378e0e2cc354e328089fd5cc1eafb20549 +A.pk.basic.1=b4c69e82f075931025ea1ff15c340a0a0887f8611b7c85d02b9a1e4bcdcb22673d10a26fd3d6018e99777a302a345626 +A.pk.legacy.1=94c69e82f075931025ea1ff15c340a0a0887f8611b7c85d02b9a1e4bcdcb22673d10a26fd3d6018e99777a302a345626 +A.fp.basic.1=68f69bbe +A.fp.legacy.1=00eeb456 +A.skG2.basic.1=91005feee5588ac7887cbd365aff07a2e255cddfaff09016669f7993d68cd9a63793dcade435c0d12e875a683b3cd69a170cff1dd1e7a4e7ce4f7a3538ee76cef7b555524c2e302e4eb8ac2c759b1fa0631395df06e6eae95ca0c3aa82731576 +A.skG2.legacy.1=170cff1dd1e7a4e7ce4f7a3538ee76cef7b555524c2e302e4eb8ac2c759b1fa0631395df06e6eae95ca0c3aa8273157611005feee5588ac7887cbd365aff07a2e255cddfaff09016669f7993d68cd9a63793dcade435c0d12e875a683b3cd69a +A.pk.rt.legacy.1=94c69e82f075931025ea1ff15c340a0a0887f8611b7c85d02b9a1e4bcdcb22673d10a26fd3d6018e99777a302a345626 +A.pk.rt.basic.1=b4c69e82f075931025ea1ff15c340a0a0887f8611b7c85d02b9a1e4bcdcb22673d10a26fd3d6018e99777a302a345626 +B.lsig.legacy.1=103edb2bcadfc658095e04ccbaf682d075612fb86e2be06366fef0d1245a9ff7f87c1c8a3bc8b89a88585d9c568389ea043ae22ef8777d79719cff2cc0c777fcb16277c9f5b3a4ed782b045ecc41421b6302941ee7cfd769e645ecaea359f457 +B.lsig.basic.1=843ae22ef8777d79719cff2cc0c777fcb16277c9f5b3a4ed782b045ecc41421b6302941ee7cfd769e645ecaea359f457103edb2bcadfc658095e04ccbaf682d075612fb86e2be06366fef0d1245a9ff7f87c1c8a3bc8b89a88585d9c568389ea +B.lverify.1=1 +B.lverify.bad.1=0 +B.lsig.rt.1=103edb2bcadfc658095e04ccbaf682d075612fb86e2be06366fef0d1245a9ff7f87c1c8a3bc8b89a88585d9c568389ea043ae22ef8777d79719cff2cc0c777fcb16277c9f5b3a4ed782b045ecc41421b6302941ee7cfd769e645ecaea359f457 +B.bsig.basic.1=80f49f1b340f745c84ab7b51bbb742a6f82fbc04204398683dbcc861ed1f87fa45180c6ba9d5950347fc8d14cae6bc8f105a6d4978bf6c4333b489c656ad1eb3668f7584430a8f9c24349e6199e791e64627bde51a6af2f2905b58c12b121fb6 +B.bsig.legacy.1=105a6d4978bf6c4333b489c656ad1eb3668f7584430a8f9c24349e6199e791e64627bde51a6af2f2905b58c12b121fb600f49f1b340f745c84ab7b51bbb742a6f82fbc04204398683dbcc861ed1f87fa45180c6ba9d5950347fc8d14cae6bc8f +B.bverify.1=1 +A.child.hard.1=35bf9c36f494622db64c5173493cff599df5e765d687742cb6533b1d8c6d886d +A.child.soft.1=39827c4c7749881f819a8e5c1f4d9669d7c25c18166a71d15b633c2f89daf7e8 +A.sk.2=604f88a4ee4198b3668dc38ae604dedeb45464df19e941b57d5957a5372085d1 +A.pk.basic.2=b11bd93b3fa94ee47b60c7628a52f7731005c92dadb73f9421de7fc5ca67e816106f26d121539fbf131545c8242a8d0f +A.pk.legacy.2=911bd93b3fa94ee47b60c7628a52f7731005c92dadb73f9421de7fc5ca67e816106f26d121539fbf131545c8242a8d0f +A.fp.basic.2=919d796a +A.fp.legacy.2=0ef6fc3e +A.skG2.basic.2=835092be4610e6a7e5e131f10f58a53444c0f89fbc37250bf19157e28f0a34f211cfea8022ade9a4b8b53ae090129cf503245c6bb1356ca13f772291319fc284c1a76b396fa469bd6f32d3eccdc549ba6f95e4ca08fb3777087e006cf2caa524 +A.skG2.legacy.2=03245c6bb1356ca13f772291319fc284c1a76b396fa469bd6f32d3eccdc549ba6f95e4ca08fb3777087e006cf2caa524035092be4610e6a7e5e131f10f58a53444c0f89fbc37250bf19157e28f0a34f211cfea8022ade9a4b8b53ae090129cf5 +A.pk.rt.legacy.2=911bd93b3fa94ee47b60c7628a52f7731005c92dadb73f9421de7fc5ca67e816106f26d121539fbf131545c8242a8d0f +A.pk.rt.basic.2=b11bd93b3fa94ee47b60c7628a52f7731005c92dadb73f9421de7fc5ca67e816106f26d121539fbf131545c8242a8d0f +B.lsig.legacy.2=0c5af10db2238f74776e094771cf2d4ee5e78ac8af94a618d106b7702c0b369012e327c943f23346ca461764f48351510726329193ae51b7c98e5c215f1e79d4328d9a107d7449d9a37bc504225d0dd952cc317c36b2ff4e6e270be58583148b +B.lsig.basic.2=8726329193ae51b7c98e5c215f1e79d4328d9a107d7449d9a37bc504225d0dd952cc317c36b2ff4e6e270be58583148b0c5af10db2238f74776e094771cf2d4ee5e78ac8af94a618d106b7702c0b369012e327c943f23346ca461764f4835151 +B.lverify.2=1 +B.lverify.bad.2=0 +B.lsig.rt.2=0c5af10db2238f74776e094771cf2d4ee5e78ac8af94a618d106b7702c0b369012e327c943f23346ca461764f48351510726329193ae51b7c98e5c215f1e79d4328d9a107d7449d9a37bc504225d0dd952cc317c36b2ff4e6e270be58583148b +B.bsig.basic.2=b5a4aaf5174fc68468b7bab3b182ea6e55fb55843d17b1950383f934710cdaa6a77c4494e79ec674dfc3167bfc1d944216d3e13e435a0509da3e670ebc5aeef151f32558891e00b9e8560e47601662a8e4ea893ab20cc5e909640e33bbf41fd3 +B.bsig.legacy.2=96d3e13e435a0509da3e670ebc5aeef151f32558891e00b9e8560e47601662a8e4ea893ab20cc5e909640e33bbf41fd315a4aaf5174fc68468b7bab3b182ea6e55fb55843d17b1950383f934710cdaa6a77c4494e79ec674dfc3167bfc1d9442 +B.bverify.2=1 +A.child.hard.2=140053409896043b8b7434dc29f14d132b3cbbd139677ff397a1c10f8f364616 +A.child.soft.2=525eb8eba7332727e1b0ff22bdf6320eb401d3d5e1caebdd72b0fa8aa2f0e942 +A.sk.3=21160cba355200250e9fad6bca96ed116930dc632dce23081636fedeb106c83b +A.pk.basic.3=982f6be34861d32d8d3e5aae0395ea80bff4e25b46052f41d6453754f51cd1721d44dd9f5fb62a35ca6d367e36218d4b +A.pk.legacy.3=182f6be34861d32d8d3e5aae0395ea80bff4e25b46052f41d6453754f51cd1721d44dd9f5fb62a35ca6d367e36218d4b +A.fp.basic.3=b7fea396 +A.fp.legacy.3=f71bdf44 +A.skG2.basic.3=a9a60b869403189f7abc1abf476d8afc27e4a8502f9a4949227f03393b793050a5a16c9b89d084452ff79741fc684925188c8776bc0b799fff488f0214a3b875d543b626c18a9ac0c8b6447de08c82aa735728727458305f69f77882b9d2098a +A.skG2.legacy.3=988c8776bc0b799fff488f0214a3b875d543b626c18a9ac0c8b6447de08c82aa735728727458305f69f77882b9d2098a09a60b869403189f7abc1abf476d8afc27e4a8502f9a4949227f03393b793050a5a16c9b89d084452ff79741fc684925 +A.pk.rt.legacy.3=182f6be34861d32d8d3e5aae0395ea80bff4e25b46052f41d6453754f51cd1721d44dd9f5fb62a35ca6d367e36218d4b +A.pk.rt.basic.3=982f6be34861d32d8d3e5aae0395ea80bff4e25b46052f41d6453754f51cd1721d44dd9f5fb62a35ca6d367e36218d4b +B.lsig.legacy.3=0d58f53ad17f3877f23884799c7f8dd866e7e6feaba63da933f01e447d39b7c48d941ecab58ff845cd51aa6f1d6ce57207acf6cc920e3310dcfbc3694d8483333e2e78a578be78b645aa1cd037608bb78d05f6a8de4377c5bfa52e7f6e01bdfa +B.lsig.basic.3=87acf6cc920e3310dcfbc3694d8483333e2e78a578be78b645aa1cd037608bb78d05f6a8de4377c5bfa52e7f6e01bdfa0d58f53ad17f3877f23884799c7f8dd866e7e6feaba63da933f01e447d39b7c48d941ecab58ff845cd51aa6f1d6ce572 +B.lverify.3=1 +B.lverify.bad.3=0 +B.lsig.rt.3=0d58f53ad17f3877f23884799c7f8dd866e7e6feaba63da933f01e447d39b7c48d941ecab58ff845cd51aa6f1d6ce57207acf6cc920e3310dcfbc3694d8483333e2e78a578be78b645aa1cd037608bb78d05f6a8de4377c5bfa52e7f6e01bdfa +B.bsig.basic.3=8300e9d700c1d263e5d9caec9a3302aa8984b515bd961f25b913de852168ecc0e0dcea0913a7359bee57071208895ea812bd1ae92601ba7f2e8d6d6809330ef06dde1c8ff633cff5db38a63b5aec867d43a6e3e9bafac7aec876d6625666a5cd +B.bsig.legacy.3=12bd1ae92601ba7f2e8d6d6809330ef06dde1c8ff633cff5db38a63b5aec867d43a6e3e9bafac7aec876d6625666a5cd0300e9d700c1d263e5d9caec9a3302aa8984b515bd961f25b913de852168ecc0e0dcea0913a7359bee57071208895ea8 +B.bverify.3=1 +A.child.hard.3=58a543b659628491544fc0f85d4938820dc19d5591d53f49c8b9d950d433aff7 +A.child.soft.3=0c9bd3c62871a9e36c947f7a7ab764a69b1fdb41f9625b30bd3a5bd91484f5b6 +A.sk.4=0b23c79ec3331dd7a2d4a8708b21263330b9a9d8891a81360744a2a483ea884a +A.pk.basic.4=8564f4d30abe512e9ef8c36f903436b927feebef83329f88f50d4621d6d9b59f16316f859fe5659024cce812d9f91852 +A.pk.legacy.4=0564f4d30abe512e9ef8c36f903436b927feebef83329f88f50d4621d6d9b59f16316f859fe5659024cce812d9f91852 +A.fp.basic.4=228139d6 +A.fp.legacy.4=8710d0bc +A.skG2.basic.4=833682df2e6ae024e5d9bfb5c5dc15cb855d55e945693979abfb2078aed37421438782b7d6b17345bdac09f86563327b04f35a0374e59bc64ef3ee948dc4cd4689c4f55f298c6a5ad9703e823f853d07c958b87aa151a066d31a95cfec1da928 +A.skG2.legacy.4=04f35a0374e59bc64ef3ee948dc4cd4689c4f55f298c6a5ad9703e823f853d07c958b87aa151a066d31a95cfec1da928033682df2e6ae024e5d9bfb5c5dc15cb855d55e945693979abfb2078aed37421438782b7d6b17345bdac09f86563327b +A.pk.rt.legacy.4=0564f4d30abe512e9ef8c36f903436b927feebef83329f88f50d4621d6d9b59f16316f859fe5659024cce812d9f91852 +A.pk.rt.basic.4=8564f4d30abe512e9ef8c36f903436b927feebef83329f88f50d4621d6d9b59f16316f859fe5659024cce812d9f91852 +B.lsig.legacy.4=11fbebe8bab5c35042663c60a32b7fcc3350f2a7a0cff79cb17185def6674c1233e6915545ad43e3043ba9517c283d20198fe3bbba59fc4ed6dc89b7432a7f5188caa47ec7b08631bfe2d3d2a3a745c0ad7bca351bfbdf74e49b2f46532c99f1 +B.lsig.basic.4=998fe3bbba59fc4ed6dc89b7432a7f5188caa47ec7b08631bfe2d3d2a3a745c0ad7bca351bfbdf74e49b2f46532c99f111fbebe8bab5c35042663c60a32b7fcc3350f2a7a0cff79cb17185def6674c1233e6915545ad43e3043ba9517c283d20 +B.lverify.4=1 +B.lverify.bad.4=0 +B.lsig.rt.4=11fbebe8bab5c35042663c60a32b7fcc3350f2a7a0cff79cb17185def6674c1233e6915545ad43e3043ba9517c283d20198fe3bbba59fc4ed6dc89b7432a7f5188caa47ec7b08631bfe2d3d2a3a745c0ad7bca351bfbdf74e49b2f46532c99f1 +B.bsig.basic.4=a57f7ec0d09676c12b4fb525a1d359b7c29cc0f010682905f0a44bafc8764998c85fb885f9affeb2e256cfb3f5558c61180da06bedd87410c1f842ddcf467b04aeed09b4cb8c2eb4dbf5f502cea4683e6c35cf2475208fa3dcd852e5d290faf2 +B.bsig.legacy.4=980da06bedd87410c1f842ddcf467b04aeed09b4cb8c2eb4dbf5f502cea4683e6c35cf2475208fa3dcd852e5d290faf2057f7ec0d09676c12b4fb525a1d359b7c29cc0f010682905f0a44bafc8764998c85fb885f9affeb2e256cfb3f5558c61 +B.bverify.4=1 +A.child.hard.4=1422752ec6e3f867f5f80020bec1d84e6ade884bf4093f4d337f503417e00fdd +A.child.soft.4=10b37a4b07fa1a78786efbe3f116dfd462ba0ce94e7afa742f5a87234c3a868f +A.sk.5=0535569670f3c8c0379aea8c93b3bedf5ef16672417c281da18b957f41398d13 +A.pk.basic.5=b14d33ec70e47c7d9c7895bc4bb6d9979d81118354bb84571aed49b1dd8560a9ddbf71660d6c567bf7f391c51e0e5c45 +A.pk.legacy.5=914d33ec70e47c7d9c7895bc4bb6d9979d81118354bb84571aed49b1dd8560a9ddbf71660d6c567bf7f391c51e0e5c45 +A.fp.basic.5=1c9dbfe5 +A.fp.legacy.5=708cb0c8 +A.skG2.basic.5=8af786a3d660b1305eee25239d7c8f225fa604b23f96287745b9caee6a039ff21733bbe644df10daaf79c0ddc187bf4811d3f20781f42de6cb8fae96a560ed9f42aff7d3fee427f7bb44967dbbaff01e3efdad10b83a33076246b5819d1ef755 +A.skG2.legacy.5=11d3f20781f42de6cb8fae96a560ed9f42aff7d3fee427f7bb44967dbbaff01e3efdad10b83a33076246b5819d1ef7550af786a3d660b1305eee25239d7c8f225fa604b23f96287745b9caee6a039ff21733bbe644df10daaf79c0ddc187bf48 +A.pk.rt.legacy.5=914d33ec70e47c7d9c7895bc4bb6d9979d81118354bb84571aed49b1dd8560a9ddbf71660d6c567bf7f391c51e0e5c45 +A.pk.rt.basic.5=b14d33ec70e47c7d9c7895bc4bb6d9979d81118354bb84571aed49b1dd8560a9ddbf71660d6c567bf7f391c51e0e5c45 +B.lsig.legacy.5=116b3ec371691cdf6b75db98148553ffa14ee11df0ebced3a2e7dfe9e7fb1e4da4f322d1df36d03bf3b75ed60cc6aadc07c0606f8cd2196e6d9a8c146a6c6f2d9d78898110da264e79291c5bf2d5d0567e741bca297c7b3d001cf202185411b5 +B.lsig.basic.5=87c0606f8cd2196e6d9a8c146a6c6f2d9d78898110da264e79291c5bf2d5d0567e741bca297c7b3d001cf202185411b5116b3ec371691cdf6b75db98148553ffa14ee11df0ebced3a2e7dfe9e7fb1e4da4f322d1df36d03bf3b75ed60cc6aadc +B.lverify.5=1 +B.lverify.bad.5=0 +B.lsig.rt.5=116b3ec371691cdf6b75db98148553ffa14ee11df0ebced3a2e7dfe9e7fb1e4da4f322d1df36d03bf3b75ed60cc6aadc07c0606f8cd2196e6d9a8c146a6c6f2d9d78898110da264e79291c5bf2d5d0567e741bca297c7b3d001cf202185411b5 +B.bsig.basic.5=98e09cacf9f860bc131c401c6dc20a96cba00c581a2abf576a58ae4e0edd96d82764f95e1b0a00d6e6ad52db83adb92b16349f9b0675e0b6ffe90ec64203fce107813ae36cfb3a4c98b40580b362d22b27595d57e1f02ab67534b96b186ee2fe +B.bsig.legacy.5=16349f9b0675e0b6ffe90ec64203fce107813ae36cfb3a4c98b40580b362d22b27595d57e1f02ab67534b96b186ee2fe18e09cacf9f860bc131c401c6dc20a96cba00c581a2abf576a58ae4e0edd96d82764f95e1b0a00d6e6ad52db83adb92b +B.bverify.5=1 +A.child.hard.5=186953b6ebeb46b7d6d17f4eb6b55738a8910468d8c7a12773fa4ece4d396e33 +A.child.soft.5=36aae8999b8d557746cb7310a2291c8facd190430c6f769f60193610a5e7f570 +A.sk.6=3e54ca602df6ef98b894e98a87eddca31b87fd052cfcab698477b3ad19c84dfb +A.pk.basic.6=925b01d07a6e175a0b38f66c5bb2263f13f9800f2becbff87a73548c3ec188e08505a3bc17f046f0610b84e3c487ec3f +A.pk.legacy.6=125b01d07a6e175a0b38f66c5bb2263f13f9800f2becbff87a73548c3ec188e08505a3bc17f046f0610b84e3c487ec3f +A.fp.basic.6=910eddce +A.fp.legacy.6=08462c2f +A.skG2.basic.6=ab3a64185b1e43943f8645682b86e13882653beeee52343ced9b87556c6eb39f2b87cd0fffe68276470a4c4afc21445413753b7fee41fa154a0b76495935a97243279fd70a0baff73cd8ae88c2b387ccd358cac5d7c34af4cc7e348c0fea602d +A.skG2.legacy.6=93753b7fee41fa154a0b76495935a97243279fd70a0baff73cd8ae88c2b387ccd358cac5d7c34af4cc7e348c0fea602d0b3a64185b1e43943f8645682b86e13882653beeee52343ced9b87556c6eb39f2b87cd0fffe68276470a4c4afc214454 +A.pk.rt.legacy.6=125b01d07a6e175a0b38f66c5bb2263f13f9800f2becbff87a73548c3ec188e08505a3bc17f046f0610b84e3c487ec3f +A.pk.rt.basic.6=925b01d07a6e175a0b38f66c5bb2263f13f9800f2becbff87a73548c3ec188e08505a3bc17f046f0610b84e3c487ec3f +B.lsig.legacy.6=825a6eb2146a57893682066d783509b342fc5869ae0559330e11cb10ec3a132e9cde762c6869e67c9b83d0de2646ebac09aa2a4d7a08831cab78b6b7a57f57fad48cd1dbe3c3da0d996db69ff13fc060af2626a14bf69092def390acf6320f4d +B.lsig.basic.6=a9aa2a4d7a08831cab78b6b7a57f57fad48cd1dbe3c3da0d996db69ff13fc060af2626a14bf69092def390acf6320f4d025a6eb2146a57893682066d783509b342fc5869ae0559330e11cb10ec3a132e9cde762c6869e67c9b83d0de2646ebac +B.lverify.6=1 +B.lverify.bad.6=0 +B.lsig.rt.6=825a6eb2146a57893682066d783509b342fc5869ae0559330e11cb10ec3a132e9cde762c6869e67c9b83d0de2646ebac09aa2a4d7a08831cab78b6b7a57f57fad48cd1dbe3c3da0d996db69ff13fc060af2626a14bf69092def390acf6320f4d +B.bsig.basic.6=b8801cf2113e290828ae4c2ef629d8cb3d3a34d3b8de7dcd0170f6a070f0787941ca2ed97d561c1b069b688945efb525033f27242eace77e730ce5c0a1200b05be002b47b2a7664445537f0ad10dbf24bbf0cc0f60ccd6992df41f3030f71c2a +B.bsig.legacy.6=833f27242eace77e730ce5c0a1200b05be002b47b2a7664445537f0ad10dbf24bbf0cc0f60ccd6992df41f3030f71c2a18801cf2113e290828ae4c2ef629d8cb3d3a34d3b8de7dcd0170f6a070f0787941ca2ed97d561c1b069b688945efb525 +B.bverify.6=1 +A.child.hard.6=5cec6bb344ecd98a133343f77b84fe620d46b1468a4579c83963cc0d32be15fc +A.child.soft.6=49f50d890fa3b2d475a6ce1bb2c56f9508fe8d2662659146e3434390ddc0e94d +A.sk.7=0e3c506a5cc9be55237397674e0fe32f61e4ecb6e2c761493d89c7a17a6dcc0d +A.pk.basic.7=9661920ea04d278794e28c0767591a11bb1f4678e765354e257887bf5c8e38ad3aaa258d22ac826ecb1f2b31a23a7415 +A.pk.legacy.7=1661920ea04d278794e28c0767591a11bb1f4678e765354e257887bf5c8e38ad3aaa258d22ac826ecb1f2b31a23a7415 +A.fp.basic.7=e141846a +A.fp.legacy.7=c4d6d99d +A.skG2.basic.7=86d69b68a97adf54d024ce7fef27dbc0b3f08b993daec1434b5b8f77b0f09614e0ff35c5e24b4e3b57c378e5370e2f3715847268902520804e69b0c74f7744ccefed304bbf4f06103874fba5468add684faf46d5719fdb2570e398cef37e64cb +A.skG2.legacy.7=15847268902520804e69b0c74f7744ccefed304bbf4f06103874fba5468add684faf46d5719fdb2570e398cef37e64cb06d69b68a97adf54d024ce7fef27dbc0b3f08b993daec1434b5b8f77b0f09614e0ff35c5e24b4e3b57c378e5370e2f37 +A.pk.rt.legacy.7=1661920ea04d278794e28c0767591a11bb1f4678e765354e257887bf5c8e38ad3aaa258d22ac826ecb1f2b31a23a7415 +A.pk.rt.basic.7=9661920ea04d278794e28c0767591a11bb1f4678e765354e257887bf5c8e38ad3aaa258d22ac826ecb1f2b31a23a7415 +B.lsig.legacy.7=946ba1386b9b458466890d857082710507ec67a1e055caa977799a92278fda373155e0b9fefb4fb40ede46112c1ccdf70035ec9fabb85bc7e8493fbc4f892d0cd9ef73ef86656a000bc95eaf980ec76a0db375c4165016bf7fc72a96dcd6ac0f +B.lsig.basic.7=a035ec9fabb85bc7e8493fbc4f892d0cd9ef73ef86656a000bc95eaf980ec76a0db375c4165016bf7fc72a96dcd6ac0f146ba1386b9b458466890d857082710507ec67a1e055caa977799a92278fda373155e0b9fefb4fb40ede46112c1ccdf7 +B.lverify.7=1 +B.lverify.bad.7=0 +B.lsig.rt.7=946ba1386b9b458466890d857082710507ec67a1e055caa977799a92278fda373155e0b9fefb4fb40ede46112c1ccdf70035ec9fabb85bc7e8493fbc4f892d0cd9ef73ef86656a000bc95eaf980ec76a0db375c4165016bf7fc72a96dcd6ac0f +B.bsig.basic.7=ae7378473f2e89255e78676f4ee798ea8e169551dfcc8b78cd564dbdf5d1495c0145e95c7e5d0df191c955a40ba033b805363357f176bd8b84063ae47bf7e3a273a2644ba437a9c496a66761a0693305b3249f588dd1e45feef9d33e1030c076 +B.bsig.legacy.7=85363357f176bd8b84063ae47bf7e3a273a2644ba437a9c496a66761a0693305b3249f588dd1e45feef9d33e1030c0760e7378473f2e89255e78676f4ee798ea8e169551dfcc8b78cd564dbdf5d1495c0145e95c7e5d0df191c955a40ba033b8 +B.bverify.7=1 +A.child.hard.7=6be06280ee13d42a1d9f12b5d3e9b429641ede55b3bad11a27948123e89d8913 +A.child.soft.7=1605a13324f75c0755fe03bfb1a9e9478586c12a54332de98ec4658dc233ce14 +C.aggsec.legacy.1=17b20ce50a20f09a4d807d4c0db622d13be8902380e908a9304d21d03520cb9712e8fb478bd4eb35477298c05ad5069610688edde3431521fa64f24c6e6fad0b38fd77ae2edd71871948273c6a17efad03b2f908fa9717935fc7ae68ca7421ec +C.versec.legacy.1=1 +C.aggsec.basic.1=98103b71225c000a8e08507ac38248bc97ff96c4ef0a0ecb610ba97798df58f741421304b46dbe709d891640bdc797d316e5b1fe117273391a37e981838677ce2185afe88e4f29a51ceb6d7c9a7f22062e8d4029345f2f37a473b2a8055ed848 +C.versec.basic.1=1 +C.versec.legacy.bad.1=0 +C.agg.G2.1=a941eab017de217c825e0724f3ec1bfbfd90ce7628f5d3bbf0806e0efdfa806fa746c178da66fb2a8d9a587ef0bab4c91774469f443f513972a0c59ae55278c32e1caf9c66d52e708e53ef2828c48f5c4b830d256c2ff1b155730588dfc9adeb +C.agg.G1.1=9503c392ceae7db1e2f247fb6148b4211708a74491989916daeec3c34bdd2803a98fc3a43976daaab00903211b1d1c46 +C.agg.sk.1=51542fee7895e4987de3b93ff52af9bb129dc076f0dcb8afe5d93460f2a6c1b7 +C.aggsec.legacy.2=0ca923fd169db16838c09804d7150f2bdde930d17040bc39c553baf9336527b15cbe83aa841b9f902a203521e7bc60220a9c9e1ddf0677564be73f7b8f9ce2a52c28c910eac2baba3ef3310fad7eaa8baf9465bfc9104f0ac08cd9da8b41b70e +C.versec.legacy.2=1 +C.aggsec.basic.2=a165590855562a1437e0d5fce7dfb1373a07fe09bdb33cf5f82b2e8d3b809ce7a8e9ae47eb0602181d474866958d51641816952a467643164dab9aa92567dac5449943f8464d0760740fcbb54bd758cc80e232032f56f3df269460d2cd7b807c +C.versec.basic.2=1 +C.versec.legacy.bad.2=0 +C.agg.G2.2=ab45f84e0c325239430f0584bf220bbabcff667d308d39c1fcd827f8c7f105e8210c20ca619ad9084984914e35fc0d1f082b5675dcfd07041f6ee1564de37b678a4b68ee51db8977bdc79f4ba1c9d49cccef35b1de0b7e8494c9cc5fa233edd0 +C.agg.G1.2=a5425f1689e33cd676a112efdd5aa80df7b137fad1db3c690bb2213745dd9a25c51d35fce39de1eaf5e268ccfdcb9163 +C.agg.sk.2=4e1643205fe0ed6f883f3d803c4742a2db0b7826aa523e5bc62a18c766d698df +C.aggsec.legacy.3=87b142eb28bb97ed9839900dbcefe90a992b4cd63468dd13d3dc8bcef394f0e77715f8da3fd62d3847ab845b2035a880193d116414b1a51a43edce8b2ccc4ee08f4492d35e19f9c35fe76cf73598afc085e62af9a6e52927c8f4d8544f9887f4 +C.versec.legacy.3=1 +C.aggsec.basic.3=8959bdf6c216c1c50eee30aa5ccd21196c058e3e28069cc70d86f4dc1608bbf9b791db866fb23ee816acd9b8ed3d3964174a16f05c9afc9cdc51790e8bf7a4ea0b4aef4645119a041ff97fa8500d6167c0db4743aba27f454853451f7229a287 +C.versec.basic.3=1 +C.versec.legacy.bad.3=0 +C.agg.G2.3=85b735e626a9322824cdb16d704db491330aa37239153a833c212f5404a1028f97d8339d437d7cdf06749330639c6ea21437d0bc3b3e6e1d411ed606e1943576c462abf6d572c9eccabdaec263073748421f84497f775a93631ccb51364f528f +C.agg.G1.3=b45111e7f20ff82bbfce790f2abeefebb885844423ed1fd37b43904b7b47454ff3c30ac47d4969c615af7316b1f41ffb +C.agg.sk.3=1d3b4ed79d0c0001f1bb2ded98523121bedbeaa37ac4fceb0f0bfdf4d8963849 +C.aggsec.legacy.10=0eab90239c026690d3ba0ac74c69f28420931128800ff1cfa7c64668600b99e7f60853e0f2d22b4d6cf07d97428cd0411256b05ad14e7ecae1372673d5c00db1880874016ea8a2ed6eb34655297e7883e6e023f28a6aa206e0fd0294bff532fa +C.versec.legacy.10=1 +C.aggsec.basic.10=a0368e7182619f7569d087c364199db4c5c20ba3e090706a3767ceb5dc054afe66fb4835b487eb17f67f36972b5e2d660c207b224abf7b30bb7db3bd16ebe0d1a87fac41370d82656af3e907293e954a884411765caf76708008ed2dd9b25622 +C.versec.basic.10=1 +C.versec.legacy.bad.10=0 +C.agg.G2.10=82974b5dafcc908dd00b725f120e9fa3ba1ec265019145a898b6ab3ddebb6f0b1a8c02827e04ee33dca6f098799ba76710b0cb5bf3b125ccd295abf5f3eca6fa272be6d727a591b32208b33618212368a15035b7e97edd2e29112e91bf61b651 +C.agg.G1.10=86689658c56d1d945a480cc1a11cb77ec19bce8fd3f8f6f5dbb1db20330aac73e78268a66e512b5ddd98fffc20bc7bbc +C.agg.sk.10=4972fe548df20e3ede53ebe27f0ab0c1bfe742903357d88d48301c6b7c9a77b6 +D.lagg=8acadc114967f7a21953644c19dc9ecbfdbdb0233d484862e2816ef3e6cc94177c85d26a3d8bc10a79ba7fced80226530f01ee9e0f441c83c8b50bf5e03be1f1dbfcc7d660d6d968c738693574f144dc1c5001a221bdf16d7127cb828e58003b +D.laggverify=1 +D.laggverify.bad=0 +E.mastersig=99a667d463e60f2e2b3feecb2a04061692faa66c543bd4eb36c5077794b2bfe24200aa1709fa72408a40a8dfe8a00d8c0d6d35dbce43924eba4354c109b6370a722f67bed82b4d1d984572d7817797477cd34aa415d20c996d573d5ed6043574 +E.masterverify=1 +E.skshare.0=2fe9aa3dc24ee2b902c2632305e5e9f9b667cb721239b1eeaec32775235696ce +E.pkshare.0=93ac3b88ca6f2a31eb5929c590692f415b3e9cb4dabb70bf9493a6858e1fe86d89ed2363f2098d0888e3fc601947fda0 +E.sharematch.0=1 +E.sigshare.poly.0=8c2810b9171817b12be33be0d8caa159785f05c30695aacba1cfac14bd4b6c4a6879ebc91a471c1605f608e2e223ce62044251375a33a8c918177fc950496fbfd4832d22f8ba8c4b391b74113703e82828d60eb468be93e150eee50bf0a0927e +E.sigshare.sign.0=8c2810b9171817b12be33be0d8caa159785f05c30695aacba1cfac14bd4b6c4a6879ebc91a471c1605f608e2e223ce62044251375a33a8c918177fc950496fbfd4832d22f8ba8c4b391b74113703e82828d60eb468be93e150eee50bf0a0927e +E.skshare.1=6d7a99964fe9909c9a713f88392b32af635db3daec83b4538c6fc3228ecdf513 +E.pkshare.1=8e333381aedd9b63aaf2e019e197e6983ca3749b8561e21485bc6b7a4bef92d0ecd50481bf95832d87d3b2bd37d3a141 +E.sharematch.1=1 +E.sigshare.poly.1=860e104d01a3d7c3af84995bdd1574c4292ea7e5373d22ccd590ac33acaa91d2f8d119fb2f4980ca4fee9ec66179f9f10f053bd123ec34abdd0e181d76bbb795459f65c1b1404904aa6d76593561b67b2c3f29d0e965533161a43e1683e4d1ea +E.sigshare.sign.1=860e104d01a3d7c3af84995bdd1574c4292ea7e5373d22ccd590ac33acaa91d2f8d119fb2f4980ca4fee9ec66179f9f10f053bd123ec34abdd0e181d76bbb795459f65c1b1404904aa6d76593561b67b2c3f29d0e965533161a43e1683e4d1ea +E.skshare.2=4a691d73ddb6e5236c82bab66d69ba08c340e25aad705836792c66a8b8b2391f +E.pkshare.2=83ad1776d2dfec1bde34672dd518bd59c3861e92f374fd34e11bfc454a29d7c92536bd0e4c48288ab704211f5053c1c5 +E.sharematch.2=1 +E.sigshare.poly.2=12e5310660dfc34e159a5910db2b2b517936acde9eadd3c954c572c3f7814a07a0350ca68f56cc4277fd9784d78182bd04588688bd1c842992e941f30939f2bc4325237ebf4b30a490473878636f72e7cca9036895141d01ccef721da90fa3ff +E.sigshare.sign.2=12e5310660dfc34e159a5910db2b2b517936acde9eadd3c954c572c3f7814a07a0350ca68f56cc4277fd9784d78182bd04588688bd1c842992e941f30939f2bc4325237ebf4b30a490473878636f72e7cca9036895141d01ccef721da90fa3ff +E.skshare.3=296fdf7a3c8e8d9a1d80009e1e54c95ce84bc381e63236e500729d4a6a5f0d0f +E.pkshare.3=893bbd2c6b4d595cdac30778e438a1b95d16eb1909b8bcc28148848507d07e98793d4c0368d328d45a5355df1f2253da +E.sharematch.3=1 +E.sigshare.poly.3=039b5d75dfad13ce4392deaa7d207a12e0a658dd5f34f66098453e60b07b38fbc7b3271d14697e6bfd56d6053a697237069259997fd43f322cb917f7fed360cbacbe2a8582358c954c5381cdc442f8323394cab23d4ce0c2745ca6e45aa99c8b +E.sigshare.sign.3=039b5d75dfad13ce4392deaa7d207a12e0a658dd5f34f66098453e60b07b38fbc7b3271d14697e6bfd56d6053a697237069259997fd43f322cb917f7fed360cbacbe2a8582358c954c5381cdc442f8323394cab23d4ce0c2745ca6e45aa99c8b +E.skshare.4=57230fd28ec31c1a4c4a5e378c6fa748d6e68772fe83d35477bb6539876fab15 +E.pkshare.4=91edd2ed20fa5ef43bf796785e0ca8ab1d6cdb4ae63aba67ffccc0f6911c1214f81a62e23175f46b767681cf92cb25f1 +E.sharematch.4=1 +E.sigshare.poly.4=97c77544f1db5118e955e892c45d1895724b77e99efd420615f54f4d4d5b7b57f668926fa45be02190d269a2354cfaf30d55b722c035e19354e593015ccf0bd71d2c7e4c35e4cfb951bd6ff5f88008014f877a44f5f9d95d01fd1b1e570a3b15 +E.sigshare.sign.4=97c77544f1db5118e955e892c45d1895724b77e99efd420615f54f4d4d5b7b57f668926fa45be02190d269a2354cfaf30d55b722c035e19354e593015ccf0bd71d2c7e4c35e4cfb951bd6ff5f88008014f877a44f5f9d95d01fd1b1e570a3b15 +E.skrecover=6c04e5af86f2ddeaf6d1d4f8bbd4a1217b29abd4517d4619dada7ec087ed6f6f +E.skrecover.match=1 +E.pkrecover=8d713f7f50fe5d3e2c0335c3d3c0ceb2a1689eb3c2a4436c3a11898b8b797818aae1316825542790d1b0b2cafffb9150 +E.sigrecover=99a667d463e60f2e2b3feecb2a04061692faa66c543bd4eb36c5077794b2bfe24200aa1709fa72408a40a8dfe8a00d8c0d6d35dbce43924eba4354c109b6370a722f67bed82b4d1d984572d7817797477cd34aa415d20c996d573d5ed6043574 +E.sigrecover.verify=1 +E.sigrecover.same=1 +F.esk=000000010000000000000000004c3b08d7413ef3f4d39922793c4b20c0bcfb26db531c9e32a505cf763c2794953757b1115e7110046606404b38e4654adc4c2a52a5337deca0794080d3f92921 +F.esk.pk.legacy=89efc5280e56a745dcfd4571d1e9b06edf0441c5fd8640f5efdf5554bcdcb07e7d1d35e09bf9ebaabe6faad282c838d4 +F.esk.pk.basic=a9efc5280e56a745dcfd4571d1e9b06edf0441c5fd8640f5efdf5554bcdcb07e7d1d35e09bf9ebaabe6faad282c838d4 +F.esk.chaincode=4c3b08d7413ef3f4d39922793c4b20c0bcfb26db531c9e32a505cf763c279495 +F.child.legacy=00000001023e497ad38000002aff185013e7118856e4bcb6e2dc9608cab5219747c8037a889789b1be76feb6df1250aa4f4cb5f7e58f7b5f942eb2f2b99b36eacb3e6e65c4766ce956e628e62a +F.child.legacy.sk=1250aa4f4cb5f7e58f7b5f942eb2f2b99b36eacb3e6e65c4766ce956e628e62a +F.child.basic=000000010203f3628b8000002a447c89f7c80822b8661513be9c7fdf172a91faf71300f68fa39cfdea0ae3740f625c4936e02f4abcee9cfbd59e403428b9937f94bd0908cf676c3f63bc7713e0 +F.child.basic.sk=625c4936e02f4abcee9cfbd59e403428b9937f94bd0908cf676c3f63bc7713e0 +F.epk.legacy=000000010000000000000000004c3b08d7413ef3f4d39922793c4b20c0bcfb26db531c9e32a505cf763c27949589efc5280e56a745dcfd4571d1e9b06edf0441c5fd8640f5efdf5554bcdcb07e7d1d35e09bf9ebaabe6faad282c838d4 +F.epk.basic=000000010000000000000000004c3b08d7413ef3f4d39922793c4b20c0bcfb26db531c9e32a505cf763c279495a9efc5280e56a745dcfd4571d1e9b06edf0441c5fd8640f5efdf5554bcdcb07e7d1d35e09bf9ebaabe6faad282c838d4 +F.epk.child.legacy=00000001010b9a9e8000000001d84919fa70508fefd47576f19b437b3bb2049039740d83de455742dae48c96ab8a9f848f28b295903845d5f860c9031899e4f1a6d092edacdaec28f64a7fd9b94679b3faaf0ecf6b09f70b1d3ed5555f +F.epk.child.basic=00000001010b9a9e80000000012428f63e5f4b2e25871336f34ecebbd6e0e648d8b4a02ec033b575a391dc6b598cf85b6e8d78a797985402debeb2a1b823ab7c98ae20ae1609aaadd70309a4d40ef5cad6a6f93cb9af0ec2045dba96cf +F.pubpriv.match.legacy=1 +F.esk.rt=000000010000000000000000004c3b08d7413ef3f4d39922793c4b20c0bcfb26db531c9e32a505cf763c2794953757b1115e7110046606404b38e4654adc4c2a52a5337deca0794080d3f92921 +F.epk.rt.legacy=000000010000000000000000004c3b08d7413ef3f4d39922793c4b20c0bcfb26db531c9e32a505cf763c27949589efc5280e56a745dcfd4571d1e9b06edf0441c5fd8640f5efdf5554bcdcb07e7d1d35e09bf9ebaabe6faad282c838d4 +G.inrange.mod0=57c1d1f8ef9ad067fef7d0056bdfec87f51c28b65dd56fa3cbcc0f1afc984725 +G.inrange.mod1=57c1d1f8ef9ad067fef7d0056bdfec87f51c28b65dd56fa3cbcc0f1afc984725 +G.big.mod1=1824b159acc5056f998c4fefecbc4ff55884b7fa0003480200000001fffffffd +G.big.mod0=EXC +G.order.mod1=0000000000000000000000000000000000000000000000000000000000000000 +G.order.mod0=73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 +G.orderm1.mod0=73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000 +G.zero.sk=0000000000000000000000000000000000000000000000000000000000000000 +G.zero.pk=c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +G.bip32seed=193afdb206c666de5cfba5d5a235477d269b1634ec36cfa1a3167cb47727bf25 +G.dh=a11d215631668626a3396afbfd38d850a2c18ffa90bd589714e40112b2592064c581eb8205fdc7bcd860e23b15e487cf +G.dh.sym=1 +H.g1.inf.basic.ser=c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g1.inf.basic.valid=1 +H.g1.inf.legacy.ser=c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g1.inf.legacy.valid=1 +H.g2.inf.basic.ser=c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.inf.basic.valid=1 +H.g2.inf.legacy=EXC +H.g1.badinf.basic=EXC +H.g1.badinf.legacy=EXC +H.g2.badinf.basic=EXC +H.g2.badinf.legacy=EXC +H.g1.zeros.basic=EXC +H.g1.zeros.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g1.zeros.legacy.valid=0 +H.g2.zeros.basic=EXC +H.g2.zeros.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.zeros.legacy.valid=0 +H.g1.zeros.legacy.unchk.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g1.zeros.legacy.unchk.valid=0 +H.g2.zeros.legacy.unchk.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.zeros.legacy.unchk.valid=0 +H.g1.ff.basic=EXC +H.g1.ff.legacy=EXC +H.g2.ff.basic=EXC +H.g2.ff.legacy=EXC +H.g1.fflow.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g1.fflow.legacy.valid=0 +H.g1.legacyAsBasic=EXC +H.g1.basicAsLegacy.ser=98138bb3b9cb34f03c9deac8e0928385873a8fe418a5f371f10cba0b6988a7854d0b48c1ffc50314bddea964b90b6be3 +H.g1.basicAsLegacy.valid=1 +H.g2.legacyAsBasic=EXC +H.g2.basicAsLegacy.ser=801627cb11cf0498af70b04e84ec07a615c01219b0693be59fb93e403f7937ddf26efe486c4b8edffdea8f136203b99e15240cfb56882628ef6d4b2cad852cbe23b882b2aab625f0e82f355ce1a4fe129b589d97ca3e17c5a36e514f93cfff32 +H.g2.basicAsLegacy.valid=0 +H.g1.negated.legacy.ser=98138bb3b9cb34f03c9deac8e0928385873a8fe418a5f371f10cba0b6988a7854d0b48c1ffc50314bddea964b90b6be3 +H.g1.negated.legacy.valid=1 +H.g1.negated.basic.ser=b8138bb3b9cb34f03c9deac8e0928385873a8fe418a5f371f10cba0b6988a7854d0b48c1ffc50314bddea964b90b6be3 +H.g1.negated.basic.valid=1 +H.g1.nonsub.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 +H.g1.nonsub.legacy.valid=0 +H.g1.nonsub.legacy.unchk.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 +H.g1.nonsub.legacy.unchk.valid=0 +H.g1.nonsub.basic=EXC +H.g1.nonsub.basic.unchk.ser=800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 +H.g1.nonsub.basic.unchk.valid=0 +H.g2.nonsub.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.nonsub.legacy.valid=0 +H.g2.nonsub.legacy.unchk.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.nonsub.legacy.unchk.valid=0 +H.g2.nonsub.basic=EXC +H.g2.nonsub.basic.unchk=EXC +H.g1.nocurve.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +H.g1.nocurve.legacy.valid=0 +H.g1.nocurve.basic=EXC +H.g2.flag48.basic=EXC +H.len47=EXC +H.g1.nocurve.sign.legacy.ser=800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +H.g1.nocurve.sign.legacy.valid=0 +H.g1.overp.sign.legacy.ser=800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g1.overp.sign.legacy.valid=0 +H.g2.x2.sign.legacy.ser=800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.x2.sign.legacy.valid=0 +H.g2.x3.sign.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.x3.sign.legacy.valid=0 +H.g2.x2.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.x2.legacy.valid=0 +H.g2.overp.sign.legacy.ser=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +H.g2.overp.sign.legacy.valid=0 +I.basic.verify.infinf=0 +I.legacy.verify.infinf=0 +I.basic.verify.infpk=0 +I.basic.verify.infsig=0 +I.aggver.empty.infsig=1 +I.aggver.empty.realsig=0 +I.aggver.mismatch=0 +I.versec.withinf=0 +# end diff --git a/tools/fuzzgen.cpp b/tools/fuzzgen.cpp new file mode 100644 index 000000000000..28a6bbebde60 --- /dev/null +++ b/tools/fuzzgen.cpp @@ -0,0 +1,165 @@ +// Differential fuzz driver for the relic -> blst migration. +// +// Uses only the public dashbls API; compile the same source against the old +// and new libraries, run with the same arguments, and diff the output. +// +// fuzzgen +// +// Covers: random byte-string decoding in every mode (the dominant +// consensus-facing attack surface), decode/re-encode round trips, and +// legacy + basic sign/verify/aggregate cycles on derived keys. + +#include +#include +#include +#include +#include +#include + +#include + +using namespace bls; +using std::vector; + +// xorshift128+ so both builds see identical byte streams with no libc +// dependency +static uint64_t s0, s1; +static uint64_t rng() +{ + uint64_t x = s0; + const uint64_t y = s1; + s0 = y; + x ^= x << 23; + s1 = x ^ y ^ (x >> 17) ^ (y >> 26); + return s1 + y; +} + +static void fill(vector& v) +{ + for (size_t i = 0; i < v.size(); i += 8) { + const uint64_t r = rng(); + for (size_t j = 0; j < 8 && i + j < v.size(); j++) + v[i + j] = (uint8_t)(r >> (8 * j)); + } +} + +static void dump(const vector& v) +{ + for (auto b : v) printf("%02x", b); +} + +static void probeG1(const vector& in, bool fLegacy) +{ + try { + G1Element e = G1Element::FromBytes(Bytes(in), fLegacy); + dump(e.Serialize(fLegacy)); + printf(" v%d", (int)e.IsValid()); + } catch (const std::exception&) { + printf("EXC"); + } + printf(";"); +} + +static void probeG2(const vector& in, bool fLegacy) +{ + try { + G2Element e = G2Element::FromBytes(Bytes(in), fLegacy); + dump(e.Serialize(fLegacy)); + printf(" v%d", (int)e.IsValid()); + } catch (const std::exception&) { + printf("EXC"); + } + printf(";"); +} + +int main(int argc, char** argv) +{ + if (argc != 3) { + fprintf(stderr, "usage: fuzzgen \n"); + return 2; + } + s0 = strtoull(argv[1], nullptr, 0) * 0x9E3779B97F4A7C15ULL + 1; + s1 = s0 ^ 0xD1B54A32D192ED03ULL; + char* end = nullptr; + errno = 0; + const long iters = strtol(argv[2], &end, 0); + if (errno != 0 || end == argv[2] || *end != '\0' || iters <= 0) { + fprintf(stderr, "fuzzgen: the iteration count must be a positive number\n"); + return 2; + } + + LegacySchemeMPL legacy; + BasicSchemeMPL basic; + + for (long i = 0; i < iters; i++) { + printf("i%ld: ", i); + + // 1. random decodes: fully random, and "plausible" (top bits biased + // into the interesting flag space) + vector b48(48), b96(96); + fill(b48); + fill(b96); + switch (i % 4) { + case 0: break; + case 1: b48[0] &= 0x1f; b96[0] &= 0x1f; break; // no flags + case 2: b48[0] |= 0x80; b96[0] |= 0x80; break; // sign/compress + case 3: b48[0] = (uint8_t)(rng() & 0xe0); b96[0] = b48[0]; break; + } + probeG1(b48, false); + probeG1(b48, true); + probeG2(b96, false); + probeG2(b96, true); + + // 2. valid-point cross-mode round trips + vector seed(32); + fill(seed); + PrivateKey sk = basic.KeyGen(seed); + G1Element pk = sk.GetG1Element(); + probeG1(pk.Serialize(true), true); + probeG1(pk.Serialize(false), true); // modern bytes into legacy codec + + // 3. legacy + basic signing over a random 32-byte hash + vector h(32); + fill(h); + G2Element lsig = legacy.Sign(sk, Bytes(h)); + dump(lsig.Serialize(true)); + printf(" %d", (int)legacy.Verify(pk, Bytes(h), lsig)); + printf(";"); + G2Element bsig = basic.Sign(sk, Bytes(h)); + dump(bsig.Serialize(false)); + printf(" %d", (int)basic.Verify(pk, Bytes(h), bsig)); + printf(";"); + + // 4. secure aggregation with 3 keys + vector sks; + vector pks; + vector lsigs; + for (int k = 0; k < 3; k++) { + vector s2(32); + fill(s2); + sks.push_back(basic.KeyGen(s2)); + pks.push_back(sks.back().GetG1Element()); + lsigs.push_back(legacy.Sign(sks.back(), Bytes(h))); + } + G2Element agg = legacy.AggregateSecure(pks, lsigs, Bytes(h)); + dump(agg.Serialize(true)); + printf(" %d", (int)legacy.VerifySecure(pks, agg, Bytes(h))); + printf(";"); + + // 5. threshold 2-of-3 recovery + vector ids; + vector> idStore(3, vector(32)); + for (auto& id : idStore) fill(id); + PrivateKey sh0 = Threshold::PrivateKeyShare({sks[0], sks[1]}, Bytes(idStore[0])); + PrivateKey sh1 = Threshold::PrivateKeyShare({sks[0], sks[1]}, Bytes(idStore[1])); + try { + PrivateKey rec = Threshold::PrivateKeyRecover( + {sh0, sh1}, {Bytes(idStore[0]), Bytes(idStore[1])}); + dump(rec.Serialize()); + } catch (const std::exception&) { + printf("EXC"); + } + printf("\n"); + } + return 0; +} diff --git a/tools/vectorgen.cpp b/tools/vectorgen.cpp new file mode 100644 index 000000000000..ff38ae4a5211 --- /dev/null +++ b/tools/vectorgen.cpp @@ -0,0 +1,22 @@ +// Regenerates test-vectors/reference.txt. +// +// Build against the library whose behavior is to become the reference (the +// checked-in file was produced by the relic-based implementation) and +// redirect the output: +// +// ./build/src/vectorgen > test-vectors/reference.txt +// +// runtest compares the current library against the file; this tool only +// generates data. + +#include + +#include "test-vectors.hpp" + +int main() +{ + for (const std::string& line : bls_test_vectors::GenerateReferenceVectors()) { + printf("%s\n", line.c_str()); + } + return 0; +} From 1d8b87d48eb63a519eb86e4d4e3f0c414811b92f Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Mon, 14 Sep 2026 00:49:38 +0700 Subject: [PATCH 4/4] build: compile dashbls with Dash's autotools, blst from depends src/dashbls is no longer a configure sub-project. Its library, the vendored mimalloc secure allocator and its Catch2 test binary are built by the new src/Makefile.dashbls.include as libtool convenience libraries, the same way crc32c and leveldb are, and dashbls/runtest (including the relic reference vectors) is part of `make check`. The BLS12-381 backend blst is detected by configure and linked from depends (or the system). The library's PrivateKey::Serialize no longer takes a scheme flag, so CBLSWrapper dispatches on the implementation type; the secure allocator pool is sized for the largest blst object; the relic macro workarounds in bls/bls.h are gone. The msan job drops --with-backend=easy, an option of the removed dashbls sub-configure. --disable-mimalloc was not an option of either configure, so MSan has been running with mimalloc; it is now a Dash configure option that builds dashbls without mimalloc, leaving malloc as the secure allocator until BLSInit() installs the locked pool. For MSan, depends builds blst with -D__BLST_NO_ASM__ so it uses its C implementation. --- .gitignore | 1 + ci/test/00_setup_env_native_msan.sh | 10 ++- configure.ac | 18 +++- contrib/guix/libexec/build.sh | 2 +- depends/packages/blst.mk | 5 ++ depends/patches/blst/no_asm_limbs.patch | 7 ++ src/Makefile.am | 21 ++--- src/Makefile.dashbls.include | 115 ++++++++++++++++++++++++ src/bls/bls.cpp | 2 +- src/bls/bls.h | 18 ++-- test/sanitizer_suppressions/ubsan | 4 + 11 files changed, 173 insertions(+), 30 deletions(-) create mode 100644 depends/patches/blst/no_asm_limbs.patch create mode 100644 src/Makefile.dashbls.include diff --git a/.gitignore b/.gitignore index eab9f3f83ec1..92498def678c 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ src/dash-chainstate src/dash-wallet src/test/fuzz/fuzz src/test/test_dash +src/dashbls/runtest src/qt/test/test_dash-qt src/qt/res/css/colors/* src/bench/bench_dash diff --git a/ci/test/00_setup_env_native_msan.sh b/ci/test/00_setup_env_native_msan.sh index af0008bf0d0c..c47f66ba4d96 100755 --- a/ci/test/00_setup_env_native_msan.sh +++ b/ci/test/00_setup_env_native_msan.sh @@ -17,7 +17,9 @@ LIBCXX_FLAGS="-nostdinc++ -nostdlib++ -isystem ${LIBCXX_DIR}include/c++/v1 -L${L export MSAN_AND_LIBCXX_FLAGS="${MSAN_FLAGS} ${LIBCXX_FLAGS}" # BDB generates false-positives and will be removed in future -export DEP_OPTS="DEBUG=1 NO_BDB=1 NO_QT=1 NO_UPNP=1 NO_NATPMP=1 CC=clang-19 CXX=clang++-19 CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}'" +# __BLST_NO_ASM__ makes blst use its C implementation instead of hand-written +# assembly, which MSan cannot see through. +export DEP_OPTS="DEBUG=1 NO_BDB=1 NO_QT=1 NO_UPNP=1 NO_NATPMP=1 CC=clang-19 CXX=clang++-19 CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}' CPPFLAGS='-D__BLST_NO_ASM__'" export GOAL="install" # CC/CXX/CFLAGS/CXXFLAGS are repeated here rather than left to depends' # config.site. Upstream dropped them in bitcoin#29800 because its @@ -26,12 +28,12 @@ export GOAL="install" # target whose compiler differs from the system default, so nothing else in # Dash's CI exercises that hand-off. # _FORTIFY_SOURCE is not compatible with MSAN. -# --with-asm=no and --with-backend=easy keep secp256k1 and relic off -# hand-written assembly, which MSan cannot see through. +# --with-asm=no keeps secp256k1 off hand-written assembly, which MSan cannot +# see through. # --disable-mimalloc selects the plain malloc secure allocator; mimalloc seeds # itself with a raw getrandom syscall before main(), which MSan cannot track. export BITCOIN_CONFIG="--with-sanitizers=memory --with-gui=no --without-bdb --with-sqlite \ ---with-asm=no --with-backend=easy --disable-mimalloc \ +--with-asm=no --disable-mimalloc \ CC=clang-19 CXX=clang++-19 CFLAGS='${MSAN_FLAGS}' CXXFLAGS='${MSAN_AND_LIBCXX_FLAGS}' \ CPPFLAGS='-U_FORTIFY_SOURCE'" export USE_MEMORY_SANITIZER="true" diff --git a/configure.ac b/configure.ac index a9e35495bca7..ef26c5c2a11d 100644 --- a/configure.ac +++ b/configure.ac @@ -167,6 +167,12 @@ AC_ARG_WITH([natpmp], [use_natpmp=$withval], [use_natpmp=auto]) +AC_ARG_ENABLE([mimalloc], + [AS_HELP_STRING([--disable-mimalloc], + [use malloc instead of mimalloc for BLS secret memory until BLSInit() installs the locked pool (default is mimalloc)])], + [use_mimalloc=$enableval], + [use_mimalloc=yes]) + AC_ARG_ENABLE(tests, AS_HELP_STRING([--disable-tests],[do not compile tests (default is to compile)]), [use_tests=$enableval], @@ -1572,6 +1578,13 @@ if test "$use_natpmp" != "no"; then CPPFLAGS="$TEMP_CPPFLAGS" fi +dnl Check for blst (required by src/dashbls) +TEMP_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS $BLST_CPPFLAGS" +AC_CHECK_HEADERS([blst.h], [], [AC_MSG_ERROR([blst headers missing])]) +AC_CHECK_LIB([blst], [blst_p1_compress], [BLST_LIBS="$BLST_LIBS -lblst"], [AC_MSG_ERROR([libblst missing])], [$BLST_LIBS]) +CPPFLAGS="$TEMP_CPPFLAGS" + if test "$build_bitcoin_wallet$build_bitcoin_cli$build_bitcoin_tx$build_bitcoin_util$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench$enable_fuzz_binary" = "nonononononononono"; then use_boost=no else @@ -1954,6 +1967,7 @@ AM_CONDITIONAL([ENABLE_ARM_CRC], [test "$enable_arm_crc" = "yes"]) AM_CONDITIONAL([ENABLE_ARM_NEON], [test "$enable_arm_neon" = "yes"]) AM_CONDITIONAL([ENABLE_ARM_SHANI], [test "$enable_arm_shani" = "yes"]) AM_CONDITIONAL([WORDS_BIGENDIAN], [test "$ac_cv_c_bigendian" = "yes"]) +AM_CONDITIONAL([USE_MIMALLOC], [test "$use_mimalloc" = "yes"]) AM_CONDITIONAL([USE_NATPMP], [test "$use_natpmp" = "yes"]) AM_CONDITIONAL([USE_UPNP], [test "$use_upnp" = "yes"]) @@ -2030,6 +2044,8 @@ AC_SUBST(BACKTRACE_FLAGS) AC_SUBST(BACKTRACE_LDFLAGS) AC_SUBST(BACKTRACE_LIBS) AC_SUBST(GMP_LIBS) +AC_SUBST(BLST_CPPFLAGS) +AC_SUBST(BLST_LIBS) AC_SUBST(NATPMP_CPPFLAGS) AC_SUBST(NATPMP_LIBS) AC_SUBST(DSYMUTIL_FLAT) @@ -2066,7 +2082,7 @@ CPPFLAGS="$CPPFLAGS_TEMP" dnl The ECDH module is required by the wallet's Platform key provider dnl (DashPay contact request encryption, wallet/platformkeys.cpp). ac_configure_args="${ac_configure_args} --disable-shared --with-pic --enable-benchmark=no --enable-module-recovery --enable-module-ecdh --disable-openssl-tests" -AC_CONFIG_SUBDIRS([src/dashbls src/secp256k1]) +AC_CONFIG_SUBDIRS([src/secp256k1]) AC_OUTPUT diff --git a/contrib/guix/libexec/build.sh b/contrib/guix/libexec/build.sh index a28778895730..94df97112159 100755 --- a/contrib/guix/libexec/build.sh +++ b/contrib/guix/libexec/build.sh @@ -270,7 +270,7 @@ mkdir -p "$DISTSRC" ${HOST_CXXFLAGS:+CXXFLAGS="${HOST_CXXFLAGS}"} \ ${HOST_LDFLAGS:+LDFLAGS="${HOST_LDFLAGS}"} - sed -i.old 's/-lstdc++ //g' {./,src/dashbls/,src/secp256k1/}{config.status,libtool} + sed -i.old 's/-lstdc++ //g' {./,src/secp256k1/}{config.status,libtool} # Build Dash Core diff --git a/depends/packages/blst.mk b/depends/packages/blst.mk index 3fd4d7020734..ecb1176fd257 100644 --- a/depends/packages/blst.mk +++ b/depends/packages/blst.mk @@ -4,6 +4,7 @@ $(package)_download_path=https://github.com/supranational/blst/archive/refs/tags $(package)_download_file=v$($(package)_version).tar.gz $(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_sha256_hash=c3fef37b566b67419703b2bbb648e15176276af9a880c22aa8f5f2e8cecc2e4d +$(package)_patches=no_asm_limbs.patch # build.sh takes CC/AR/RANLIB/CFLAGS from the environment. __BLST_PORTABLE__ # selects runtime CPU dispatch instead of letting build.sh probe the builder's @@ -13,6 +14,10 @@ define $(package)_set_vars $(package)_build_env=CC="$($(package)_cc)" AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CFLAGS="$($(package)_cflags) $($(package)_cppflags) -fno-builtin -fPIC -D__BLST_PORTABLE__" endef +define $(package)_preprocess_cmds + patch -p1 < $($(package)_patch_dir)/no_asm_limbs.patch +endef + define $(package)_build_cmds ./build.sh endef diff --git a/depends/patches/blst/no_asm_limbs.patch b/depends/patches/blst/no_asm_limbs.patch new file mode 100644 index 000000000000..a7782114c2e7 --- /dev/null +++ b/depends/patches/blst/no_asm_limbs.patch @@ -0,0 +1,7 @@ +--- a/src/vect.h ++++ b/src/vect.h +@@ -10,3 +10,3 @@ + +-#if defined(__x86_64__) || defined(__aarch64__) ++#if (defined(__x86_64__) || defined(__aarch64__)) && !defined(__BLST_NO_ASM__) + /* These are available even in ILP32 flavours, but even then they are diff --git a/src/Makefile.am b/src/Makefile.am index 0724e19a22da..965450284fcb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,14 +31,6 @@ check_PROGRAMS = TESTS = BENCHMARKS = -# The first make in dashbls after configure reruns its config.status, which -# replaces relic_conf.h. Let that finish before compiling anything that -# includes it. -BUILT_SOURCES = dashbls/depends/relic/include/relic_conf.h - -dashbls/depends/relic/include/relic_conf.h: FORCE - $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C dashbls depends/relic/include/relic_conf.h - if ENABLE_STACKTRACES if ENABLE_CRASH_HOOKS if CRASH_HOOKS_WRAPPED_CXX_ABI @@ -54,7 +46,7 @@ endif # ENABLE_CRASH_HOOKS endif # ENABLE_STACKTRACES BITCOIN_INCLUDES=-I$(builddir) -I$(srcdir)/$(MINISKETCH_INCLUDE_DIR_INT) -I$(srcdir)/secp256k1/include -I$(srcdir)/$(UNIVALUE_INCLUDE_DIR_INT) -BITCOIN_INCLUDES+=-isystem$(srcdir)/dashbls/include -isystem$(srcdir)/dashbls/depends/relic/include -isystem$(srcdir)/dashbls/depends/minialloc/include +BITCOIN_INCLUDES+=$(DASHBLS_CPPFLAGS) BITCOIN_INCLUDES+=-isystem$(srcdir)/immer LIBBITCOIN_NODE=libbitcoin_node.a @@ -64,7 +56,6 @@ LIBBITCOIN_CLI=libbitcoin_cli.a LIBBITCOIN_UTIL=libbitcoin_util.a LIBBITCOIN_CRYPTO_BASE=crypto/libbitcoin_crypto_base.la LIBBITCOINQT=qt/libbitcoinqt.a -LIBDASHBLS=dashbls/libdashbls.la LIBSECP256K1=secp256k1/libsecp256k1.la if ENABLE_ZMQ @@ -118,9 +109,6 @@ LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_ARM_SHANI) endif noinst_LTLIBRARIES += $(LIBBITCOIN_CRYPTO) -$(LIBDASHBLS): - $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) - $(LIBSECP256K1): $(wildcard secp256k1/src/*.h) $(wildcard secp256k1/src/*.c) $(wildcard secp256k1/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) @@ -1254,7 +1242,7 @@ lib_LTLIBRARIES += $(LIBBITCOINKERNEL) libdashkernel_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS) $(PTHREAD_FLAGS) libdashkernel_la_LIBADD = $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) $(LIBSECP256K1) $(LIBDASHBLS) $(GMP_LIBS) -libdashkernel_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL -isystem$(srcdir)/dashbls/include -isystem$(srcdir)/dashbls/depends/relic/include -isystem$(srcdir)/dashbls/depends/minialloc/include -isystem$(srcdir)/immer $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) -I$(srcdir)/$(UNIVALUE_INCLUDE_DIR_INT) +libdashkernel_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL $(DASHBLS_CPPFLAGS) -isystem$(srcdir)/immer $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) -I$(srcdir)/$(UNIVALUE_INCLUDE_DIR_INT) # libdashkernel requires default symbol visibility, explicitly specify that # here so that things still work even when user configures with @@ -1423,7 +1411,7 @@ libdashconsensus_la_SOURCES = support/cleanse.cpp $(crypto_libbitcoin_crypto_bas libdashconsensus_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS) libdashconsensus_la_LIBADD = $(LIBDASHBLS) $(LIBSECP256K1) $(GMP_LIBS) libdashconsensus_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL -DDISABLE_OPTIMIZED_SHA256 -libdashconsensus_la_CPPFLAGS += -isystem$(srcdir)/dashbls/include -isystem$(srcdir)/dashbls/depends/relic/include -isystem$(srcdir)/dashbls/depends/minialloc/include +libdashconsensus_la_CPPFLAGS += $(DASHBLS_CPPFLAGS) libdashconsensus_la_CPPFLAGS += -isystem$(srcdir)/immer libdashconsensus_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) @@ -1456,6 +1444,7 @@ CLEANFILES += util/*.gcda util/*.gcno CLEANFILES += wallet/*.gcda wallet/*.gcno CLEANFILES += wallet/test/*.gcda wallet/test/*.gcno CLEANFILES += zmq/*.gcda zmq/*.gcno +CLEANFILES += dashbls/src/*.gcda dashbls/src/*.gcno dashbls/depends/mimalloc/src/*.gcda dashbls/depends/mimalloc/src/*.gcno CLEANFILES += obj/build.h IMMER_DIST = immer/immer @@ -1475,7 +1464,6 @@ $(top_srcdir)/$(subdir)/config/bitcoin-config.h.in: $(am__configure_deps) clean-local: - -$(MAKE) -C dashbls clean -$(MAKE) -C secp256k1 clean -rm -f leveldb/*/*.gcda leveldb/*/*.gcno leveldb/helpers/memenv/*.gcda leveldb/helpers/memenv/*.gcno -rm -f config.h @@ -1556,6 +1544,7 @@ include Makefile.minisketch.include include Makefile.crc32c.include include Makefile.leveldb.include +include Makefile.dashbls.include include Makefile.test_util.include include Makefile.test_fuzz.include diff --git a/src/Makefile.dashbls.include b/src/Makefile.dashbls.include new file mode 100644 index 000000000000..bb95d7abc8f7 --- /dev/null +++ b/src/Makefile.dashbls.include @@ -0,0 +1,115 @@ +# Copyright (c) 2026 The Dash Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +LIBDASHBLS_INT = dashbls/libdashbls.la + +noinst_LTLIBRARIES += $(LIBDASHBLS_INT) +if USE_MIMALLOC +LIBMIMALLOC_INT = dashbls/libmimalloc-secure.la +noinst_LTLIBRARIES += $(LIBMIMALLOC_INT) +endif + +# What consumers link, dependents first: dashbls -> mimalloc -> blst (from depends) +LIBDASHBLS = $(LIBDASHBLS_INT) $(LIBMIMALLOC_INT) $(BLST_LIBS) + +# Flags for consumers of the library +DASHBLS_CPPFLAGS = -isystem$(srcdir)/dashbls/include $(BLST_CPPFLAGS) + +# Flags used only when building the library itself. Its headers are treated +# as system headers, as they are for consumers, so that Dash's warning set +# (-Werror in CI) does not apply to the vendored code. +DASHBLS_CPPFLAGS_INT = $(BLST_CPPFLAGS) +DASHBLS_CPPFLAGS_INT += -isystem$(srcdir)/dashbls/include/dashbls +DASHBLS_CPPFLAGS_INT += -isystem$(srcdir)/dashbls/depends/mimalloc/include +if USE_MIMALLOC +DASHBLS_CPPFLAGS_INT += -DBLSALLOC_MIMALLOC=1 +endif + +MIMALLOC_CPPFLAGS_INT = +MIMALLOC_CPPFLAGS_INT += -I$(srcdir)/dashbls/depends/mimalloc/include +MIMALLOC_CPPFLAGS_INT += -I$(srcdir)/dashbls/depends/mimalloc/src +MIMALLOC_CPPFLAGS_INT += -DMI_SECURE=4 +MIMALLOC_CPPFLAGS_INT += -DNDEBUG + +DASHBLS_H = \ + dashbls/include/dashbls/bls.hpp \ + dashbls/include/dashbls/chaincode.hpp \ + dashbls/include/dashbls/elements.hpp \ + dashbls/include/dashbls/extendedprivatekey.hpp \ + dashbls/include/dashbls/extendedpublickey.hpp \ + dashbls/include/dashbls/hdkeys.hpp \ + dashbls/include/dashbls/hkdf.hpp \ + dashbls/include/dashbls/legacy.hpp \ + dashbls/include/dashbls/privatekey.hpp \ + dashbls/include/dashbls/schemes.hpp \ + dashbls/include/dashbls/test-utils.hpp \ + dashbls/include/dashbls/threshold.hpp \ + dashbls/include/dashbls/util.hpp + +dashbls_libdashbls_la_SOURCES = \ + $(DASHBLS_H) \ + dashbls/src/bls.cpp \ + dashbls/src/chaincode.cpp \ + dashbls/src/elements.cpp \ + dashbls/src/extendedprivatekey.cpp \ + dashbls/src/extendedpublickey.cpp \ + dashbls/src/legacy.cpp \ + dashbls/src/privatekey.cpp \ + dashbls/src/schemes.cpp \ + dashbls/src/threshold.cpp + +dashbls_libdashbls_la_CPPFLAGS = $(AM_CPPFLAGS) $(DASHBLS_CPPFLAGS_INT) + +# Specify -static in both CXXFLAGS and LDFLAGS so libtool will only build a +# static version of this library (same as crc32c and leveldb). +dashbls_libdashbls_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -static +dashbls_libdashbls_la_LDFLAGS = $(AM_LDFLAGS) -static + +MIMALLOC_H = \ + dashbls/depends/mimalloc/include/mimalloc-new-delete.h \ + dashbls/depends/mimalloc/include/mimalloc-override.h \ + dashbls/depends/mimalloc/include/mimalloc-stats.h \ + dashbls/depends/mimalloc/include/mimalloc.h \ + dashbls/depends/mimalloc/src/bitmap.h + +dashbls_libmimalloc_secure_la_SOURCES = \ + $(MIMALLOC_H) \ + dashbls/depends/mimalloc/src/alloc-aligned.c \ + dashbls/depends/mimalloc/src/alloc-posix.c \ + dashbls/depends/mimalloc/src/alloc.c \ + dashbls/depends/mimalloc/src/arena-meta.c \ + dashbls/depends/mimalloc/src/arena.c \ + dashbls/depends/mimalloc/src/bitmap.c \ + dashbls/depends/mimalloc/src/heap.c \ + dashbls/depends/mimalloc/src/init.c \ + dashbls/depends/mimalloc/src/libc.c \ + dashbls/depends/mimalloc/src/options.c \ + dashbls/depends/mimalloc/src/os.c \ + dashbls/depends/mimalloc/src/page-map.c \ + dashbls/depends/mimalloc/src/page.c \ + dashbls/depends/mimalloc/src/random.c \ + dashbls/depends/mimalloc/src/stats.c \ + dashbls/depends/mimalloc/src/prim/prim.c + +dashbls_libmimalloc_secure_la_CPPFLAGS = $(AM_CPPFLAGS) $(MIMALLOC_CPPFLAGS_INT) +dashbls_libmimalloc_secure_la_CFLAGS = $(AM_CFLAGS) $(PIE_FLAGS) -static +dashbls_libmimalloc_secure_la_LDFLAGS = $(AM_LDFLAGS) -static + +if ENABLE_TESTS +if !ENABLE_FUZZ +DASHBLS_RUNTEST = dashbls/runtest +TESTS += $(DASHBLS_RUNTEST) +check_PROGRAMS += $(DASHBLS_RUNTEST) + +dashbls_runtest_SOURCES = \ + dashbls/src/test.cpp \ + dashbls/src/test-vectors.hpp \ + dashbls/depends/catch2/include/catch2/catch.hpp +dashbls_runtest_CPPFLAGS = $(AM_CPPFLAGS) $(DASHBLS_CPPFLAGS_INT) -isystem$(srcdir)/dashbls/depends/catch2/include +dashbls_runtest_CPPFLAGS += -DDASHBLS_REFERENCE_VECTORS=\"$(abs_srcdir)/dashbls/test-vectors/reference.txt\" +dashbls_runtest_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +dashbls_runtest_LDADD = $(LIBDASHBLS) +dashbls_runtest_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(PTHREAD_FLAGS) -static +endif +endif diff --git a/src/bls/bls.cpp b/src/bls/bls.cpp index 96a188e2ae93..f1bb58767376 100644 --- a/src/bls/bls.cpp +++ b/src/bls/bls.cpp @@ -415,7 +415,7 @@ static void create_secure_allocator() // static variable in function scope ensures it's initialized when first accessed // and destroyed before LockedPoolManager - static mt_pooled_secure_allocator a(sizeof(bn_t) + sizeof(size_t)); + static mt_pooled_secure_allocator a(sizeof(blst_p2) + sizeof(size_t)); secure_allocator_instance = &a; } diff --git a/src/bls/bls.h b/src/bls/bls.h index 82abc2c6de04..dad1b39d6ab2 100644 --- a/src/bls/bls.h +++ b/src/bls/bls.h @@ -10,21 +10,17 @@ #include #include -// bls-dash uses relic, which may define DEBUG and ERROR, which leads to many warnings in some build setups -#undef ERROR -#undef DEBUG #include #include #include #include #include -#undef DOUBLE -#undef SEED #include #include #include #include +#include namespace bls { extern std::atomic bls_legacy_scheme; @@ -127,7 +123,11 @@ class CBLSWrapper if (!fValid) { return std::vector(SerSize, 0); } - return impl.Serialize(specificLegacyScheme); + if constexpr (std::is_same_v) { + return impl.Serialize(); + } else { + return impl.Serialize(specificLegacyScheme); + } } std::array ToBytes(const bool specificLegacyScheme) const @@ -135,7 +135,11 @@ class CBLSWrapper if (!fValid) { return std::array{}; } - return impl.SerializeToArray(specificLegacyScheme); + if constexpr (std::is_same_v) { + return impl.SerializeToArray(); + } else { + return impl.SerializeToArray(specificLegacyScheme); + } } const uint256& GetHash() const diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan index c20a58eec210..73b87a922401 100644 --- a/test/sanitizer_suppressions/ubsan +++ b/test/sanitizer_suppressions/ubsan @@ -2,6 +2,7 @@ # -fsanitize=undefined suppressions # ================================= +nonnull-attribute:dashbls/ # -fsanitize=integer suppressions # =============================== @@ -18,13 +19,16 @@ implicit-integer-sign-change:*/include/boost/ implicit-integer-sign-change:*/include/c++/ implicit-integer-sign-change:*/new_allocator.h implicit-integer-sign-change:crc32c/ +implicit-integer-sign-change:dashbls/ implicit-integer-sign-change:minisketch/ implicit-integer-sign-change:secp256k1* implicit-signed-integer-truncation:*/include/c++/ +implicit-signed-integer-truncation:dashbls/ implicit-signed-integer-truncation:leveldb/ implicit-signed-integer-truncation:secp256k1* implicit-signed-integer-truncation,implicit-integer-sign-change:secp256k1_modinv64_posdivsteps_62_var implicit-unsigned-integer-truncation:*/include/c++/ +implicit-unsigned-integer-truncation:dashbls/ implicit-unsigned-integer-truncation:leveldb/ implicit-unsigned-integer-truncation:secp256k1* implicit-signed-integer-truncation,implicit-integer-sign-change:secp256k1*