Merge pull request #5466 from UdjinM6/dashbls_1.3.0

chore: bump `dashbls` subtree to 1.3.0
This commit is contained in:
UdjinM6 2023-07-01 14:15:00 +03:00 committed by GitHub
commit d0d4514508
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 5866 additions and 12 deletions

View File

@ -15,6 +15,7 @@ blspy.*.so
.mypy_cache/
.pytest_chache/
.eggs/
cmake-build-debug/
js_build
node_modules
@ -67,6 +68,8 @@ yarn-error.log
.vs/
out/
target
Makefile.in
/ar-lib
/mdate-sh

View File

@ -14,6 +14,7 @@ endif()
project(BLS)
set(BUILD_BLS_JS_BINDINGS "1" CACHE STRING "")
set(BUILD_BLS_PYTHON_BINDINGS "1" CACHE STRING "")
set(BUILD_BLS_TESTS "1" CACHE STRING "")
set(BUILD_BLS_BENCHMARKS "1" CACHE STRING "")
@ -110,10 +111,36 @@ 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}
#)
add_subdirectory(src)
# Write include paths for rust binding
if(EMSCRIPTEN)
add_subdirectory(js-bindings)
file(APPEND "${CMAKE_CURRENT_LIST_DIR}/build/include_paths.txt" "${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}/c++/v1/;")
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()
if(EMSCRIPTEN)
if(BUILD_BLS_JS_BINDINGS)
add_subdirectory(js-bindings)
endif()
else()
# emscripten can't build python bindings, it produces only javascript
# add_subdirectory(contrib/pybind11)

373
src/dashbls/apple.rust.deps.sh Executable file
View File

@ -0,0 +1,373 @@
#!/bin/sh
set -x
# "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
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
}
prepare() {
download_gmp() {
GMP_VERSION="6.2.1"
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://gmplib.org/download/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
rm gmp/compat.c && cp ../../contrib/gmp-patch-6.2.1/compat.c gmp/compat.c
rm gmp/longlong.h && cp ../../contrib/gmp-patch-6.2.1/longlong.h gmp/longlong.h
# shellcheck disable=SC2039,SC2164
popd #contrib
# shellcheck disable=SC2039,SC2164
popd #build
}
download_cmake_toolchain() {
if [ ! -s "${BUILD}/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 "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}/contrib"
if [ ! -s "${CURRENT_DIR}/${BUILD}/contrib/relic" ]; then
# shellcheck disable=SC2039,SC2164
pushd "${CURRENT_DIR}/${BUILD}/contrib"
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 #contrib
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=arm-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
# shellcheck disable=SC2039,SC2164
popd # gmp
# shellcheck disable=SC2039,SC2164
popd # contrib
# shellcheck disable=SC2039,SC2164
popd # build
}
build_relic_arch() {
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
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"
else
EXTRA_ARGS+=" -DARCH=ARM"
if [[ $ARCH = "armv7s" ]]; then
EXTRA_ARGS+=" -DIOS_ARCH=armv7s"
elif [[ $ARCH = "armv7k" ]]; then
EXTRA_ARGS+=" -DIOS_ARCH=armv7k"
elif [[ $ARCH = "arm64_32" ]]; then
EXTRA_ARGS+=" -DIOS_ARCH=arm64_32"
fi
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 # contrib/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)
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}/_deps/relic-build/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
# 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"
}
build_target() {
BUILD_IN=$1
echo "Build target: $BUILD_IN"
ARCH=""
PLATFORM=""
# shellcheck disable=SC2039
if [[ $BUILD_IN = "x86_64-apple-ios" ]]; then
ARCH=x86_64
PLATFORM=$IPHONESIMULATOR
elif [[ $BUILD_IN = "aarch64-apple-ios" ]]; then
ARCH=arm64
PLATFORM=$IPHONEOS
elif [[ $BUILD_IN = "aarch64-apple-ios-sim" ]]; then
ARCH=arm64
PLATFORM=$IPHONESIMULATOR
elif [[ $BUILD_IN = "x86_64-apple-darwin" ]]; then
ARCH=x86_64
PLATFORM=$MACOS
elif [[ $BUILD_IN = "aarch64-apple-darwin" ]]; then
ARCH=arm64
PLATFORM=$MACOS
fi
build_all_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}/_deps/relic-build/lib/librelic_s.a" "build/artefacts/${BUILD_IN}"
cp "build/relic-${PFX}/_deps/sodium-build/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
}
prepare
build_target "$TARGET"

458
src/dashbls/apple.rust.sh Executable file
View File

@ -0,0 +1,458 @@
#!/bin/sh
set -x
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
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
}
prepare() {
download_gmp() {
GMP_VERSION="6.2.1"
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://gmplib.org/download/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
rm gmp/compat.c && cp ../../contrib/gmp-patch-6.2.1/compat.c gmp/compat.c
rm gmp/longlong.h && cp ../../contrib/gmp-patch-6.2.1/longlong.h gmp/longlong.h
# shellcheck disable=SC2039,SC2164
popd #contrib
# shellcheck disable=SC2039,SC2164
popd #build
}
download_cmake_toolchain() {
if [ ! -s "${BUILD}/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 "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}/contrib"
if [ ! -s "${CURRENT_DIR}/${BUILD}/contrib/relic" ]; then
# shellcheck disable=SC2039,SC2164
pushd "${CURRENT_DIR}/${BUILD}/contrib"
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 #contrib
fi
}
rm -rf ${BUILD}
mkdir -p ${BUILD}
download_relic
download_gmp
download_cmake_toolchain
mkdir -p ${BUILD}/artefacts/include
}
build_gmp_arch() {
PLATFORM=$1
ARCH=$2
PFX=${PLATFORM}-${ARCH}
# why this works with this host only?
HOST=arm-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
# shellcheck disable=SC2039,SC2164
popd # gmp
# shellcheck disable=SC2039,SC2164
popd # contrib
# shellcheck disable=SC2039,SC2164
popd # build
}
build_relic_arch() {
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
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"
else
EXTRA_ARGS+=" -DARCH=ARM"
if [[ $ARCH = "armv7s" ]]; then
EXTRA_ARGS+=" -DIOS_ARCH=armv7s"
elif [[ $ARCH = "armv7k" ]]; then
EXTRA_ARGS+=" -DIOS_ARCH=armv7k"
elif [[ $ARCH = "arm64_32" ]]; then
EXTRA_ARGS+=" -DIOS_ARCH=arm64_32"
fi
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 # contrib/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)
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"../relic-${PFX}/_deps/relic-build/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
# 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"
}
build_all() {
BUILD_IN=$1
TARGET_DIR=build/artefacts
# shellcheck disable=SC2039
IFS='|' read -ra BUILD_PAIRS <<< "$BUILD_IN"
# shellcheck disable=SC2039
for BUILD_PAIR in "${BUILD_PAIRS[@]}"
do
# shellcheck disable=SC2039
IFS=';' read -ra PARSED_PAIR <<< "$BUILD_PAIR"
# shellcheck disable=SC2039
PLATFORM=${PARSED_PAIR[0]}
# shellcheck disable=SC2039
ARCH=${PARSED_PAIR[1]}
GMP_LIPOARGS=""
RELIC_LIPOARGS=""
BLS_LIPOARGS=""
# shellcheck disable=SC2039
local NEED_LIPO=0
# shellcheck disable=SC2039
IFS='+' read -ra ARCHS <<< "$ARCH"
# shellcheck disable=SC2039
for i in "${!ARCHS[@]}"
do
# shellcheck disable=SC2039
local SINGLEARCH=${ARCHS[i]}
# build for every platform+arch
build_all_arch "$PLATFORM" "$SINGLEARCH"
PFX="${PLATFORM}"-"${SINGLEARCH}"
ARCH_TARGET_DIR=${TARGET_DIR}/${PFX}
rm -rf "${ARCH_TARGET_DIR}"
mkdir -p "${ARCH_TARGET_DIR}"
#mv "${BUILD}/gmplib-${PFX}/lib/libgmp.a" "${ARCH_TARGET_DIR}/libgmp.a"
#mv "${BUILD}/relic-${PFX}/_deps/relic-build/lib/librelic_s.a" "${ARCH_TARGET_DIR}/librelic.a"
#mv "${BUILD}/bls-${PFX}/libbls.a" "${ARCH_TARGET_DIR}/libbls.a"
libtool -static -o "${ARCH_TARGET_DIR}/libbls.a" \
"${BUILD}/gmplib-${PFX}/lib/libgmp.a" \
"${BUILD}/relic-${PFX}/_deps/relic-build/lib/librelic_s.a" \
"${BUILD}/bls-${PFX}/libbls.a"
# shellcheck disable=SC2039
GMP_LIPOARGS+="${ARCH_TARGET_DIR}/libgmp.a "
# shellcheck disable=SC2039
RELIC_LIPOARGS+="${ARCH_TARGET_DIR}/librelic.a "
# shellcheck disable=SC2039
BLS_LIPOARGS+="${ARCH_TARGET_DIR}/libbls.a "
NEED_LIPO=i
done
# Do lipo if we need https://developer.apple.com/forums/thread/666335?answerId=645963022#645963022
# if [[ $NEED_LIPO -gt 0 ]]
# then
# FAT_TARGET_DIR=${TARGET_DIR}/${PLATFORM}-fat
# rm -rf "${FAT_TARGET_DIR}"
# mkdir -p "${FAT_TARGET_DIR}"
# # shellcheck disable=SC2086
# xcrun lipo $GMP_LIPOARGS -create -output "${FAT_TARGET_DIR}/libgmp.a"
# # shellcheck disable=SC2086
# xcrun lipo $RELIC_LIPOARGS -create -output "${FAT_TARGET_DIR}/librelic.a"
# # shellcheck disable=SC2086
# xcrun lipo $BLS_LIPOARGS -create -output "${FAT_TARGET_DIR}/libbls.a"
# libtool -static -o "${FAT_TARGET_DIR}/libbls_combined.a" "${FAT_TARGET_DIR}/libgmp.a" "${FAT_TARGET_DIR}/librelic.a" "${FAT_TARGET_DIR}/libbls.a"
# rm "${FAT_TARGET_DIR}/libgmp.a"
# rm "${FAT_TARGET_DIR}/librelic.a"
# rm "${FAT_TARGET_DIR}/libbls.a"
# mv "${FAT_TARGET_DIR}/libbls_combined.a" "${FAT_TARGET_DIR}/libbls.a"
# # clean up
# # shellcheck disable=SC2039
# for i in "${!ARCHS[@]}"
# do
# local SINGLEARCH=${ARCHS[i]}
# rm -rf "${TARGET_DIR}-${SINGLEARCH}"
# done
# fi
done
}
#make_relic_headers_universal() {
# RELIC_TARGET_DIR=relic-iphoneos-arm64
# perl -p -e 's/#define WSIZE.*/#ifdef __LP64__\n#define WSIZE 64\n#else\n#define WSIZE 32\n#endif/' \
# "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h" \
# > "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h.new"
#
# rm "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h"
# mv "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h.new" "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h"
#}
#copy_headers() {
# mkdir build/artefacts/include
# # Copy all headers we will need
# cp -rf src/*.hpp build/artefacts/include
# cp -rf build/gmp/include/gmp.h build/artefacts/include
# cp -rf build/contrib/relic/include/*.h build/artefacts/include
# cp -rf build/contrib/relic/include/low/*.h build/artefacts/include
# cp -rf build/contrib/relic/relic-iphoneos-arm64/include/*.h build/artefacts/include
# rm -rf build/artefacts/include/test-utils.hpp
#}
#function make_fat_binary()
#{
# pushd artefacts
#
# XCFRAMEWORK_ARGS=""
#
# for dir in */; do
# if [ -d "$dir" ]; then
# if [[ "$dir" != "include/" ]]; then
# libtool -static -o "${dir}libbls_combined.a" "${dir}libgmp.a" "${dir}librelic.a" "${dir}libbls.a"
#
# XCFRAMEWORK_ARGS+="-library ${dir}libbls_combined.a -headers include "
# fi
# fi
# done
#
# #xcodebuild -create-xcframework $XCFRAMEWORK_ARGS -output "libbls.xcframework"
#}
prepare
build_all "${MACOS};x86_64+arm64"
build_all "${IPHONEOS};arm64|${IPHONESIMULATOR};arm64+x86_64"
#make_relic_headers_universal
#copy_headers
#make_fat_binary

404
src/dashbls/apple.rust.single.sh Executable file
View File

@ -0,0 +1,404 @@
#!/bin/sh
set -x
# "x86_64-apple-ios"
# "x86_64-apple-ios-sim"
# "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
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
}
prepare() {
download_gmp() {
GMP_VERSION="6.2.1"
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://gmplib.org/download/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
rm gmp/compat.c && cp ../../contrib/gmp-patch-6.2.1/compat.c gmp/compat.c
rm gmp/longlong.h && cp ../../contrib/gmp-patch-6.2.1/longlong.h gmp/longlong.h
# shellcheck disable=SC2039,SC2164
popd #contrib
# shellcheck disable=SC2039,SC2164
popd #build
}
download_cmake_toolchain() {
if [ ! -s "${BUILD}/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 "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}/contrib"
if [ ! -s "${CURRENT_DIR}/${BUILD}/contrib/relic" ]; then
# shellcheck disable=SC2039,SC2164
pushd "${CURRENT_DIR}/${BUILD}/contrib"
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 #contrib
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=arm-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
# shellcheck disable=SC2039,SC2164
popd # gmp
# shellcheck disable=SC2039,SC2164
popd # contrib
# shellcheck disable=SC2039,SC2164
popd # build
}
build_relic_arch() {
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
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"
else
EXTRA_ARGS+=" -DARCH=ARM"
if [[ $ARCH = "armv7s" ]]; then
EXTRA_ARGS+=" -DIOS_ARCH=armv7s"
elif [[ $ARCH = "armv7k" ]]; then
EXTRA_ARGS+=" -DIOS_ARCH=armv7k"
elif [[ $ARCH = "arm64_32" ]]; then
EXTRA_ARGS+=" -DIOS_ARCH=arm64_32"
fi
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 # contrib/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)
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"../relic-${PFX}/_deps/relic-build/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
# 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"
}
build_target() {
BUILD_IN=$1
echo "Build target: $BUILD_IN"
ARCH=""
PLATFORM=""
# shellcheck disable=SC2039
if [[ $BUILD_IN = "x86_64-apple-ios" ]]; then
ARCH=x86_64
PLATFORM=$IPHONESIMULATOR
elif [[ $BUILD_IN = "aarch64-apple-ios" ]]; then
ARCH=arm64
PLATFORM=$IPHONEOS
elif [[ $BUILD_IN = "aarch64-apple-ios-sim" ]]; then
ARCH=arm64
PLATFORM=$IPHONESIMULATOR
elif [[ $BUILD_IN = "x86_64-apple-darwin" ]]; then
ARCH=x86_64
PLATFORM=$MACOS
elif [[ $BUILD_IN = "aarch64-apple-darwin" ]]; then
ARCH=arm64
PLATFORM=$MACOS
fi
build_all_arch "$PLATFORM" "$ARCH"
PFX="${PLATFORM}"-"${ARCH}"
rm -rf "build/artefacts/${BUILD_IN}"
mkdir -p "build/artefacts/${BUILD_IN}/include"
# libtool -static -o "build/artefacts/${BUILD_IN}/libbls.a" \
# "build/gmplib-${PFX}/lib/libgmp.a" \
# "build/relic-${PFX}/_deps/relic-build/lib/librelic_s.a" \
# "build/bls-${PFX}/libbls.a"
cp "build/gmplib-${PFX}/lib/libgmp.a" "build/artefacts/${BUILD_IN}"
cp "build/relic-${PFX}/_deps/relic-build/lib/librelic_s.a" "build/artefacts/${BUILD_IN}"
cp "build/relic-${PFX}/_deps/sodium-build/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
}
#make_relic_headers_universal() {
# RELIC_TARGET_DIR=relic-iphoneos-arm64
# perl -p -e 's/#define WSIZE.*/#ifdef __LP64__\n#define WSIZE 64\n#else\n#define WSIZE 32\n#endif/' \
# "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h" \
# > "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h.new"
#
# rm "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h"
# mv "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h.new" "build/contrib/relic/${RELIC_TARGET_DIR}/include/relic_conf.h"
#}
#
#copy_headers() {
## mkdir build/artefacts/include
# # Copy all headers we will need
# cp -rf src/*.hpp ${BUILD}/artefacts/include
# cp -rf ${BUILD}/contrib/gmp/include/gmp.h ${BUILD}/artefacts/include
# cp -rf ${BUILD}/contrib/relic/include/*.h ${BUILD}/artefacts/include
# cp -rf ${BUILD}/contrib/relic/include/low/*.h ${BUILD}/artefacts/include
# #cp -rf ${BUILD}/contrib/relic/relic-iphoneos-arm64/include/*.h ${BUILD}/artefacts/include
# rm -rf ${BUILD}/artefacts/include/test-utils.hpp
#}
prepare
build_target "$TARGET"
#copy_headers
#build_all "${MACOS};x86_64+arm64"
#build_all "${IPHONEOS};arm64|${IPHONESIMULATOR};arm64+x86_64"
#make_relic_headers_universal
#copy_headers
#make_fat_binary

View File

@ -1,5 +1,5 @@
AC_PREREQ([2.60])
AC_INIT([libdashbls],[1.2.4])
AC_INIT([libdashbls],[1.3.0])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([build-aux/m4])
@ -783,3 +783,4 @@ 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

View File

@ -59,6 +59,7 @@ public:
GTElement Pair(const G2Element &b) const;
uint32_t GetFingerprint(bool fLegacy = false) const;
std::vector<uint8_t> Serialize(bool fLegacy = false) const;
G1Element Copy();
friend bool operator==(const G1Element &a, const G1Element &b);
friend bool operator!=(const G1Element &a, const G1Element &b);
@ -101,6 +102,7 @@ public:
G2Element Negate() const;
GTElement Pair(const G1Element &a) const;
std::vector<uint8_t> Serialize(bool fLegacy = false) const;
G2Element Copy();
friend bool operator==(G2Element const &a, G2Element const &b);
friend bool operator!=(G2Element const &a, G2Element const &b);

View File

@ -39,6 +39,7 @@ class CoreMPL {
public:
CoreMPL() = delete;
CoreMPL(const std::string& strId) : strCiphersuiteId(strId) {}
virtual ~CoreMPL() {}
// Generates a private key from a seed, similar to HD key generation
// (hashes the seed), and reduces it mod the group order
virtual PrivateKey KeyGen(const vector<uint8_t>& seed);
@ -112,7 +113,7 @@ protected:
bool fLegacy);
};
class BasicSchemeMPL : public CoreMPL {
class BasicSchemeMPL final : public CoreMPL {
public:
static const std::string CIPHERSUITE_ID;
BasicSchemeMPL() : CoreMPL(BasicSchemeMPL::CIPHERSUITE_ID) {}
@ -133,7 +134,7 @@ public:
const G2Element& signature) override;
};
class AugSchemeMPL : public CoreMPL {
class AugSchemeMPL final : public CoreMPL {
public:
static const std::string CIPHERSUITE_ID;
@ -186,7 +187,7 @@ public:
const G2Element& signature) override;
};
class PopSchemeMPL : public CoreMPL {
class PopSchemeMPL final : public CoreMPL {
public:
static const std::string CIPHERSUITE_ID;
@ -221,7 +222,7 @@ public:
/**
* This scheme reflects the Sign/Verify behaviour of older bls-signatures library versions (<0.1.29).
*/
class LegacySchemeMPL : public CoreMPL {
class LegacySchemeMPL final : public CoreMPL {
public:
LegacySchemeMPL() : CoreMPL(std::string{}) {}

View File

@ -34,5 +34,5 @@ foreach(file ${JS_BINDINGS_TESTS})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tests/${file} tests/${file} COPYONLY)
endforeach()
set_target_properties(blsjstmp PROPERTIES LINK_FLAGS "--bind -Oz --closure 1 -s MODULARIZE=1 -s NODEJS_CATCH_EXIT=1 -s NODEJS_CATCH_REJECTION=1")
set_target_properties(blsjstmp PROPERTIES LINK_FLAGS "--bind -Oz --closure 1 -s MODULARIZE=1")
add_custom_command(TARGET blsjstmp POST_BUILD COMMAND npm run build:web)

View File

@ -21,6 +21,7 @@ export declare class BasicSchemeMPL {
static deriveChildSk(sk: PrivateKey, index: number): PrivateKey;
static deriveChildSkUnhardened(sk: PrivateKey, index: number): PrivateKey;
static deriveChildPkUnhardened(pk: G1Element, index: number): G1Element;
static verifySecure(pk: G1Element, sig: G2Element, msg: Uint8Array): boolean;
}
export declare class PopSchemeMPL {

View File

@ -42,7 +42,8 @@ EMSCRIPTEN_BINDINGS(blsjs) {
.class_function("aggregateVerify", &SchemeMPLWrapper<BasicSchemeMPL>::AggregateVerify)
.class_function("deriveChildSk", &SchemeMPLWrapper<BasicSchemeMPL>::DeriveChildSk)
.class_function("deriveChildSkUnhardened", &SchemeMPLWrapper<BasicSchemeMPL>::DeriveChildSkUnhardened)
.class_function("deriveChildPkUnhardened", &SchemeMPLWrapper<BasicSchemeMPL>::DeriveChildPkUnhardened);
.class_function("deriveChildPkUnhardened", &SchemeMPLWrapper<BasicSchemeMPL>::DeriveChildPkUnhardened)
.class_function("verifySecure", &SchemeMPLWrapper<BasicSchemeMPL>::VerifySecure);
class_<PopSchemeMPLWrapper>("PopSchemeMPL")
.class_function("skToG1", &PopSchemeMPLWrapper::SkToG1)

View File

@ -81,6 +81,15 @@ template <typename SchemeMPL> class SchemeMPLWrapper : public JSWrapper<SchemeMP
return G1ElementWrapper(mpl.DeriveChildPkUnhardened(pk.GetWrappedInstance(), index));
}
static bool VerifySecure(val pubkeyArray, const G2ElementWrapper &signature, val messageVal) {
std::vector<G1Element> pubkeys = G1ElementWrapper::Unwrap
(helpers::toVectorFromJSArray<G1ElementWrapper>(pubkeyArray));
std::vector <uint8_t> message = helpers::toVector(messageVal);
return mpl.VerifySecure(pubkeys, signature.GetWrappedInstance(), message);
}
protected:
static inline SchemeMPL mpl;
};

View File

@ -21,6 +21,7 @@ from bls12381 import h_eff, q
from ec import JacobianPoint, default_ec_twist, eval_iso
from fields import Fq, Fq2, roots_of_unity
from hash_to_field import Hp2
from typing import Union
def sgn0(x: Fq2) -> int:
@ -198,7 +199,7 @@ def iso3(P):
#
# map from Fq2 element(s) to point in G2 subgroup of Ell2
#
def opt_swu2_map(t: Fq2, t2: Fq2 = None) -> JacobianPoint:
def opt_swu2_map(t: Fq2, t2: Union[Fq2, None] = None) -> JacobianPoint:
Pp = iso3(osswu2_help(t))
if t2 is not None:
Pp2 = iso3(osswu2_help(t2))

2
src/dashbls/rust-bindings/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
Cargo.lock
target

View File

@ -0,0 +1,17 @@
unstable_features = true
blank_lines_lower_bound = 0
condense_wildcard_suffixes = true
error_on_line_overflow = true
error_on_unformatted = true
format_code_in_doc_comments = true
format_macro_matchers = true
format_strings = true
imports_granularity = "Crate"
normalize_comments = true
normalize_doc_attributes = true
reorder_impl_items = true
group_imports = "StdExternalCrate"
use_field_init_shorthand = true
use_try_shorthand = true
wrap_comments = true

View File

@ -0,0 +1,15 @@
[package]
name = "bls-dash-sys"
description = ""
version = "1.2.5"
build = "build.rs"
edition = "2021"
[features]
default = []
apple = []
[build-dependencies]
cc = "1.0"
bindgen = "0.65.1"
glob ="0.3"

View File

@ -0,0 +1,435 @@
pub type G1Element = *mut ::std::os::raw::c_void;
pub type G2Element = *mut ::std::os::raw::c_void;
pub type PrivateKey = *mut ::std::os::raw::c_void;
pub type CoreMPL = *mut ::std::os::raw::c_void;
pub type BasicSchemeMPL = CoreMPL;
pub type AugSchemeMPL = CoreMPL;
pub type PopSchemeMPL = CoreMPL;
pub type LegacySchemeMPL = CoreMPL;
pub type BIP32ExtendedPrivateKey = *mut ::std::os::raw::c_void;
pub type BIP32ExtendedPublicKey = *mut ::std::os::raw::c_void;
pub type BIP32ChainCode = *mut ::std::os::raw::c_void;
extern "C" {
pub fn G1ElementSize() -> ::std::os::raw::c_int;
pub fn G1ElementFromBytes(
data: *const ::std::os::raw::c_void,
legacy: bool,
didErr: *mut bool,
) -> G1Element;
pub fn G1ElementGenerator() -> G1Element;
pub fn G1ElementIsValid(el: G1Element) -> bool;
pub fn G1ElementGetFingerprint(el: G1Element, legacy: bool) -> u32;
pub fn G1ElementIsEqual(el1: G1Element, el2: G1Element) -> bool;
pub fn G1ElementAdd(el1: G1Element, el2: G1Element) -> G1Element;
pub fn G1ElementMul(el: G1Element, sk: PrivateKey) -> G1Element;
pub fn G1ElementNegate(el: G1Element) -> G1Element;
pub fn G1ElementCopy(el: G1Element) -> G1Element;
pub fn G1ElementSerialize(el: G1Element, legacy: bool) -> *mut ::std::os::raw::c_void;
pub fn G1ElementFree(el: G1Element);
pub fn G2ElementSize() -> ::std::os::raw::c_int;
pub fn G2ElementFromBytes(
data: *const ::std::os::raw::c_void,
legacy: bool,
didErr: *mut bool,
) -> G2Element;
pub fn G2ElementGenerator() -> G2Element;
pub fn G2ElementIsValid(el: G2Element) -> bool;
pub fn G2ElementIsEqual(el1: G2Element, el2: G2Element) -> bool;
pub fn G2ElementAdd(el1: G2Element, el2: G2Element) -> G2Element;
pub fn G2ElementMul(el: G2Element, sk: PrivateKey) -> G2Element;
pub fn G2ElementNegate(el: G2Element) -> G2Element;
pub fn G2ElementCopy(el: G2Element) -> G2Element;
pub fn G2ElementSerialize(el: G2Element, legacy: bool) -> *mut ::std::os::raw::c_void;
pub fn G2ElementFree(el: G2Element);
pub fn PrivateKeyFromBytes(
data: *const ::std::os::raw::c_void,
modOrder: bool,
didErr: *mut bool,
) -> PrivateKey;
pub fn PrivateKeyFromSeedBIP32(data: *const ::std::os::raw::c_void, len: usize) -> PrivateKey;
pub fn PrivateKeyAggregate(sks: *mut *mut ::std::os::raw::c_void, len: usize) -> PrivateKey;
pub fn PrivateKeyGetG1Element(sk: PrivateKey, didErr: *mut bool) -> G1Element;
pub fn PrivateKeyGetG2Element(sk: PrivateKey, didErr: *mut bool) -> G2Element;
pub fn PrivateKeyGetG2Power(sk: PrivateKey, el: G2Element) -> G2Element;
pub fn PrivateKeyIsEqual(sk1: PrivateKey, sk2: PrivateKey) -> bool;
pub fn PrivateKeySerialize(sk: PrivateKey) -> *mut ::std::os::raw::c_void;
pub fn PrivateKeyFree(sk: PrivateKey);
pub fn PrivateKeySizeBytes() -> usize;
pub fn SecFree(p: *mut ::std::os::raw::c_void);
pub fn AllocPtrArray(len: usize) -> *mut *mut ::std::os::raw::c_void;
pub fn SetPtrArray(
arrPtr: *mut *mut ::std::os::raw::c_void,
elemPtr: *mut ::std::os::raw::c_void,
index: ::std::os::raw::c_int,
);
pub fn FreePtrArray(inPtr: *mut *mut ::std::os::raw::c_void);
pub fn GetPtrAtIndex(
arrPtr: *mut *mut ::std::os::raw::c_void,
index: ::std::os::raw::c_int,
) -> *mut ::std::os::raw::c_void;
pub fn SecAllocBytes(len: usize) -> *mut u8;
pub fn GetAddressAtIndex(
ptr: *mut u8,
index: ::std::os::raw::c_int,
) -> *mut ::std::os::raw::c_void;
pub fn GetLastErrorMsg() -> *const ::std::os::raw::c_char;
pub fn CoreMPLKeyGen(
scheme: CoreMPL,
seed: *const ::std::os::raw::c_void,
seedLen: usize,
didErr: *mut bool,
) -> PrivateKey;
pub fn CoreMPLSkToG1(scheme: CoreMPL, sk: PrivateKey) -> G1Element;
pub fn CoreMPLSign(
scheme: CoreMPL,
sk: PrivateKey,
msg: *const ::std::os::raw::c_void,
msgLen: usize,
) -> G2Element;
pub fn CoreMPLVerify(
scheme: BasicSchemeMPL,
pk: G1Element,
msg: *const ::std::os::raw::c_void,
msgLen: usize,
sig: G2Element,
) -> bool;
pub fn CoreMPLVerifySecure(
scheme: CoreMPL,
pks: *mut *mut ::std::os::raw::c_void,
pksLen: usize,
sig: G2Element,
msg: *const ::std::os::raw::c_void,
msgLen: usize,
) -> bool;
pub fn CoreMPLAggregatePubKeys(
scheme: CoreMPL,
pubKeys: *mut *mut ::std::os::raw::c_void,
pkLen: usize,
) -> G1Element;
pub fn CoreMPLAggregateSigs(
scheme: CoreMPL,
sigs: *mut *mut ::std::os::raw::c_void,
sigLen: usize,
) -> G2Element;
pub fn CoreMPLDeriveChildSk(scheme: CoreMPL, sk: PrivateKey, index: u32) -> PrivateKey;
pub fn CoreMPLDeriveChildSkUnhardened(
scheme: CoreMPL,
sk: PrivateKey,
index: u32,
) -> PrivateKey;
pub fn CoreMPLDeriveChildPkUnhardened(scheme: CoreMPL, sk: G1Element, index: u32) -> G1Element;
pub fn CoreMPLAggregateVerify(
scheme: CoreMPL,
pks: *mut *mut ::std::os::raw::c_void,
pkLen: usize,
msgs: *mut *mut ::std::os::raw::c_void,
msgLens: *const ::std::os::raw::c_void,
msgLen: usize,
sig: G2Element,
) -> bool;
pub fn NewBasicSchemeMPL() -> BasicSchemeMPL;
pub fn BasicSchemeMPLAggregateVerify(
scheme: BasicSchemeMPL,
pks: *mut *mut ::std::os::raw::c_void,
pksLen: usize,
msgs: *mut *mut ::std::os::raw::c_void,
msgsLens: *const ::std::os::raw::c_void,
msgsLen: usize,
sig: G2Element,
) -> bool;
pub fn BasicSchemeMPLFree(scheme: BasicSchemeMPL);
pub fn NewAugSchemeMPL() -> AugSchemeMPL;
pub fn AugSchemeMPLSign(
scheme: AugSchemeMPL,
sk: PrivateKey,
msg: *const ::std::os::raw::c_void,
msgLen: usize,
) -> G2Element;
pub fn AugSchemeMPLSignPrepend(
scheme: AugSchemeMPL,
sk: PrivateKey,
msg: *const ::std::os::raw::c_void,
msgLen: usize,
prepPk: G1Element,
) -> G2Element;
pub fn AugSchemeMPLVerify(
scheme: AugSchemeMPL,
pk: G1Element,
msg: *const ::std::os::raw::c_void,
msgLen: usize,
sig: G2Element,
) -> bool;
pub fn AugSchemeMPLAggregateVerify(
scheme: AugSchemeMPL,
pks: *mut *mut ::std::os::raw::c_void,
pksLen: usize,
msgs: *mut *mut ::std::os::raw::c_void,
msgsLens: *const ::std::os::raw::c_void,
msgsLen: usize,
sig: G2Element,
) -> bool;
pub fn AugSchemeMPLFree(scheme: AugSchemeMPL);
pub fn NewPopSchemeMPL() -> PopSchemeMPL;
pub fn PopSchemeMPLPopProve(scheme: PopSchemeMPL, sk: PrivateKey) -> G2Element;
pub fn PopSchemeMPLPopVerify(scheme: PopSchemeMPL, pk: G1Element, sig: G2Element) -> bool;
pub fn PopSchemeMPLFastAggregateVerify(
scheme: PopSchemeMPL,
pks: *mut *mut ::std::os::raw::c_void,
pksLen: usize,
msgs: *const ::std::os::raw::c_void,
msgsLen: usize,
sig: G2Element,
) -> bool;
pub fn PopSchemeMPLFree(scheme: PopSchemeMPL);
pub fn NewLegacySchemeMPL() -> LegacySchemeMPL;
pub fn LegacySchemeMPLSign(
scheme: LegacySchemeMPL,
sk: PrivateKey,
msg: *const ::std::os::raw::c_void,
msgLen: usize,
) -> G2Element;
pub fn LegacySchemeMPLSignPrepend(
scheme: LegacySchemeMPL,
sk: PrivateKey,
msg: *const ::std::os::raw::c_void,
msgLen: usize,
prepPk: G1Element,
) -> G2Element;
pub fn LegacySchemeMPLVerify(
scheme: LegacySchemeMPL,
pk: G1Element,
msg: *const ::std::os::raw::c_void,
msgLen: usize,
sig: G2Element,
) -> bool;
pub fn LegacySchemeMPLVerifySecure(
scheme: LegacySchemeMPL,
pks: *mut *mut ::std::os::raw::c_void,
pksLen: usize,
sig: G2Element,
msg: *const ::std::os::raw::c_void,
msgLen: usize,
) -> bool;
pub fn LegacySchemeMPLAggregateVerify(
scheme: LegacySchemeMPL,
pks: *mut *mut ::std::os::raw::c_void,
pksLen: usize,
msgs: *mut *mut ::std::os::raw::c_void,
msgsLens: *const ::std::os::raw::c_void,
msgsLen: usize,
sig: G2Element,
) -> bool;
pub fn LegacySchemeMPLFree(scheme: LegacySchemeMPL);
pub fn ThresholdPrivateKeyShare(
sks: *mut *mut ::std::os::raw::c_void,
sksLen: usize,
hash: *const ::std::os::raw::c_void,
didErr: *mut bool,
) -> PrivateKey;
pub fn ThresholdPrivateKeyRecover(
sks: *mut *mut ::std::os::raw::c_void,
sksLen: usize,
hashes: *mut *mut ::std::os::raw::c_void,
hashesLen: usize,
didErr: *mut bool,
) -> PrivateKey;
pub fn ThresholdPublicKeyShare(
pks: *mut *mut ::std::os::raw::c_void,
pksLen: usize,
hash: *const ::std::os::raw::c_void,
didErr: *mut bool,
) -> G1Element;
pub fn ThresholdPublicKeyRecover(
pks: *mut *mut ::std::os::raw::c_void,
pksLen: usize,
hashes: *mut *mut ::std::os::raw::c_void,
hashesLen: usize,
didErr: *mut bool,
) -> G1Element;
pub fn ThresholdSignatureShare(
sigs: *mut *mut ::std::os::raw::c_void,
sigsLen: usize,
hash: *const ::std::os::raw::c_void,
didErr: *mut bool,
) -> G2Element;
pub fn ThresholdSignatureRecover(
sigs: *mut *mut ::std::os::raw::c_void,
sigsLen: usize,
hashes: *mut *mut ::std::os::raw::c_void,
hashesLen: usize,
didErr: *mut bool,
) -> G2Element;
pub fn ThresholdSign(sk: PrivateKey, hash: *const ::std::os::raw::c_void) -> G2Element;
pub fn ThresholdVerify(
pk: G1Element,
hash: *const ::std::os::raw::c_void,
sig: G2Element,
) -> bool;
pub fn BIP32ChainCodeSerialize(cc: BIP32ChainCode) -> *mut ::std::os::raw::c_void;
pub fn BIP32ChainCodeIsEqual(cc1: BIP32ChainCode, cc2: BIP32ChainCode) -> bool;
pub fn BIP32ChainCodeFree(cc: BIP32ChainCode);
pub fn BIP32ExtendedPublicKeyFromBytes(
data: *const ::std::os::raw::c_void,
legacy: bool,
didErr: *mut bool,
) -> BIP32ExtendedPublicKey;
pub fn BIP32ExtendedPublicKeyPublicChild(
pk: BIP32ExtendedPublicKey,
index: u32,
legacy: bool,
) -> BIP32ExtendedPublicKey;
pub fn BIP32ExtendedPublicKeyGetChainCode(pk: BIP32ExtendedPublicKey) -> BIP32ChainCode;
pub fn BIP32ExtendedPublicKeySerialize(
pk: BIP32ExtendedPublicKey,
legacy: bool,
) -> *mut ::std::os::raw::c_void;
pub fn BIP32ExtendedPublicKeyIsEqual(
pk1: BIP32ExtendedPublicKey,
pk2: BIP32ExtendedPublicKey,
) -> bool;
pub fn BIP32ExtendedPublicKeyGetPublicKey(
pk: BIP32ExtendedPublicKey,
) -> *mut ::std::os::raw::c_void;
pub fn BIP32ExtendedPublicKeyFree(pk: BIP32ExtendedPublicKey);
pub fn BIP32ExtendedPrivateKeyFromBytes(
data: *const ::std::os::raw::c_void,
didErr: *mut bool,
) -> BIP32ExtendedPrivateKey;
pub fn BIP32ExtendedPrivateKeyFromSeed(
data: *const ::std::os::raw::c_void,
len: usize,
didErr: *mut bool,
) -> BIP32ExtendedPrivateKey;
pub fn BIP32ExtendedPrivateKeyPrivateChild(
sk: BIP32ExtendedPrivateKey,
index: u32,
legacy: bool,
) -> BIP32ExtendedPrivateKey;
pub fn BIP32ExtendedPrivateKeyPublicChild(
sk: BIP32ExtendedPrivateKey,
index: u32,
) -> BIP32ExtendedPublicKey;
pub fn BIP32ExtendedPrivateKeyGetChainCode(sk: BIP32ExtendedPrivateKey) -> BIP32ChainCode;
pub fn BIP32ExtendedPrivateKeySerialize(
sk: BIP32ExtendedPrivateKey,
) -> *mut ::std::os::raw::c_void;
pub fn BIP32ExtendedPrivateKeyIsEqual(
sk1: BIP32ExtendedPrivateKey,
sk2: BIP32ExtendedPrivateKey,
) -> bool;
pub fn BIP32ExtendedPrivateKeyGetPrivateKey(
sk: BIP32ExtendedPrivateKey,
) -> *mut ::std::os::raw::c_void;
pub fn BIP32ExtendedPrivateKeyGetExtendedPublicKey(
sk: BIP32ExtendedPrivateKey,
legacy: bool,
didErr: *mut bool,
) -> BIP32ExtendedPublicKey;
pub fn BIP32ExtendedPrivateKeyGetPublicKey(
sk: BIP32ExtendedPrivateKey,
didErr: *mut bool,
) -> *mut ::std::os::raw::c_void;
pub fn BIP32ExtendedPrivateKeyFree(sk: BIP32ExtendedPrivateKey);
}

View File

@ -0,0 +1,374 @@
use std::{env, fs, io, io::Write, path::{Path, PathBuf}, process::{Command, Output}};
#[cfg(not(feature = "apple"))]
fn create_cross_cmake_command() -> Command {
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
let mut command = if target_arch.eq("wasm32") {
Command::new("emcmake")
} else {
Command::new("cmake")
};
if target_arch.eq("wasm32") {
command.arg("cmake");
}
command
}
fn handle_command_output(output: Output) {
io::stdout()
.write_all(&output.stdout)
.expect("should write output");
io::stderr()
.write_all(&output.stderr)
.expect("should write output");
assert!(output.status.success());
}
#[cfg(not(feature = "apple"))]
fn main() {
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
// TODO: fix build for wasm32 on MacOS
// errors with `error: linking with `rust-lld` failed: exit status: 1`
if target_arch.eq("wasm32") {
println!("Build for wasm32 is not fully supported");
return;
}
let root_path = Path::new("../..")
.canonicalize()
.expect("can't get abs path");
let bls_dash_build_path = root_path.join("build");
let bls_dash_src_path = root_path.join("src");
let c_bindings_path = root_path.join("rust-bindings/bls-dash-sys/c-bindings");
println!("root {}", root_path.display());
println!("bls_dash_build_path {}", bls_dash_build_path.display());
println!("bls_dash_src_path {}", bls_dash_src_path.display());
// println!("c_bindings_path {}", c_bindings_path.display());
// Run cmake
println!("Run cmake:");
if bls_dash_build_path.exists() {
fs::remove_dir_all(&bls_dash_build_path).expect("can't clean build directory");
}
fs::create_dir_all(&bls_dash_build_path).expect("can't create build directory");
let cmake_output = create_cross_cmake_command()
.current_dir(&bls_dash_build_path)
.arg("-DBUILD_BLS_PYTHON_BINDINGS=0")
.arg("-DBUILD_BLS_TESTS=0")
.arg("-DBUILD_BLS_BENCHMARKS=0")
.arg("-DBUILD_BLS_JS_BINDINGS=0")
.arg("..")
.output()
.expect("can't run cmake");
handle_command_output(cmake_output);
// Build deps for bls-signatures
println!("Build dependencies:");
let build_output = Command::new("cmake")
.args(["--build", ".", "--", "-j", "6"])
.current_dir(&bls_dash_build_path)
.output()
.expect("can't build bls-signatures deps");
handle_command_output(build_output);
// Collect include paths
let include_paths_file_path = bls_dash_build_path.join("include_paths.txt");
let include_paths =
fs::read_to_string(include_paths_file_path).expect("should read include paths from file");
let mut include_paths: Vec<_> = include_paths
.split(';')
.filter(|path| !path.is_empty())
.map(|path| PathBuf::from(path))
.collect();
include_paths.extend([
bls_dash_build_path.join("_deps/relic-src/include"),
bls_dash_build_path.join("_deps/relic-build/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(),
]);
// Build c binding
println!("Build C binding:");
let mut cc = cc::Build::new();
let cpp_files_mask = c_bindings_path.join("**/*.cpp");
let cpp_files: Vec<_> = glob::glob(cpp_files_mask.to_str().unwrap())
.expect("can't get list of cpp files")
.filter_map(Result::ok)
.collect();
cc.files(cpp_files)
.includes(&include_paths)
.cpp(true)
.flag_if_supported("-std=c++14");
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
// Fix homebrew LLVM installation issue
if env::consts::OS == "macos" && target_arch == "wasm32" {
cc.archiver("llvm-ar");
}
if target_arch.eq("wasm32") {
cc.flag_if_supported("-ffreestanding")
.define("_LIBCPP_HAS_NO_THREADS", Some("1"));
}
if !cfg!(debug_assertions) {
cc.opt_level(2);
}
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");
println!(
"cargo:rustc-link-search={}",
root_path.join("build/depends/mimalloc").display()
);
println!("cargo:rustc-link-lib=static=mimalloc-secure");
println!(
"cargo:rustc-link-search={}",
bls_dash_build_path.join("src").display()
);
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");
}
// Generate rust code for c binding to src/lib.rs
// println!("Generate C binding for rust:");
// let mut builder = bindgen::Builder::default()
// // .trust_clang_mangling(true)
// // .wasm_import_module_name()
// .size_t_is_usize(true)
// .parse_callbacks(Box::new(bindgen::CargoCallbacks));
// let headers_to_process = [
// "blschia.h",
// "elements.h",
// "privatekey.h",
// "schemes.h",
// "threshold.h",
// "bip32/chaincode.h",
// "bip32/extendedprivatekey.h",
// "bip32/extendedpublickey.h",
// ];
// for header in headers_to_process {
// builder = builder.header(c_bindings_path.join(header).to_str().unwrap())
// }
// if target_arch == "wasm32" {
// builder = builder.clang_args(
// include_paths
// .iter()
// .map(|path| format!("-I{}", path.display())),
// );
// }
// let bindings = builder.generate().expect("Unable to generate bindings");
// let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
// bindings
// .write_to_file(out_path.join("bindings.rs"))
// .expect("couldn't write bindings");
// // Rerun build if files changed
// println!("cargo:rerun-if-changed={}", c_bindings_path.display());
println!("cargo:rerun-if-changed={}", bls_dash_src_path.display());
}
// fn main() {
// let target = env::var("TARGET").unwrap();
// println!("Building bls-signatures for apple target: {}", target);
// let root_path = Path::new("../..")
// .canonicalize()
// .expect("can't get abs path");
// let bls_dash_build_path = root_path.join("build");
// let bls_dash_src_path = root_path.join("src");
// let artefacts_path = bls_dash_build_path.join("artefacts");
// let target_path = artefacts_path.join(&target);
// let script = root_path.join("apple.rust.single.sh");
// if bls_dash_build_path.exists() {
// fs::remove_dir_all(&bls_dash_build_path).expect("can't clean build directory");
// }
// fs::create_dir_all(&bls_dash_build_path).expect("can't create build directory");
// let output = Command::new("sh")
// .current_dir(&root_path)
// .arg(script)
// .arg(target)
// .output()
// .expect("Failed to execute the shell script");
// handle_command_output(output);
// let library_path = target_path.join("libbls.a");
// if !fs::metadata(&library_path).is_ok() {
// panic!("Library file not found: {}", library_path.display());
// }
// 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");
// println!("cargo:rerun-if-changed={}", bls_dash_src_path.display());
// }
#[cfg(feature = "apple")]
fn main() {
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
// TODO: fix build for wasm32 on MacOS
// errors with `error: linking with `rust-lld` failed: exit status: 1`
if target_arch.eq("wasm32") {
println!("Build for wasm32 is not fully supported");
return;
}
let target = env::var("TARGET").unwrap();
println!("Building bls-signatures for apple target: {}", target);
let root_path = Path::new("../..")
.canonicalize()
.expect("can't get abs path");
let bls_dash_build_path = root_path.join("build");
let bls_dash_src_path = root_path.join("src");
let bls_dash_src_include_path = root_path.join("include/dashbls");
let c_bindings_path = root_path.join("rust-bindings/bls-dash-sys/c-bindings");
let artefacts_path = bls_dash_build_path.join("artefacts");
let target_path = artefacts_path.join(&target);
let script = root_path.join("apple.rust.deps.sh");
if bls_dash_build_path.exists() {
fs::remove_dir_all(&bls_dash_build_path).expect("can't clean build directory");
}
fs::create_dir_all(&bls_dash_build_path).expect("can't create build directory");
let output = Command::new("sh")
.current_dir(&root_path)
.arg(script)
.arg(target.as_str())
.output()
.expect("Failed to execute the shell script");
handle_command_output(output);
let (arch, platform) = match target.as_str() {
"x86_64-apple-ios" => ("x86_64", "iphonesimulator"),
"aarch64-apple-ios" => ("arm64", "iphoneos"),
"aarch64-apple-ios-sim" => ("arm64", "iphonesimulator"),
"x86_64-apple-darwin" => ("x86_64", "macosx"),
"aarch64-apple-darwin" => ("arm64", "macosx"),
_ => panic!("Target {} not supported", target.as_str())
};
env::set_var("IPHONEOS_DEPLOYMENT_TARGET", "13.0");
// Collect include paths
let include_paths_file_path = bls_dash_build_path.join("include_paths.txt");
let include_paths =
fs::read_to_string(include_paths_file_path).expect("should read include paths from file");
let mut include_paths: Vec<_> = include_paths
.split(';')
.filter(|path| !path.is_empty())
.map(|path| PathBuf::from(path))
.collect();
include_paths.extend([
bls_dash_build_path.join(format!("relic-{}-{}/_deps/relic-src/include", platform, arch)),
bls_dash_build_path.join(format!("relic-{}-{}/_deps/relic-build/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(),
bls_dash_src_include_path.clone()
]);
let cpp_files: Vec<_> = glob::glob(c_bindings_path.join("**/*.cpp").to_str().unwrap())
.expect("can't get list of cpp files")
.filter_map(Result::ok)
.collect();
let mut cc = cc::Build::new();
cc.files(cpp_files)
.includes(&include_paths)
.cpp(true)
.flag("-Wno-unused-parameter")
.flag("-Wno-sign-compare")
.flag("-Wno-delete-non-abstract-non-virtual-dtor")
.flag("-std=c++14");
cc.compile("dashbls");
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-lib=static=bls");
println!("cargo:rustc-link-search={}", bls_dash_src_path.display());
println!("cargo:rustc-link-lib=static=dashbls");
println!("cargo:rerun-if-changed={}", bls_dash_src_path.display());
}

View File

@ -0,0 +1,25 @@
#include <vector>
#include "bls.hpp"
#include "chaincode.h"
void* BIP32ChainCodeSerialize(const BIP32ChainCode cc)
{
const bls::ChainCode* ccPtr = (bls::ChainCode*)cc;
const std::vector<uint8_t> serialized = ccPtr->Serialize();
uint8_t* buffer = (uint8_t*)malloc(bls::ChainCode::SIZE);
memcpy(buffer, serialized.data(), bls::ChainCode::SIZE);
return (void*)buffer;
}
bool BIP32ChainCodeIsEqual(const BIP32ChainCode cc1, const BIP32ChainCode cc2)
{
const bls::ChainCode* cc1Ptr = (bls::ChainCode*)cc1;
const bls::ChainCode* cc2Ptr = (bls::ChainCode*)cc2;
return *cc1Ptr == *cc2Ptr;
}
void BIP32ChainCodeFree(const BIP32ChainCode cc)
{
const bls::ChainCode* ccPtr = (bls::ChainCode*)cc;
delete ccPtr;
}

View File

@ -0,0 +1,21 @@
#ifndef BIP32CHAINCODE_H_
#define BIP32CHAINCODE_H_
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef void* BIP32ChainCode;
void* BIP32ChainCodeSerialize(const BIP32ChainCode cc);
bool BIP32ChainCodeIsEqual(const BIP32ChainCode cc1, const BIP32ChainCode cc2);
void BIP32ChainCodeFree(const BIP32ChainCode cc);
#ifdef __cplusplus
}
#endif
#endif // BIP32CHAINCODE_H_

View File

@ -0,0 +1,128 @@
#include "extendedprivatekey.h"
#include <vector>
#include "../blschia.h"
#include "../error.h"
#include "bls.hpp"
BIP32ExtendedPrivateKey BIP32ExtendedPrivateKeyFromBytes(const void* data, bool* didErr)
{
bls::ExtendedPrivateKey* el = nullptr;
try {
el = new bls::ExtendedPrivateKey(bls::ExtendedPrivateKey::FromBytes(
bls::Bytes((uint8_t*)(data), bls::ExtendedPrivateKey::SIZE)));
} catch (const std::exception& ex) {
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
*didErr = false;
return el;
}
BIP32ExtendedPrivateKey BIP32ExtendedPrivateKeyFromSeed(const void* data, const size_t len, bool* didErr)
{
bls::ExtendedPrivateKey* el = nullptr;
try {
el = new bls::ExtendedPrivateKey(bls::ExtendedPrivateKey::FromSeed(
bls::Bytes((uint8_t*)(data), len)));
} catch (const std::exception& ex) {
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
*didErr = false;
return el;
}
BIP32ExtendedPrivateKey BIP32ExtendedPrivateKeyPrivateChild(
const BIP32ExtendedPrivateKey sk,
const uint32_t index,
const bool legacy)
{
const bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
return new bls::ExtendedPrivateKey(skPtr->PrivateChild(index, legacy));
}
BIP32ExtendedPublicKey BIP32ExtendedPrivateKeyPublicChild(
const BIP32ExtendedPrivateKey sk,
const uint32_t index)
{
const bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
return new bls::ExtendedPublicKey(skPtr->PublicChild(index));
}
BIP32ChainCode BIP32ExtendedPrivateKeyGetChainCode(const BIP32ExtendedPrivateKey sk)
{
const bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
return new bls::ChainCode(skPtr->GetChainCode());
}
void* BIP32ExtendedPrivateKeySerialize(const BIP32ExtendedPrivateKey sk)
{
const bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
uint8_t* buffer =
bls::Util::SecAlloc<uint8_t>(bls::ExtendedPrivateKey::SIZE);
skPtr->Serialize(buffer);
return (void*)buffer;
}
bool BIP32ExtendedPrivateKeyIsEqual(
const BIP32ExtendedPrivateKey sk1,
const BIP32ExtendedPrivateKey sk2)
{
const bls::ExtendedPrivateKey* sk1Ptr = (bls::ExtendedPrivateKey*)sk1;
const bls::ExtendedPrivateKey* sk2Ptr = (bls::ExtendedPrivateKey*)sk2;
return *sk1Ptr == *sk2Ptr;
}
void* BIP32ExtendedPrivateKeyGetPrivateKey(const BIP32ExtendedPrivateKey sk)
{
bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
return new bls::PrivateKey(skPtr->GetPrivateKey());
}
void* BIP32ExtendedPrivateKeyGetPublicKey(
const BIP32ExtendedPrivateKey sk,
bool* didErr)
{
bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
bls::G1Element* el = nullptr;
try {
el = new bls::G1Element(skPtr->GetPublicKey());
*didErr = false;
} catch (const std::exception& ex) {
// set err
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
return el;
}
BIP32ExtendedPublicKey BIP32ExtendedPrivateKeyGetExtendedPublicKey(
const BIP32ExtendedPrivateKey sk,
const bool legacy,
bool* didErr)
{
bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
bls::ExtendedPublicKey* pk = nullptr;
try {
pk = new bls::ExtendedPublicKey(skPtr->GetExtendedPublicKey(legacy));
*didErr = false;
} catch (const std::exception& ex) {
// set err
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
return pk;
}
void BIP32ExtendedPrivateKeyFree(const BIP32ExtendedPrivateKey sk)
{
const bls::ExtendedPrivateKey* skPtr = (bls::ExtendedPrivateKey*)sk;
delete skPtr;
}

View File

@ -0,0 +1,48 @@
#ifndef BIP32EXTENDEDPRIVATEKEY_H_
#define BIP32EXTENDEDPRIVATEKEY_H_
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "extendedpublickey.h"
#include "chaincode.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void* BIP32ExtendedPrivateKey;
// ExtendedPrivateKey
BIP32ExtendedPrivateKey BIP32ExtendedPrivateKeyFromBytes(
const void* data,
bool* didErr);
BIP32ExtendedPrivateKey BIP32ExtendedPrivateKeyFromSeed(const void* data, const size_t len, bool* didErr);
BIP32ExtendedPrivateKey BIP32ExtendedPrivateKeyPrivateChild(
const BIP32ExtendedPrivateKey sk,
const uint32_t index,
const bool legacy);
BIP32ExtendedPublicKey BIP32ExtendedPrivateKeyPublicChild(
const BIP32ExtendedPrivateKey sk,
const uint32_t index);
BIP32ChainCode BIP32ExtendedPrivateKeyGetChainCode(const BIP32ExtendedPrivateKey sk);
void* BIP32ExtendedPrivateKeySerialize(const BIP32ExtendedPrivateKey sk);
bool BIP32ExtendedPrivateKeyIsEqual(
const BIP32ExtendedPrivateKey sk1,
const BIP32ExtendedPrivateKey sk2);
void* BIP32ExtendedPrivateKeyGetPrivateKey(const BIP32ExtendedPrivateKey sk);
BIP32ExtendedPublicKey BIP32ExtendedPrivateKeyGetExtendedPublicKey(
const BIP32ExtendedPrivateKey sk,
const bool legacy,
bool* didErr);
void* BIP32ExtendedPrivateKeyGetPublicKey(
const BIP32ExtendedPrivateKey sk,
bool* didErr);
void BIP32ExtendedPrivateKeyFree(const BIP32ExtendedPrivateKey sk);
#ifdef __cplusplus
}
#endif
#endif // BIP32EXTENDEDPRIVATEKEY_H_

View File

@ -0,0 +1,72 @@
#include "extendedpublickey.h"
#include <vector>
#include "../blschia.h"
#include "../error.h"
#include "bls.hpp"
BIP32ExtendedPublicKey BIP32ExtendedPublicKeyFromBytes(
const void* data,
const bool legacy,
bool* didErr)
{
bls::ExtendedPublicKey* el = nullptr;
try {
el = new bls::ExtendedPublicKey(bls::ExtendedPublicKey::FromBytes(
bls::Bytes((uint8_t*)(data), bls::ExtendedPublicKey::SIZE),
legacy));
} catch (const std::exception& ex) {
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
*didErr = false;
return el;
}
BIP32ExtendedPublicKey BIP32ExtendedPublicKeyPublicChild(
const BIP32ExtendedPublicKey pk,
const uint32_t index,
const bool legacy)
{
const bls::ExtendedPublicKey* pkPtr = (bls::ExtendedPublicKey*)pk;
return new bls::ExtendedPublicKey(pkPtr->PublicChild(index, legacy));
}
BIP32ChainCode BIP32ExtendedPublicKeyGetChainCode(const BIP32ExtendedPublicKey pk)
{
const bls::ExtendedPublicKey* pkPtr = (bls::ExtendedPublicKey*)pk;
return new bls::ChainCode(pkPtr->GetChainCode());
}
void* BIP32ExtendedPublicKeyGetPublicKey(const BIP32ExtendedPublicKey pk) {
bls::ExtendedPublicKey* pkPtr = (bls::ExtendedPublicKey*)pk;
return new bls::G1Element(pkPtr->GetPublicKey());
}
void* BIP32ExtendedPublicKeySerialize(
const BIP32ExtendedPublicKey pk,
const bool legacy)
{
const bls::ExtendedPublicKey* pkPtr = (bls::ExtendedPublicKey*)pk;
const std::vector<uint8_t> serialized = pkPtr->Serialize(legacy);
uint8_t* buffer = (uint8_t*)malloc(bls::ExtendedPublicKey::SIZE);
memcpy(buffer, serialized.data(), bls::ExtendedPublicKey::SIZE);
return (void*)buffer;
}
bool BIP32ExtendedPublicKeyIsEqual(
const BIP32ExtendedPublicKey pk1,
const BIP32ExtendedPublicKey pk2)
{
const bls::ExtendedPublicKey* pk1Ptr = (bls::ExtendedPublicKey*)pk1;
const bls::ExtendedPublicKey* pk2Ptr = (bls::ExtendedPublicKey*)pk2;
return *pk1Ptr == *pk2Ptr;
}
void BIP32ExtendedPublicKeyFree(const BIP32ExtendedPublicKey pk)
{
const bls::ExtendedPublicKey* pkPtr = (bls::ExtendedPublicKey*)pk;
delete pkPtr;
}

View File

@ -0,0 +1,38 @@
#ifndef BIP32EXTENDEDPUBLICKEY_H_
#define BIP32EXTENDEDPUBLICKEY_H_
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "chaincode.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void* BIP32ExtendedPublicKey;
// ExtendedPublicKey
BIP32ExtendedPublicKey BIP32ExtendedPublicKeyFromBytes(
const void* data,
const bool legacy,
bool* didErr);
BIP32ExtendedPublicKey BIP32ExtendedPublicKeyPublicChild(
const BIP32ExtendedPublicKey pk,
const uint32_t index,
const bool legacy);
BIP32ChainCode BIP32ExtendedPublicKeyGetChainCode(const BIP32ExtendedPublicKey pk);
void* BIP32ExtendedPublicKeyGetPublicKey(const BIP32ExtendedPublicKey pk);
void* BIP32ExtendedPublicKeySerialize(
const BIP32ExtendedPublicKey pk,
const bool legacy);
bool BIP32ExtendedPublicKeyIsEqual(
const BIP32ExtendedPublicKey pk1,
const BIP32ExtendedPublicKey pk2);
void BIP32ExtendedPublicKeyFree(const BIP32ExtendedPublicKey pk);
#ifdef __cplusplus
}
#endif
#endif // BIP32EXTENDEDPUBLICKEY_H_

View File

@ -0,0 +1,56 @@
// Copyright (c) 2021 The Dash Core developers
// 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 <string>
#include <stdlib.h>
#include "bls.hpp"
#include "error.h"
#include "blschia.h"
// TODO: Revisit
std::string gErrMsg;
void SecFree(void *p) {
bls::Util::SecFree(p);
}
void** AllocPtrArray(size_t len) {
// caller to free
return (void**)bls::Util::SecAlloc<uint8_t>(sizeof(void*) * len);
}
void SetPtrArray(void** arrPtr, void* elemPtr, int index) {
arrPtr[index] = elemPtr;
}
void FreePtrArray(void** inPtr) {
bls::Util::SecFree(inPtr);
}
void* GetPtrAtIndex(void** arrPtr, int index) {
return arrPtr[index];
}
uint8_t* SecAllocBytes(size_t len) {
return (uint8_t*)bls::Util::SecAlloc<uint8_t>(sizeof(uint8_t) * len);
}
void* GetAddressAtIndex(uint8_t* ptr, int index) {
return (void*)&ptr[index];
}
const char* GetLastErrorMsg() {
return gErrMsg.c_str();
}

View File

@ -0,0 +1,46 @@
// Copyright (c) 2021 The Dash Core developers
// 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 BLSCHIA_H_
#define BLSCHIA_H_
#include <stdbool.h>
#include <stdint.h>
#include "privatekey.h"
#ifdef __cplusplus
extern "C" {
#endif
// Export the BLS SecFree method
void SecFree(void *p);
typedef void** carr;
// Additional C++ helper funcs for allocations
void** AllocPtrArray(size_t len);
void SetPtrArray(void **arrPtr, void *elemPtr, int index);
void FreePtrArray(void **inPtr);
void* GetPtrAtIndex(void **arrPtr, int index);
// Allocates an array of bytes with size of passed in len argument
uint8_t* SecAllocBytes(size_t len);
void* GetAddressAtIndex(uint8_t *ptr, int index);
const char* GetLastErrorMsg();
#ifdef __cplusplus
}
#endif
#endif // BLSCHIA_H_

View File

@ -0,0 +1,162 @@
// Copyright (c) 2021 The Dash Core developers
// 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 <vector>
#include "bls.hpp"
#include "blschia.h"
#include "error.h"
#include "elements.h"
// G1Element
int G1ElementSize() {
return bls::G1Element::SIZE;
}
G1Element G1ElementFromBytes(const void* data, bool legacy, bool* didErr) {
bls::G1Element* el = nullptr;
try {
el = new bls::G1Element(
bls::G1Element::FromBytes(bls::Bytes((uint8_t*)(data), bls::G1Element::SIZE), legacy)
);
} catch(const std::exception& ex) {
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
*didErr = false;
return el;
}
G1Element G1ElementGenerator() {
return new bls::G1Element(bls::G1Element::Generator());
}
bool G1ElementIsValid(const G1Element el) {
const bls::G1Element* elPtr = (bls::G1Element*)el;
return elPtr->IsValid();
}
uint32_t G1ElementGetFingerprint(const G1Element el, const bool legacy) {
const bls::G1Element* elPtr = (bls::G1Element*)el;
return elPtr->GetFingerprint(legacy);
}
void* G1ElementSerialize(const G1Element el, const bool legacy) {
const bls::G1Element* elPtr = (bls::G1Element*)el;
const std::vector<uint8_t> serialized = elPtr->Serialize(legacy);
uint8_t* buffer = (uint8_t*)malloc(bls::G1Element::SIZE);
memcpy(buffer, serialized.data(), bls::G1Element::SIZE);
return (void*)buffer;
}
bool G1ElementIsEqual(const G1Element el1, const G1Element el2) {
const bls::G1Element* el1Ptr = (bls::G1Element*)el1;
const bls::G1Element* el2Ptr = (bls::G1Element*)el2;
return *el1Ptr == *el2Ptr;
}
G1Element G1ElementAdd(const G1Element el1, const G1Element el2) {
const bls::G1Element* el1Ptr = (bls::G1Element*)el1;
const bls::G1Element* el2Ptr = (bls::G1Element*)el2;
return new bls::G1Element((*el1Ptr) + (*el2Ptr));
}
G1Element G1ElementMul(const G1Element el, const PrivateKey sk) {
const bls::G1Element* elPtr = (bls::G1Element*)el;
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
return new bls::G1Element(*elPtr * *skPtr);
}
G1Element G1ElementNegate(const G1Element el) {
const bls::G1Element* elPtr = (bls::G1Element*)el;
return new bls::G1Element(elPtr->Negate());
}
G1Element G1ElementCopy(const G1Element el) {
return new bls::G1Element(((bls::G1Element*)el)->Copy());
}
void G1ElementFree(const G1Element el) {
const bls::G1Element* elPtr = (bls::G1Element*)el;
delete elPtr;
}
// G2Element
int G2ElementSize() {
return bls::G2Element::SIZE;
}
G2Element G2ElementFromBytes(const void* data, const bool legacy, bool* didErr) {
bls::G2Element* el = nullptr;
try {
el = new bls::G2Element(
bls::G2Element::FromBytes(bls::Bytes((uint8_t*)data, bls::G2Element::SIZE), legacy)
);
*didErr = false;
} catch(const std::exception& ex) {
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
return el;
}
G2Element G2ElementGenerator() {
return new bls::G2Element(bls::G2Element::Generator());
}
bool G2ElementIsValid(const G2Element el) {
const bls::G2Element* elPtr = (bls::G2Element*)el;
return elPtr->IsValid();
}
void* G2ElementSerialize(const G2Element el, const bool legacy) {
const bls::G2Element* elPtr = (bls::G2Element*)el;
const std::vector<uint8_t> serialized = elPtr->Serialize(legacy);
uint8_t* buffer = (uint8_t*)malloc(bls::G2Element::SIZE);
memcpy(buffer, serialized.data(), bls::G2Element::SIZE);
return (void*)buffer;
}
bool G2ElementIsEqual(const G2Element el1, const G2Element el2) {
const bls::G2Element* el1Ptr = (bls::G2Element*)el1;
const bls::G2Element* el2Ptr = (bls::G2Element*)el2;
return *el1Ptr == *el2Ptr;
}
G2Element G2ElementAdd(const G2Element el1, const G2Element el2) {
bls::G2Element* el1Ptr = (bls::G2Element*)el1;
bls::G2Element* el2Ptr = (bls::G2Element*)el2;
return new bls::G2Element(*el1Ptr + *el2Ptr);
}
G2Element G2ElementMul(const G2Element el, const PrivateKey sk) {
const bls::G2Element* elPtr = (bls::G2Element*)el;
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
return new bls::G2Element(*elPtr * *skPtr);
}
G2Element G2ElementNegate(const G2Element el) {
const bls::G2Element* elPtr = (bls::G2Element*)el;
return new bls::G2Element(elPtr->Negate());
}
G2Element G2ElementCopy(const G1Element el) {
return new bls::G2Element(((bls::G2Element*)el)->Copy());
}
void G2ElementFree(const G2Element el) {
bls::G2Element* elPtr = (bls::G2Element*)el;
delete elPtr;
}

View File

@ -0,0 +1,58 @@
// Copyright (c) 2021 The Dash Core developers
// 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 ELEMENTS_H_
#define ELEMENTS_H_
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef void* G1Element;
typedef void* G2Element;
typedef void* PrivateKey;
// G1Element
int G1ElementSize();
G1Element G1ElementFromBytes(const void* data, const bool legacy, bool* didErr);
G1Element G1ElementGenerator();
bool G1ElementIsValid(const G1Element el);
uint32_t G1ElementGetFingerprint(const G1Element el, const bool legacy);
bool G1ElementIsEqual(const G1Element el1, const G1Element el2);
G1Element G1ElementAdd(const G1Element el1, const G1Element el2);
G1Element G1ElementMul(const G1Element el, const PrivateKey sk);
G1Element G1ElementNegate(const G1Element el);
G1Element G1ElementCopy(const G1Element el);
void* G1ElementSerialize(const G1Element el, const bool legacy);
void G1ElementFree(const G1Element el);
// G2Element
int G2ElementSize();
G2Element G2ElementFromBytes(const void* data, const bool legacy, bool* didErr);
G2Element G2ElementGenerator();
bool G2ElementIsValid(const G2Element el);
bool G2ElementIsEqual(const G2Element el1, const G2Element el2);
G2Element G2ElementAdd(const G2Element el1, const G2Element el2);
G2Element G2ElementMul(const G2Element el, const PrivateKey sk);
G2Element G2ElementNegate(const G2Element el);
G2Element G2ElementCopy(const G2Element el);
void* G2ElementSerialize(const G2Element el, const bool legacy);
void G2ElementFree(const G2Element el);
#ifdef __cplusplus
}
#endif
#endif // ELEMENTS_H_

View File

@ -0,0 +1,21 @@
// Copyright (c) 2020 The Dash Core developers
// 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 ERROR_H_
#define ERROR_H_
#include <string>
extern std::string gErrMsg;
#endif // ERROR_H_

View File

@ -0,0 +1,120 @@
// Copyright (c) 2021 The Dash Core developers
// 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 <vector>
#include "bls.hpp"
#include "privatekey.h"
#include "blschia.h"
#include "error.h"
#include "utils.hpp"
// private key bindings implementation
PrivateKey PrivateKeyFromBytes(const void* data, const bool modOrder, bool* didErr) {
bls::PrivateKey* skPtr = nullptr;
try {
skPtr = new bls::PrivateKey(
bls::PrivateKey::FromBytes(
bls::Bytes((uint8_t*)data, bls::PrivateKey::PRIVATE_KEY_SIZE),
modOrder
)
);
} catch (const std::exception& ex) {
// set err
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
*didErr = false;
return skPtr;
}
PrivateKey PrivateKeyFromSeedBIP32(const void* data, const size_t len) {
return new bls::PrivateKey(
bls::PrivateKey::FromSeedBIP32(bls::Bytes((uint8_t*)data, len))
);
}
PrivateKey PrivateKeyAggregate(void** sks, const size_t len) {
return new bls::PrivateKey(
bls::PrivateKey::Aggregate(toBLSVector<bls::PrivateKey>(sks, len))
);
}
void* PrivateKeySerialize(const PrivateKey sk) {
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
uint8_t* buffer = bls::Util::SecAlloc<uint8_t>(bls::PrivateKey::PRIVATE_KEY_SIZE);
skPtr->Serialize(buffer);
return (void*)buffer;
}
size_t PrivateKeySizeBytes() {
return bls::PrivateKey::PRIVATE_KEY_SIZE;
}
bool PrivateKeyIsEqual(const PrivateKey sk1, const PrivateKey sk2) {
const bls::PrivateKey* sk1Ptr = (bls::PrivateKey*)sk1;
const bls::PrivateKey* sk2Ptr = (bls::PrivateKey*)sk2;
return *sk1Ptr == *sk2Ptr;
}
G1Element PrivateKeyGetG1Element(const PrivateKey sk, bool* didErr) {
bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
bls::G1Element* el = nullptr;
try {
el = new bls::G1Element(skPtr->GetG1Element());
*didErr = false;
} catch (const std::exception& ex) {
// set err
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
return el;
}
G2Element PrivateKeyGetG2Element(const PrivateKey sk, bool* didErr) {
bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
bls::G2Element* el = nullptr;
try {
el = new bls::G2Element(skPtr->GetG2Element());
*didErr = false;
} catch (const std::exception& ex) {
// set err
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
return el;
}
G2Element PrivateKeyGetG2Power(const PrivateKey sk, const G2Element el) {
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
const bls::G2Element* elPtr = (bls::G2Element*)el;
return new bls::G2Element(skPtr->GetG2Power(*elPtr));
}
G2Element PrivateKeySignG2(const PrivateKey sk,
uint8_t* msg,
const size_t len,
const uint8_t* dst,
const size_t dstLen) {
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
return new bls::G2Element(skPtr->SignG2(msg, len, dst, dstLen));
}
void PrivateKeyFree(PrivateKey sk) {
bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
delete skPtr;
}

View File

@ -0,0 +1,40 @@
// Copyright (c) 2021 The Dash Core developers
// 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 PRIVATEKEY_H_
#define PRIVATEKEY_H_
#include <stdbool.h>
#include <stdlib.h>
#include "elements.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void* PrivateKey;
PrivateKey PrivateKeyFromBytes(const void* data, const bool modOrder, bool* didErr);
PrivateKey PrivateKeyFromSeedBIP32(const void* data, const size_t len);
PrivateKey PrivateKeyAggregate(void** sks, const size_t len);
G1Element PrivateKeyGetG1Element(const PrivateKey sk, bool* didErr);
G2Element PrivateKeyGetG2Element(const PrivateKey sk, bool* didErr);
G2Element PrivateKeyGetG2Power(const PrivateKey sk, const G2Element el);
bool PrivateKeyIsEqual(const PrivateKey sk1, const PrivateKey sk2);
void* PrivateKeySerialize(const PrivateKey sk);
void PrivateKeyFree(const PrivateKey sk);
size_t PrivateKeySizeBytes();
#ifdef __cplusplus
}
#endif
#endif // PRIVATEKEY_H_

View File

@ -0,0 +1,388 @@
// Copyright (c) 2021 The Dash Core developers
// 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 "schemes.h"
#include <vector>
#include "bls.hpp"
#include "blschia.h"
#include "elements.h"
#include "error.h"
#include "privatekey.h"
#include "utils.hpp"
// Implementation of bindings for CoreMPL class
PrivateKey CoreMPLKeyGen(
const CoreMPL scheme,
const void* seed,
const size_t seedLen,
bool* didErr)
{
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
bls::PrivateKey* sk = nullptr;
try {
sk = new bls::PrivateKey(
schemePtr->KeyGen(bls::Bytes((uint8_t*)seed, seedLen)));
} catch (const std::exception& ex) {
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
*didErr = false;
return sk;
}
G1Element CoreMPLSkToG1(const CoreMPL scheme, const PrivateKey sk)
{
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
return new bls::G1Element(schemePtr->SkToG1(*skPtr));
}
G2Element CoreMPLSign(
CoreMPL scheme,
const PrivateKey sk,
const void* msg,
const size_t msgLen)
{
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
return new bls::G2Element(
schemePtr->Sign(*skPtr, bls::Bytes((uint8_t*)msg, msgLen)));
}
bool CoreMPLVerify(
const CoreMPL scheme,
const G1Element pk,
const void* msg,
const size_t msgLen,
const G2Element sig)
{
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
const bls::G1Element* pkPtr = (bls::G1Element*)pk;
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
return schemePtr->Verify(
*pkPtr, bls::Bytes((uint8_t*)msg, msgLen), *sigPtr);
}
bool CoreMPLVerifySecure(
const CoreMPL scheme,
void** pks,
const size_t pksLen,
const G2Element sig,
const void* msg,
const size_t msgLen)
{
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
const std::vector<bls::G1Element> vecPubKeys =
toBLSVector<bls::G1Element>(pks, pksLen);
const uint8_t* msgPtr = (uint8_t*)msg;
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
return schemePtr->VerifySecure(
vecPubKeys, *sigPtr, bls::Bytes(msgPtr, msgLen));
}
G1Element CoreMPLAggregatePubKeys(
const CoreMPL scheme,
void** pks,
const size_t pksLen)
{
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
return new bls::G1Element(
schemePtr->Aggregate(toBLSVector<bls::G1Element>(pks, pksLen)));
}
G2Element CoreMPLAggregateSigs(
const CoreMPL scheme,
void** sigs,
const size_t sigsLen)
{
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
return new bls::G2Element(
schemePtr->Aggregate(toBLSVector<bls::G2Element>(sigs, sigsLen)));
}
PrivateKey CoreMPLDeriveChildSk(
const CoreMPL scheme,
const PrivateKey sk,
const uint32_t index)
{
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
return new bls::PrivateKey(schemePtr->DeriveChildSk(*skPtr, index));
}
PrivateKey CoreMPLDeriveChildSkUnhardened(
CoreMPL scheme,
PrivateKey sk,
uint32_t index)
{
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
return new bls::PrivateKey(
schemePtr->DeriveChildSkUnhardened(*skPtr, index));
}
G1Element CoreMPLDeriveChildPkUnhardened(
CoreMPL scheme,
G1Element el,
uint32_t index)
{
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
bls::G1Element* elPtr = (bls::G1Element*)el;
return new bls::G1Element(
schemePtr->DeriveChildPkUnhardened(*elPtr, index));
}
bool CoreMPLAggregateVerify(
const CoreMPL scheme,
void** pks,
const size_t pksLen,
void** msgs,
const void* msgsLens,
const size_t msgsLen,
const G2Element sig)
{
bls::CoreMPL* schemePtr = (bls::CoreMPL*)scheme;
const size_t* msgLensPtr = (size_t*)msgsLens;
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
const std::vector<bls::G1Element> vecPubKeys =
toBLSVector<bls::G1Element>(pks, pksLen);
const std::vector<size_t> vecMsgsLens =
std::vector<size_t>(msgLensPtr, msgLensPtr + msgsLen);
const std::vector<bls::Bytes> vecMsgs =
toVectorBytes(msgs, msgsLen, vecMsgsLens);
return schemePtr->AggregateVerify(vecPubKeys, vecMsgs, *sigPtr);
}
// BasicSchemeMPL
BasicSchemeMPL NewBasicSchemeMPL() { return new bls::BasicSchemeMPL(); }
bool BasicSchemeMPLAggregateVerify(
BasicSchemeMPL scheme,
void** pks,
const size_t pksLen,
void** msgs,
const void* msgsLens,
const size_t msgsLen,
const G2Element sig)
{
bls::BasicSchemeMPL* schemePtr = (bls::BasicSchemeMPL*)scheme;
const size_t* msgLensPtr = (size_t*)msgsLens;
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
const std::vector<bls::G1Element> vecPubKeys =
toBLSVector<bls::G1Element>(pks, pksLen);
const std::vector<size_t> vecMsgsLens =
std::vector<size_t>(msgLensPtr, msgLensPtr + msgsLen);
const std::vector<bls::Bytes> vecMsgs =
toVectorBytes(msgs, msgsLen, vecMsgsLens);
return schemePtr->AggregateVerify(vecPubKeys, vecMsgs, *sigPtr);
}
void BasicSchemeMPLFree(BasicSchemeMPL scheme)
{
bls::BasicSchemeMPL* schemePtr = (bls::BasicSchemeMPL*)scheme;
delete schemePtr;
}
// AugSchemeMPL
AugSchemeMPL NewAugSchemeMPL() { return new bls::AugSchemeMPL(); }
G2Element AugSchemeMPLSign(
const AugSchemeMPL scheme,
const PrivateKey sk,
const void* msg,
const size_t msgLen)
{
bls::AugSchemeMPL* schemePtr = (bls::AugSchemeMPL*)scheme;
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
return new bls::G2Element(
schemePtr->Sign(*skPtr, bls::Bytes((uint8_t*)msg, msgLen)));
}
G2Element AugSchemeMPLSignPrepend(
const AugSchemeMPL scheme,
const PrivateKey sk,
const void* msg,
const size_t msgLen,
const G1Element prepPk)
{
bls::AugSchemeMPL* schemePtr = (bls::AugSchemeMPL*)scheme;
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
const bls::G1Element* prepPkPtr = (bls::G1Element*)prepPk;
return new bls::G2Element(
schemePtr->Sign(*skPtr, bls::Bytes((uint8_t*)msg, msgLen), *prepPkPtr));
}
bool AugSchemeMPLVerify(
const AugSchemeMPL scheme,
const G1Element pk,
const void* msg,
const size_t msgLen,
const G2Element sig)
{
bls::AugSchemeMPL* schemePtr = (bls::AugSchemeMPL*)scheme;
const bls::G1Element* pkPtr = (bls::G1Element*)pk;
const uint8_t* msgPtr = (uint8_t*)msg;
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
return schemePtr->Verify(*pkPtr, bls::Bytes(msgPtr, msgLen), *sigPtr);
}
bool AugSchemeMPLAggregateVerify(
const AugSchemeMPL scheme,
void** pks,
const size_t pksLen,
void** msgs,
const void* msgsLens,
const size_t msgsLen,
const G2Element sig)
{
bls::AugSchemeMPL* schemePtr = (bls::AugSchemeMPL*)scheme;
const size_t* msgLensPtr = (size_t*)msgsLens;
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
const std::vector<bls::G1Element> vecPubKeys =
toBLSVector<bls::G1Element>(pks, pksLen);
const std::vector<size_t> vecMsgsLens =
std::vector<size_t>(msgLensPtr, msgLensPtr + msgsLen);
const std::vector<bls::Bytes> vecMsgs =
toVectorBytes(msgs, msgsLen, vecMsgsLens);
return schemePtr->AggregateVerify(vecPubKeys, vecMsgs, *sigPtr);
}
void AugSchemeMPLFree(AugSchemeMPL scheme)
{
bls::AugSchemeMPL* schemePtr = (bls::AugSchemeMPL*)scheme;
delete schemePtr;
}
// PopSchemeMPL
PopSchemeMPL NewPopSchemeMPL() { return new bls::PopSchemeMPL(); }
G2Element PopSchemeMPLPopProve(
const PopSchemeMPL scheme,
const PrivateKey sk)
{
bls::PopSchemeMPL* schemePtr = (bls::PopSchemeMPL*)scheme;
const bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
return new bls::G2Element(schemePtr->PopProve(*skPtr));
}
bool PopSchemeMPLPopVerify(
const PopSchemeMPL scheme,
const G1Element pk,
const G2Element sig)
{
bls::PopSchemeMPL* schemePtr = (bls::PopSchemeMPL*)scheme;
const bls::G1Element* pkPtr = (bls::G1Element*)pk;
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
return schemePtr->PopVerify(*pkPtr, *sigPtr);
}
bool PopSchemeMPLFastAggregateVerify(
const PopSchemeMPL scheme,
void** pks,
const size_t pksLen,
const void* msg,
const size_t msgLen,
const G2Element sig)
{
bls::PopSchemeMPL* schemePtr = (bls::PopSchemeMPL*)scheme;
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
const std::vector<bls::G1Element> vecPubKeys =
toBLSVector<bls::G1Element>(pks, pksLen);
return schemePtr->FastAggregateVerify(
vecPubKeys, bls::Bytes((uint8_t*)msg, msgLen), *sigPtr);
}
void PopSchemeMPLFree(PopSchemeMPL scheme)
{
bls::PopSchemeMPL* schemePtr = (bls::PopSchemeMPL*)scheme;
delete schemePtr;
}
// LegacySchemeMPL
LegacySchemeMPL NewLegacySchemeMPL() { return new bls::LegacySchemeMPL(); }
G2Element LegacySchemeMPLSign(
const LegacySchemeMPL scheme,
const PrivateKey sk,
const void* msg,
const size_t msgLen)
{
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)));
}
bool LegacySchemeMPLVerify(
const LegacySchemeMPL scheme,
const G1Element pk,
const void* msg,
const size_t msgLen,
const G2Element sig)
{
bls::LegacySchemeMPL* schemePtr = (bls::LegacySchemeMPL*)scheme;
const bls::G1Element* pkPtr = (bls::G1Element*)pk;
const uint8_t* msgPtr = (uint8_t*)msg;
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
return schemePtr->Verify(*pkPtr, bls::Bytes(msgPtr, msgLen), *sigPtr);
}
bool LegacySchemeMPLVerifySecure(
const LegacySchemeMPL scheme,
void** pks,
const size_t pksLen,
const G2Element sig,
const void* msg,
const size_t msgLen)
{
bls::LegacySchemeMPL* schemePtr = (bls::LegacySchemeMPL*)scheme;
const std::vector<bls::G1Element> vecPubKeys =
toBLSVector<bls::G1Element>(pks, pksLen);
const uint8_t* msgPtr = (uint8_t*)msg;
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
// Because of scheme pointer it will call CoreMPL::VerifySecure with 'legacy' flag variant
return schemePtr->VerifySecure(
vecPubKeys, *sigPtr, bls::Bytes(msgPtr, msgLen));
}
bool LegacySchemeMPLAggregateVerify(
const LegacySchemeMPL scheme,
void** pks,
const size_t pksLen,
void** msgs,
const void* msgsLens,
const size_t msgsLen,
const G2Element sig)
{
bls::LegacySchemeMPL* schemePtr = (bls::LegacySchemeMPL*)scheme;
const size_t* msgLensPtr = (size_t*)msgsLens;
const bls::G2Element* sigPtr = (bls::G2Element*)sig;
const std::vector<bls::G1Element> vecPubKeys =
toBLSVector<bls::G1Element>(pks, pksLen);
const std::vector<size_t> vecMsgsLens =
std::vector<size_t>(msgLensPtr, msgLensPtr + msgsLen);
const std::vector<bls::Bytes> vecMsgs =
toVectorBytes(msgs, msgsLen, vecMsgsLens);
return schemePtr->AggregateVerify(vecPubKeys, vecMsgs, *sigPtr);
}
void LegacySchemeMPLFree(LegacySchemeMPL scheme)
{
bls::LegacySchemeMPL* schemePtr = (bls::LegacySchemeMPL*)scheme;
delete schemePtr;
}

View File

@ -0,0 +1,184 @@
// Copyright (c) 2021 The Dash Core developers
// 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 SCHEMES_H_
#define SCHEMES_H_
#include <stdbool.h>
#include <stdlib.h>
#include "elements.h"
#include "privatekey.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void* CoreMPL;
typedef CoreMPL BasicSchemeMPL;
typedef CoreMPL AugSchemeMPL;
typedef CoreMPL PopSchemeMPL;
typedef CoreMPL LegacySchemeMPL;
// CoreMPL
PrivateKey CoreMPLKeyGen(
const CoreMPL scheme,
const void* seed,
const size_t seedLen,
bool* didErr);
G1Element CoreMPLSkToG1(const CoreMPL scheme, const PrivateKey sk);
G2Element CoreMPLSign(
const CoreMPL scheme,
const PrivateKey sk,
const void* msg,
const size_t msgLen);
bool CoreMPLVerify(
const BasicSchemeMPL scheme,
const G1Element pk,
const void* msg,
const size_t msgLen,
const G2Element sig);
bool CoreMPLVerifySecure(
const CoreMPL scheme,
void** pks,
const size_t pksLen,
const G2Element sig,
const void* msg,
const size_t msgLen);
G1Element CoreMPLAggregatePubKeys(
const CoreMPL scheme,
void** pubKeys,
const size_t pkLen);
G2Element CoreMPLAggregateSigs(
const CoreMPL scheme,
void** sigs,
const size_t sigLen);
PrivateKey CoreMPLDeriveChildSk(
const CoreMPL scheme,
const PrivateKey sk,
const uint32_t index);
PrivateKey CoreMPLDeriveChildSkUnhardened(
const CoreMPL scheme,
const PrivateKey sk,
const uint32_t index);
G1Element CoreMPLDeriveChildPkUnhardened(
const CoreMPL scheme,
const G1Element sk,
const uint32_t index);
bool CoreMPLAggregateVerify(
const CoreMPL scheme,
void** pks,
const size_t pkLen,
void** msgs,
const void* msgLens,
const size_t msgLen,
const G2Element sig);
// BasicSchemeMPL
BasicSchemeMPL NewBasicSchemeMPL();
bool BasicSchemeMPLAggregateVerify(
BasicSchemeMPL scheme,
void** pks,
const size_t pksLen,
void** msgs,
const void* msgsLens,
const size_t msgsLen,
const G2Element sig);
void BasicSchemeMPLFree(BasicSchemeMPL scheme);
// AugSchemeMPL
AugSchemeMPL NewAugSchemeMPL();
G2Element AugSchemeMPLSign(
const AugSchemeMPL scheme,
const PrivateKey sk,
const void* msg,
const size_t msgLen);
G2Element AugSchemeMPLSignPrepend(
const AugSchemeMPL scheme,
const PrivateKey sk,
const void* msg,
const size_t msgLen,
const G1Element prepPk);
bool AugSchemeMPLVerify(
const AugSchemeMPL scheme,
const G1Element pk,
const void* msg,
const size_t msgLen,
const G2Element sig);
bool AugSchemeMPLAggregateVerify(
const AugSchemeMPL scheme,
void** pks,
const size_t pksLen,
void** msgs,
const void* msgsLens,
const size_t msgsLen,
const G2Element sig);
void AugSchemeMPLFree(AugSchemeMPL scheme);
// PopSchemeMPL
PopSchemeMPL NewPopSchemeMPL();
G2Element PopSchemeMPLPopProve(
const PopSchemeMPL scheme,
const PrivateKey sk);
bool PopSchemeMPLPopVerify(
const PopSchemeMPL scheme,
const G1Element pk,
const G2Element sig);
bool PopSchemeMPLFastAggregateVerify(
const PopSchemeMPL scheme,
void** pks,
const size_t pksLen,
const void* msgs,
const size_t msgsLen,
const G2Element sig);
void PopSchemeMPLFree(PopSchemeMPL scheme);
// LegacySchemeMPL
LegacySchemeMPL NewLegacySchemeMPL();
G2Element LegacySchemeMPLSign(
const LegacySchemeMPL scheme,
const PrivateKey sk,
const void* msg,
const size_t msgLen);
G2Element LegacySchemeMPLSignPrepend(
const LegacySchemeMPL scheme,
const PrivateKey sk,
const void* msg,
const size_t msgLen,
const G1Element prepPk);
bool LegacySchemeMPLVerify(
const LegacySchemeMPL scheme,
const G1Element pk,
const void* msg,
const size_t msgLen,
const G2Element sig);
bool LegacySchemeMPLVerifySecure(
const LegacySchemeMPL scheme,
void** pks,
const size_t pksLen,
const G2Element sig,
const void* msg,
const size_t msgLen);
bool LegacySchemeMPLAggregateVerify(
const LegacySchemeMPL scheme,
void** pks,
const size_t pksLen,
void** msgs,
const void* msgsLens,
const size_t msgsLen,
const G2Element sig);
void LegacySchemeMPLFree(LegacySchemeMPL scheme);
#ifdef __cplusplus
}
#endif
#endif // SCHEMES_H_

View File

@ -0,0 +1,168 @@
// Copyright (c) 2021 The Dash Core developers
// 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 <vector>
#include <stdint.h>
#include "bls.hpp"
#include "privatekey.h"
#include "elements.h"
#include "blschia.h"
#include "threshold.h"
#include "utils.hpp"
#include "error.h"
std::vector<bls::Bytes> toVectorHashes(void** elems, const size_t len) {
std::vector<bls::Bytes> vec;
vec.reserve(len);
for (int i = 0 ; i < len; ++i) {
vec.push_back(
bls::Bytes((uint8_t*)elems[i], HashSize)
);
}
return vec;
}
PrivateKey ThresholdPrivateKeyShare(void** sks, const size_t sksLen, const void* hash, bool* didErr) {
bls::PrivateKey* sk = nullptr;
try {
sk = new bls::PrivateKey(
bls::Threshold::PrivateKeyShare(
toBLSVector<bls::PrivateKey>(sks, sksLen),
bls::Bytes((uint8_t*)hash, HashSize)
)
);
} catch(const std::exception& ex) {
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
*didErr = false;
return sk;
}
PrivateKey ThresholdPrivateKeyRecover(void** sks,
const size_t sksLen,
void** hashes,
const size_t hashesLen,
bool* didErr) {
bls::PrivateKey* sk = nullptr;
std::vector<bls::Bytes> pop = toVectorHashes(hashes, hashesLen);
try {
sk = new bls::PrivateKey(
bls::Threshold::PrivateKeyRecover(
toBLSVector<bls::PrivateKey>(sks, sksLen),
toVectorHashes(hashes, hashesLen)
)
);
} catch(const std::exception& ex) {
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
*didErr = false;
return sk;
}
G1Element ThresholdPublicKeyShare(void** pks, const size_t pksLen, const void* hash, bool* didErr) {
bls::G1Element* el = nullptr;
try {
el = new bls::G1Element(
bls::Threshold::PublicKeyShare(
toBLSVector<bls::G1Element>(pks, pksLen),
bls::Bytes((uint8_t*)hash, HashSize)
)
);
} catch(const std::exception& ex) {
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
*didErr = false;
return el;
}
G1Element ThresholdPublicKeyRecover(void** pks,
const size_t pksLen,
void** hashes,
const size_t hashesLen,
bool* didErr) {
bls::G1Element* el = nullptr;
try {
el = new bls::G1Element(
bls::Threshold::PublicKeyRecover(
toBLSVector<bls::G1Element>(pks, pksLen),
toVectorHashes(hashes, hashesLen)
)
);
} catch(const std::exception& ex) {
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
*didErr = false;
return el;
}
G2Element ThresholdSignatureShare(void** sigs, const size_t sigsLen, const void* hash, bool* didErr) {
bls::G2Element* el = nullptr;
try {
el = new bls::G2Element(
bls::Threshold::SignatureShare(
toBLSVector<bls::G2Element>(sigs, sigsLen),
bls::Bytes((uint8_t*)hash, HashSize)
)
);
} catch(const std::exception& ex) {
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
*didErr = false;
return el;
}
G2Element ThresholdSignatureRecover(void** sigs,
const size_t sigsLen,
void** hashes,
const size_t hashesLen,
bool* didErr) {
bls::G2Element* el = nullptr;
try {
el = new bls::G2Element(
bls::Threshold::SignatureRecover(
toBLSVector<bls::G2Element>(sigs, sigsLen),
toVectorHashes(hashes, hashesLen)
)
);
} catch(const std::exception& ex) {
gErrMsg = ex.what();
*didErr = true;
return nullptr;
}
*didErr = false;
return el;
}
G2Element ThresholdSign(const PrivateKey sk, const void* hash) {
bls::PrivateKey* skPtr = (bls::PrivateKey*)sk;
return new bls::G2Element(
bls::Threshold::Sign(*skPtr, bls::Bytes((uint8_t*)hash, HashSize))
);
}
bool ThresholdVerify(const G1Element pk, const void* hash, const G2Element sig) {
bls::G1Element* pkPtr = (bls::G1Element*)pk;
bls::G2Element* sigPtr = (bls::G2Element*)sig;
return bls::Threshold::Verify(*pkPtr, bls::Bytes((uint8_t*)hash, HashSize), *sigPtr);
}

View File

@ -0,0 +1,55 @@
// Copyright (c) 2021 The Dash Core developers
// 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 THRESHOLD_H_
#define THRESHOLD_H_
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include "privatekey.h"
#include "elements.h"
#ifdef __cplusplus
extern "C" {
#endif
const int HashSize = 32;
PrivateKey ThresholdPrivateKeyShare(void** sks, const size_t sksLen, const void* hash, bool* didErr);
PrivateKey ThresholdPrivateKeyRecover(void** sks,
const size_t sksLen,
void** hashes,
const size_t hashesLen,
bool* didErr);
G1Element ThresholdPublicKeyShare(void** pks, const size_t pksLen, const void* hash, bool* didErr);
G1Element ThresholdPublicKeyRecover(void** pks,
const size_t pksLen,
void** hashes,
const size_t hashesLen,
bool* didErr);
G2Element ThresholdSignatureShare(void** sigs, const size_t sigsLen, const void* hash, bool* didErr);
G2Element ThresholdSignatureRecover(void** sigs,
const size_t sigsLen,
void** hashes,
const size_t hashesLen,
bool* didErr);
G2Element ThresholdSign(const PrivateKey sk, const void* hash);
bool ThresholdVerify(const G1Element pk, const void* hash, const G2Element sig);
#ifdef __cplusplus
}
#endif
#endif // THRESHOLD_H_

View File

@ -0,0 +1,40 @@
// Copyright (c) 2021 The Dash Core developers
// 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 <vector>
#include "bls.hpp"
#include "privatekey.h"
#include "elements.h"
// helper functions
template <class T>
std::vector<T> toBLSVector(void** elems, const size_t len) {
std::vector<T> vec;
vec.reserve(len);
for (int i = 0 ; i < len; ++i) {
T* el = (T*)elems[i];
vec.push_back(*el);
}
return vec;
}
std::vector<bls::Bytes> toVectorBytes(void** elems, const size_t len, const std::vector<size_t> vecElemsLens) {
std::vector<bls::Bytes> vec;
vec.reserve(len);
for (int i = 0 ; i < len; ++i) {
uint8_t* elPtr = (uint8_t*)elems[i];
vec.push_back(bls::Bytes(elPtr, vecElemsLens[i]));
}
return vec;
}

View File

@ -0,0 +1,34 @@
// Copyright (c) 2021 The Dash Core developers
// 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.
#pragma once
#include <vector>
#include "bls.hpp"
#include "privatekey.h"
#include "elements.h"
// helper functions
template <class T>
std::vector<T> toBLSVector(void** elems, const size_t len) {
std::vector<T> vec;
vec.reserve(len);
for (int i = 0 ; i < (int)len; ++i) {
const T* el = (T*)elems[i];
vec.push_back(*el);
}
return vec;
}
std::vector<bls::Bytes> toVectorBytes(void** elems, const size_t len, const std::vector<size_t> vecElemsLens);

View File

@ -0,0 +1,8 @@
#include "c-bindings/blschia.h"
#include "c-bindings/elements.h"
#include "c-bindings/privatekey.h"
#include "c-bindings/schemes.h"
#include "c-bindings/threshold.h"
#include "c-bindings/bip32/chaincode.h"
#include "c-bindings/bip32/extendedprivatekey.h"
#include "c-bindings/bip32/extendedpublickey.h"

View File

@ -0,0 +1,6 @@
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
// include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
include!("../bindings.rs");

View File

@ -0,0 +1,79 @@
use bls_dash_sys as sys;
#[test]
fn sign_and_verify() {
let seed = b"seedweedseedweedseedweedseedweed";
let bad_seed = b"weedseedweedseedweedseedweedseed";
unsafe {
let scheme = sys::NewAugSchemeMPL();
let mut did_err = false;
let sk = sys::CoreMPLKeyGen(
scheme,
seed.as_ptr() as *const _,
seed.len(),
&mut did_err as *mut _,
);
assert!(!did_err);
let pk = sys::PrivateKeyGetG1Element(sk, &mut did_err as *mut _);
assert!(!did_err);
let sk2 = sys::CoreMPLKeyGen(
scheme,
bad_seed.as_ptr() as *const _,
bad_seed.len(),
&mut did_err as *mut _,
);
assert!(!did_err);
let pk2 = sys::PrivateKeyGetG1Element(sk2, &mut did_err as *mut _);
assert!(!did_err);
let message = b"Evgeny owns 1337 dash no cap";
let sig = sys::CoreMPLSign(scheme, sk, message.as_ptr() as *const _, message.len());
let verify =
sys::CoreMPLVerify(scheme, pk, message.as_ptr() as *const _, message.len(), sig);
assert!(verify);
let verify_bad = sys::CoreMPLVerify(
scheme,
pk2,
message.as_ptr() as *const _,
message.len(),
sig,
);
assert!(!verify_bad);
sys::G2ElementFree(sig);
sys::G1ElementFree(pk2);
sys::PrivateKeyFree(sk2);
sys::G1ElementFree(pk);
sys::PrivateKeyFree(sk);
sys::AugSchemeMPLFree(scheme);
}
}
#[test]
fn test_private_key_from_bip32() {
use std::slice;
let long_seed: [u8; 32] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2];
let long_private_key_test_data: [u8; 32] = [50, 67, 148, 112, 207, 6, 210, 118, 137, 125, 27, 144, 105, 189, 214, 228, 68, 83, 144, 205, 80, 105, 133, 222, 14, 26, 28, 136, 167, 111, 241, 118];
let short_seed: [u8; 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let short_private_key_test_data: [u8; 32] = [70, 137, 28, 44, 236, 73, 89, 60, 129, 146, 30, 71, 61, 183, 72, 0, 41, 224, 252, 30, 185, 51, 198, 185, 61, 129, 245, 55, 14, 177, 159, 189];
unsafe {
let c_private_key = sys::PrivateKeyFromSeedBIP32(long_seed.as_ptr() as *const _, long_seed.len());
let serialized = sys::PrivateKeySerialize(c_private_key) as *const u8;
let data = slice::from_raw_parts(serialized, sys::PrivateKeySizeBytes());
assert_eq!(data, &long_private_key_test_data);
sys::PrivateKeyFree(c_private_key);
let c_private_key = sys::PrivateKeyFromSeedBIP32(short_seed.as_ptr() as *const _, short_seed.len());
let serialized = sys::PrivateKeySerialize(c_private_key) as *const u8;
let data = slice::from_raw_parts(serialized, sys::PrivateKeySizeBytes());
assert_eq!(data, &short_private_key_test_data);
sys::PrivateKeyFree(c_private_key);
}
}

View File

@ -0,0 +1,17 @@
unstable_features = true
blank_lines_lower_bound = 0
condense_wildcard_suffixes = true
error_on_line_overflow = true
error_on_unformatted = true
format_code_in_doc_comments = true
format_macro_matchers = true
format_strings = true
imports_granularity = "Crate"
normalize_comments = true
normalize_doc_attributes = true
reorder_impl_items = true
group_imports = "StdExternalCrate"
use_field_init_shorthand = true
use_try_shorthand = true
wrap_comments = true

View File

@ -0,0 +1,18 @@
[package]
name = "bls-signatures"
description = ""
version = "1.2.5"
edition = "2021"
[features]
legacy = []
bip32 = []
use_serde = ["serde"]
dash_helpers = ["rand"]
default = [ "legacy", "bip32", "dash_helpers", "use_serde"]
apple = ["bls-dash-sys/apple"]
[dependencies]
bls-dash-sys = { path = "../bls-dash-sys" }
serde = { version= "1.0.160", features = ["derive"], optional = true}
rand = { version= "0.8.5", optional = true}

View File

@ -0,0 +1,33 @@
use std::ffi::c_void;
use bls_dash_sys::{BIP32ChainCodeFree, BIP32ChainCodeIsEqual, BIP32ChainCodeSerialize};
pub const BIP32_CHAIN_CODE_SIZE: usize = 32;
#[derive(Debug)]
pub struct ChainCode {
pub(crate) c_chain_code: *mut c_void,
}
impl ChainCode {
pub fn serialize(&self) -> Box<[u8; BIP32_CHAIN_CODE_SIZE]> {
unsafe {
let malloc_ptr = BIP32ChainCodeSerialize(self.c_chain_code);
Box::from_raw(malloc_ptr as *mut _)
}
}
}
impl PartialEq for ChainCode {
fn eq(&self, other: &Self) -> bool {
unsafe { BIP32ChainCodeIsEqual(self.c_chain_code, other.c_chain_code) }
}
}
impl Eq for ChainCode {}
impl Drop for ChainCode {
fn drop(&mut self) {
unsafe { BIP32ChainCodeFree(self.c_chain_code) }
}
}

View File

@ -0,0 +1,7 @@
mod chain_code;
mod private_key;
mod public_key;
pub use chain_code::*;
pub use private_key::*;
pub use public_key::*;

View File

@ -0,0 +1,205 @@
use std::ffi::c_void;
use bls_dash_sys::{
BIP32ExtendedPrivateKeyFree, BIP32ExtendedPrivateKeyFromBytes, BIP32ExtendedPrivateKeyFromSeed,
BIP32ExtendedPrivateKeyGetChainCode, BIP32ExtendedPrivateKeyGetExtendedPublicKey,
BIP32ExtendedPrivateKeyGetPrivateKey, BIP32ExtendedPrivateKeyGetPublicKey,
BIP32ExtendedPrivateKeyIsEqual, BIP32ExtendedPrivateKeyPrivateChild,
BIP32ExtendedPrivateKeyPublicChild, BIP32ExtendedPrivateKeySerialize,
};
use crate::{
bip32::{chain_code::ChainCode, ExtendedPublicKey},
utils::{c_err_to_result, SecureBox},
BlsError, G1Element, PrivateKey,
};
pub const BIP32_EXTENDED_PRIVATE_KEY_SIZE: usize = 77;
#[derive(Debug)]
pub struct ExtendedPrivateKey {
c_extended_private_key: *mut c_void,
}
impl PartialEq for ExtendedPrivateKey {
fn eq(&self, other: &Self) -> bool {
unsafe {
BIP32ExtendedPrivateKeyIsEqual(
self.c_extended_private_key,
other.c_extended_private_key,
)
}
}
}
impl Eq for ExtendedPrivateKey {}
impl ExtendedPrivateKey {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, BlsError> {
if bytes.len() != BIP32_EXTENDED_PRIVATE_KEY_SIZE {
return Err(BlsError {
msg: format!(
"Extended Private Key size must be {}, got {}",
BIP32_EXTENDED_PRIVATE_KEY_SIZE,
bytes.len()
),
});
}
Ok(ExtendedPrivateKey {
c_extended_private_key: c_err_to_result(|did_err| unsafe {
BIP32ExtendedPrivateKeyFromBytes(bytes.as_ptr() as *const _, did_err)
})?,
})
}
pub fn from_seed(bytes: &[u8]) -> Result<Self, BlsError> {
Ok(ExtendedPrivateKey {
c_extended_private_key: c_err_to_result(|did_err| unsafe {
BIP32ExtendedPrivateKeyFromSeed(bytes.as_ptr() as *const _, bytes.len(), did_err)
})?,
})
}
pub(crate) fn private_child_with_legacy_flag(&self, index: u32, legacy: bool) -> Self {
ExtendedPrivateKey {
c_extended_private_key: unsafe {
BIP32ExtendedPrivateKeyPrivateChild(self.c_extended_private_key, index, legacy)
},
}
}
pub fn private_child(&self, index: u32) -> Self {
self.private_child_with_legacy_flag(index, false)
}
pub fn public_child(&self, index: u32) -> ExtendedPublicKey {
ExtendedPublicKey {
c_extended_public_key: unsafe {
BIP32ExtendedPrivateKeyPublicChild(self.c_extended_private_key, index)
},
}
}
pub(crate) fn extended_public_key_with_legacy_flag(
&self,
legacy: bool,
) -> Result<ExtendedPublicKey, BlsError> {
Ok(ExtendedPublicKey {
c_extended_public_key: c_err_to_result(|did_err| unsafe {
BIP32ExtendedPrivateKeyGetExtendedPublicKey(
self.c_extended_private_key,
legacy,
did_err,
)
})?,
})
}
pub fn extended_public_key(&self) -> Result<ExtendedPublicKey, BlsError> {
self.extended_public_key_with_legacy_flag(false)
}
pub fn public_key(&self) -> Result<G1Element, BlsError> {
Ok(G1Element {
c_element: c_err_to_result(|did_err| unsafe {
BIP32ExtendedPrivateKeyGetPublicKey(self.c_extended_private_key, did_err)
})?,
})
}
pub fn private_key(&self) -> PrivateKey {
PrivateKey {
c_private_key: unsafe {
BIP32ExtendedPrivateKeyGetPrivateKey(self.c_extended_private_key)
},
}
}
pub fn serialize(&self) -> SecureBox {
unsafe {
let secalloc_ptr = BIP32ExtendedPrivateKeySerialize(self.c_extended_private_key);
SecureBox::from_ptr(secalloc_ptr as *mut u8, BIP32_EXTENDED_PRIVATE_KEY_SIZE)
}
}
pub fn chain_code(&self) -> ChainCode {
ChainCode {
c_chain_code: unsafe {
BIP32ExtendedPrivateKeyGetChainCode(self.c_extended_private_key)
},
}
}
}
impl Drop for ExtendedPrivateKey {
fn drop(&mut self) {
unsafe { BIP32ExtendedPrivateKeyFree(self.c_extended_private_key) }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serialize_deserialize() {
let seed = b"seedweedseedweedseedweedseedweed";
let private_key =
ExtendedPrivateKey::from_seed(seed).expect("cannot generate extended private key");
let private_key_bytes = private_key.serialize();
let private_key_2 = ExtendedPrivateKey::from_bytes(private_key_bytes.as_ref())
.expect("cannot deserialize extended private key");
assert_eq!(private_key, private_key_2);
assert_eq!(private_key.private_key(), private_key_2.private_key());
assert_eq!(private_key.public_key(), private_key_2.public_key());
}
#[test]
fn hierarchical_deterministic_keys() {
let seed = b"seedweedseedweedseedweedseedweed";
let private_key =
ExtendedPrivateKey::from_seed(seed).expect("cannot generate extended private key");
let public_key = private_key
.extended_public_key()
.expect("cannot get extended public key");
let private_child = private_key.private_child(1337);
let private_grandchild = private_child.private_child(420);
let public_child = public_key.public_child(1337);
let public_grandchild = public_child.public_child(420);
assert_eq!(
public_grandchild,
private_grandchild
.extended_public_key()
.expect("cannot get extended public key")
);
}
#[test]
fn public_keys_match() {
let seed = b"seedweedseedweedseedweedseedweed";
let private_key =
ExtendedPrivateKey::from_seed(seed).expect("cannot generate extended private key");
let public_key = private_key
.extended_public_key()
.expect("cannot get extended public key");
assert_eq!(private_key.public_key(), Ok(public_key.public_key()));
}
#[test]
fn fingerprint_for_short_bip32_seed() {
assert_eq!(
ExtendedPrivateKey::from_seed(&[1u8, 50, 6, 244, 24, 199, 1, 25])
.expect("cannot generate extended private key")
.public_key()
.expect("cannot get public key from extended private key")
.fingerprint_legacy(),
0xa4700b27
);
}
}

View File

@ -0,0 +1,119 @@
use std::ffi::c_void;
use bls_dash_sys::{
BIP32ExtendedPublicKeyFree, BIP32ExtendedPublicKeyFromBytes,
BIP32ExtendedPublicKeyGetChainCode, BIP32ExtendedPublicKeyGetPublicKey,
BIP32ExtendedPublicKeyIsEqual, BIP32ExtendedPublicKeyPublicChild,
BIP32ExtendedPublicKeySerialize,
};
use crate::{bip32::chain_code::ChainCode, utils::c_err_to_result, BlsError, G1Element};
pub const BIP32_EXTENDED_PUBLIC_KEY_SIZE: usize = 93;
#[derive(Debug)]
pub struct ExtendedPublicKey {
pub(crate) c_extended_public_key: *mut c_void,
}
impl PartialEq for ExtendedPublicKey {
fn eq(&self, other: &Self) -> bool {
unsafe {
BIP32ExtendedPublicKeyIsEqual(self.c_extended_public_key, other.c_extended_public_key)
}
}
}
impl Eq for ExtendedPublicKey {}
impl ExtendedPublicKey {
pub(crate) fn from_bytes_with_legacy_flag(
bytes: &[u8],
legacy: bool,
) -> Result<Self, BlsError> {
if bytes.len() != BIP32_EXTENDED_PUBLIC_KEY_SIZE {
return Err(BlsError {
msg: format!(
"Extended Public Key size must be {}, got {}",
BIP32_EXTENDED_PUBLIC_KEY_SIZE,
bytes.len()
),
});
}
Ok(ExtendedPublicKey {
c_extended_public_key: c_err_to_result(|did_err| unsafe {
BIP32ExtendedPublicKeyFromBytes(bytes.as_ptr() as *const _, legacy, did_err)
})?,
})
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, BlsError> {
Self::from_bytes_with_legacy_flag(bytes, false)
}
pub(crate) fn public_child_with_legacy_flag(&self, index: u32, legacy: bool) -> Self {
ExtendedPublicKey {
c_extended_public_key: unsafe {
BIP32ExtendedPublicKeyPublicChild(self.c_extended_public_key, index, legacy)
},
}
}
pub fn public_child(&self, index: u32) -> Self {
self.public_child_with_legacy_flag(index, false)
}
pub(crate) fn serialize_with_legacy_flag(
&self,
legacy: bool,
) -> Box<[u8; BIP32_EXTENDED_PUBLIC_KEY_SIZE]> {
unsafe {
let malloc_ptr = BIP32ExtendedPublicKeySerialize(self.c_extended_public_key, legacy);
Box::from_raw(malloc_ptr as *mut _)
}
}
pub fn serialize(&self) -> Box<[u8; BIP32_EXTENDED_PUBLIC_KEY_SIZE]> {
self.serialize_with_legacy_flag(false)
}
pub fn chain_code(&self) -> ChainCode {
ChainCode {
c_chain_code: unsafe { BIP32ExtendedPublicKeyGetChainCode(self.c_extended_public_key) },
}
}
pub fn public_key(&self) -> G1Element {
G1Element {
c_element: unsafe { BIP32ExtendedPublicKeyGetPublicKey(self.c_extended_public_key) },
}
}
}
impl Drop for ExtendedPublicKey {
fn drop(&mut self) {
unsafe { BIP32ExtendedPublicKeyFree(self.c_extended_public_key) }
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::bip32::ExtendedPrivateKey;
#[test]
fn serialize_deserialize() {
let seed = b"seedweedseedweedseedweedseedweed";
let private_key =
ExtendedPrivateKey::from_seed(seed).expect("cannot generate extended private key");
let public_key = private_key
.extended_public_key()
.expect("cannot get extended public key");
let public_key_bytes = public_key.serialize();
let public_key_2 = ExtendedPublicKey::from_bytes(public_key_bytes.as_ref())
.expect("cannot deserialize extended public key");
assert_eq!(public_key, public_key_2);
}
}

View File

@ -0,0 +1,368 @@
use std::ffi::c_void;
use bls_dash_sys::{CoreMPLDeriveChildPkUnhardened, G1ElementFree, G1ElementFromBytes, G1ElementGenerator, G1ElementGetFingerprint, G1ElementIsEqual, G1ElementSerialize, G1ElementCopy, G2ElementCopy, G2ElementFree, G2ElementFromBytes, G2ElementIsEqual, G2ElementSerialize, ThresholdPublicKeyRecover, ThresholdSignatureRecover};
#[cfg(feature = "use_serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::{schemes::Scheme, utils::c_err_to_result, BlsError, BasicSchemeMPL};
// TODO Split into modules
pub const G1_ELEMENT_SIZE: usize = 48; // TODO somehow extract it from bls library
pub const G2_ELEMENT_SIZE: usize = 96; // TODO somehow extract it from bls library
#[cfg(feature = "dash_helpers")]
pub type PublicKey = G1Element;
#[cfg(feature = "dash_helpers")]
pub type Signature = G2Element;
#[derive(Debug)]
pub struct G1Element {
pub(crate) c_element: *mut c_void,
}
impl PartialEq for G1Element {
fn eq(&self, other: &Self) -> bool {
unsafe { G1ElementIsEqual(self.c_element, other.c_element) }
}
}
impl Eq for G1Element {}
impl G1Element {
pub fn generate() -> Self {
let c_element = unsafe { G1ElementGenerator() };
G1Element { c_element }
}
#[cfg(feature = "dash_helpers")]
pub fn verify(&self, signature: &G2Element, message: &[u8]) -> bool {
self.verify_basic(signature, message)
}
pub fn verify_basic(&self, signature: &G2Element, message: &[u8]) -> bool {
let basic_scheme = BasicSchemeMPL::new();
basic_scheme.verify(self, message, signature)
}
pub(crate) fn from_bytes_with_legacy_flag(
bytes: &[u8],
legacy: bool,
) -> Result<Self, BlsError> {
if bytes.len() != G1_ELEMENT_SIZE {
return Err(BlsError {
msg: format!(
"G1 Element size must be {}, got {}",
G1_ELEMENT_SIZE,
bytes.len()
),
});
}
Ok(G1Element {
c_element: c_err_to_result(|did_err| unsafe {
G1ElementFromBytes(bytes.as_ptr() as *const _, legacy, did_err)
})?,
})
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, BlsError> {
Self::from_bytes_with_legacy_flag(bytes, false)
}
pub(crate) fn to_bytes_with_legacy_flag(&self, legacy: bool) -> Box<[u8; G1_ELEMENT_SIZE]> {
unsafe {
let malloc_ptr = G1ElementSerialize(self.c_element, legacy);
Box::from_raw(malloc_ptr as *mut _)
}
}
pub fn to_bytes(&self) -> Box<[u8; G1_ELEMENT_SIZE]> {
self.to_bytes_with_legacy_flag(false)
}
pub fn derive_child_public_key_unhardened(
&self,
scheme: &impl Scheme,
index: u32,
) -> G1Element {
G1Element {
c_element: unsafe {
CoreMPLDeriveChildPkUnhardened(scheme.as_mut_ptr(), self.c_element, index)
},
}
}
pub(crate) fn fingerprint_with_legacy_flag(&self, legacy: bool) -> u32 {
unsafe { G1ElementGetFingerprint(self.c_element, legacy) }
}
pub fn fingerprint(&self) -> u32 {
self.fingerprint_with_legacy_flag(false)
}
pub fn threshold_recover(
bls_ids_with_elements: &[(Vec<u8>, G1Element)],
) -> Result<Self, BlsError> {
unsafe {
let len = bls_ids_with_elements.len();
let (c_hashes, c_elements): (Vec<_>, Vec<_>) = bls_ids_with_elements
.iter()
.map(|(hash, element)| {
(
hash.as_ptr() as *mut c_void,
element.c_element as *mut c_void,
)
})
.unzip();
let c_hashes_ptr = c_hashes.as_ptr() as *mut *mut c_void;
let c_elements_ptr = c_elements.as_ptr() as *mut *mut c_void;
Ok(G1Element {
c_element: c_err_to_result(|did_err| {
ThresholdPublicKeyRecover(c_elements_ptr, len, c_hashes_ptr, len, did_err)
})?,
})
}
}
}
impl Clone for G1Element {
fn clone(&self) -> Self {
unsafe {
G1Element{c_element: G1ElementCopy(self.c_element)}
}
}
}
#[cfg(feature = "use_serde")]
// Implement Serialize trait for G1Element
impl Serialize for G1Element {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let bytes = *self.to_bytes();
serializer.serialize_bytes(&bytes)
}
}
#[cfg(feature = "use_serde")]
// Implement Deserialize trait for G1Element
impl<'de> Deserialize<'de> for G1Element {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct G1ElementVisitor;
impl<'de> serde::de::Visitor<'de> for G1ElementVisitor {
type Value = G1Element;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a byte array representing a G1Element")
}
fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
G1Element::from_bytes(bytes).map_err(serde::de::Error::custom)
}
}
deserializer.deserialize_bytes(G1ElementVisitor)
}
}
impl Drop for G1Element {
fn drop(&mut self) {
unsafe { G1ElementFree(self.c_element) }
}
}
#[derive(Debug)]
pub struct G2Element {
pub(crate) c_element: *mut c_void,
}
impl PartialEq for G2Element {
fn eq(&self, other: &Self) -> bool {
unsafe { G2ElementIsEqual(self.c_element, other.c_element) }
}
}
impl Eq for G2Element {}
impl G2Element {
pub(crate) fn from_bytes_with_legacy_flag(
bytes: &[u8],
legacy: bool,
) -> Result<Self, BlsError> {
if bytes.len() != G2_ELEMENT_SIZE {
return Err(BlsError {
msg: format!(
"G2 Element size must be {}, got {}",
G2_ELEMENT_SIZE,
bytes.len()
),
});
}
Ok(G2Element {
c_element: c_err_to_result(|did_err| unsafe {
G2ElementFromBytes(bytes.as_ptr() as *const _, legacy, did_err)
})?,
})
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, BlsError> {
Self::from_bytes_with_legacy_flag(bytes, false)
}
pub(crate) fn to_bytes_with_legacy_flag(&self, legacy: bool) -> Box<[u8; G2_ELEMENT_SIZE]> {
unsafe {
let malloc_ptr = G2ElementSerialize(self.c_element, legacy);
Box::from_raw(malloc_ptr as *mut _)
}
}
pub fn to_bytes(&self) -> Box<[u8; G2_ELEMENT_SIZE]> {
self.to_bytes_with_legacy_flag(false)
}
pub fn threshold_recover(
bls_ids_with_elements: &[(Vec<u8>, G2Element)],
) -> Result<Self, BlsError> {
unsafe {
let len = bls_ids_with_elements.len();
let (c_hashes, c_elements): (Vec<_>, Vec<_>) = bls_ids_with_elements
.iter()
.map(|(hash, element)| {
(
hash.as_ptr() as *mut c_void,
element.c_element as *mut c_void,
)
})
.unzip();
let c_hashes_ptr = c_hashes.as_ptr() as *mut *mut c_void;
let c_elements_ptr = c_elements.as_ptr() as *mut *mut c_void;
Ok(G2Element {
c_element: c_err_to_result(|did_err| {
ThresholdSignatureRecover(c_elements_ptr, len, c_hashes_ptr, len, did_err)
})?,
})
}
}
}
impl Clone for G2Element {
fn clone(&self) -> Self {
unsafe {
G2Element{c_element: G2ElementCopy(self.c_element)}
}
}
}
#[cfg(feature = "use_serde")]
// Implement Serialize trait for G1Element
impl Serialize for G2Element {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let bytes = *self.to_bytes();
serializer.serialize_bytes(&bytes)
}
}
#[cfg(feature = "use_serde")]
// Implement Deserialize trait for G1Element
impl<'de> Deserialize<'de> for G2Element {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct G2ElementVisitor;
impl<'de> serde::de::Visitor<'de> for G2ElementVisitor {
type Value = G2Element;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a byte array representing a G2Element")
}
fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
G2Element::from_bytes(bytes).map_err(serde::de::Error::custom)
}
}
deserializer.deserialize_bytes(G2ElementVisitor)
}
}
impl Drop for G2Element {
fn drop(&mut self) {
unsafe { G2ElementFree(self.c_element) }
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
schemes::{AugSchemeMPL, Scheme},
PrivateKey,
};
#[test]
fn g1_serialize_deserialize() {
let seed = b"seedweedseedweedseedweedseedweed";
let scheme = AugSchemeMPL::new();
let sk = PrivateKey::key_gen(&scheme, seed).expect("unable to generate private key");
let g1 = sk.g1_element().expect("cannot get G1 element");
let g1_bytes = g1.to_bytes();
let g1_2 =
G1Element::from_bytes(g1_bytes.as_ref()).expect("cannot build G1 element from bytes");
assert_eq!(g1, g1_2);
}
#[test]
fn g2_serialize_deserialize() {
let seed = b"seedweedseedweedseedweedseedweed";
let scheme = AugSchemeMPL::new();
let sk = PrivateKey::key_gen(&scheme, seed).expect("unable to generate private key");
let g2 = scheme.sign(&sk, b"ayy");
let g2_bytes = g2.to_bytes();
let g2_2 =
G2Element::from_bytes(g2_bytes.as_ref()).expect("cannot build G2 element from bytes");
assert_eq!(g2, g2_2);
}
#[test]
fn should_generate_new_g1_element() {
let g1_element = G1Element::generate();
assert_eq!(g1_element.to_bytes().len(), 48);
}
#[test]
fn should_return_fingerprint() {
let bytes = [
151, 241, 211, 167, 49, 151, 215, 148, 38, 149, 99, 140, 79, 169, 172, 15, 195, 104,
140, 79, 151, 116, 185, 5, 161, 78, 58, 63, 23, 27, 172, 88, 108, 85, 232, 63, 249,
122, 26, 239, 251, 58, 240, 10, 219, 34, 198, 187,
];
let g1_element =
G1Element::from_bytes(&bytes).expect("should create g1 element from bytes");
assert_eq!(g1_element.fingerprint(), 2093959050);
}
}

View File

@ -0,0 +1,2 @@
mod private_key;
mod public_key;

View File

@ -0,0 +1,58 @@
use crate::{
bip32::{ExtendedPrivateKey, ExtendedPublicKey},
BlsError,
};
impl ExtendedPrivateKey {
pub fn private_child_legacy(&self, index: u32) -> Self {
self.private_child_with_legacy_flag(index, true)
}
pub fn extended_public_key_legacy(&self) -> Result<ExtendedPublicKey, BlsError> {
self.extended_public_key_with_legacy_flag(true)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serialize_deserialize_legacy() {
let seed = b"seedweedseedweedseedweedseedweed";
let private_key =
ExtendedPrivateKey::from_seed(seed).expect("cannot generate extended private key");
let public_key = private_key
.extended_public_key_legacy()
.expect("cannot get extended public key");
let public_key_bytes = public_key.serialize_legacy();
let public_key_2 = ExtendedPublicKey::from_bytes_legacy(public_key_bytes.as_ref())
.expect("cannot deserialize extended public key");
assert_eq!(public_key, public_key_2);
}
#[test]
fn hierarchical_deterministic_keys_legacy() {
let seed = b"seedweedseedweedseedweedseedweed";
let private_key =
ExtendedPrivateKey::from_seed(seed).expect("cannot generate extended private key");
let public_key = private_key
.extended_public_key_legacy()
.expect("cannot get extended public key");
let private_child = private_key.private_child_legacy(1337);
let private_grandchild = private_child.private_child_legacy(420);
let public_child = public_key.public_child_legacy(1337);
let public_grandchild = public_child.public_child_legacy(420);
assert_eq!(
public_grandchild,
private_grandchild
.extended_public_key_legacy()
.expect("cannot get extended public key")
);
}
}

View File

@ -0,0 +1,40 @@
use crate::{
bip32::{ExtendedPublicKey, BIP32_EXTENDED_PUBLIC_KEY_SIZE},
BlsError,
};
impl ExtendedPublicKey {
pub fn from_bytes_legacy(bytes: &[u8]) -> Result<Self, BlsError> {
Self::from_bytes_with_legacy_flag(bytes, true)
}
pub fn public_child_legacy(&self, index: u32) -> Self {
self.public_child_with_legacy_flag(index, true)
}
pub fn serialize_legacy(&self) -> Box<[u8; BIP32_EXTENDED_PUBLIC_KEY_SIZE]> {
self.serialize_with_legacy_flag(true)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::bip32::ExtendedPrivateKey;
#[test]
fn serialize_deserialize_legacy() {
let seed = b"seedweedseedweedseedweedseedweed";
let private_key =
ExtendedPrivateKey::from_seed(seed).expect("cannot generate extended private key");
let public_key = private_key
.extended_public_key_legacy()
.expect("cannot get extended public key");
let public_key_bytes = public_key.serialize_legacy();
let public_key_2 = ExtendedPublicKey::from_bytes_legacy(public_key_bytes.as_ref())
.expect("cannot deserialize extended public key");
assert_eq!(public_key, public_key_2);
}
}

View File

@ -0,0 +1,25 @@
use crate::{BlsError, G1Element, G2Element, G1_ELEMENT_SIZE, G2_ELEMENT_SIZE};
impl G1Element {
pub fn serialize_legacy(&self) -> Box<[u8; G1_ELEMENT_SIZE]> {
self.to_bytes_with_legacy_flag(true)
}
pub fn from_bytes_legacy(bytes: &[u8]) -> Result<Self, BlsError> {
Self::from_bytes_with_legacy_flag(bytes, true)
}
pub fn fingerprint_legacy(&self) -> u32 {
self.fingerprint_with_legacy_flag(true)
}
}
impl G2Element {
pub fn from_bytes_legacy(bytes: &[u8]) -> Result<Self, BlsError> {
Self::from_bytes_with_legacy_flag(bytes, true)
}
pub fn serialize_legacy(&self) -> Box<[u8; G2_ELEMENT_SIZE]> {
self.to_bytes_with_legacy_flag(true)
}
}

View File

@ -0,0 +1,2 @@
mod bip32;
mod elements;

View File

@ -0,0 +1,104 @@
mod elements;
mod private_key;
mod schemes;
mod utils;
#[cfg(feature = "legacy")]
mod legacy;
#[cfg(feature = "bip32")]
pub mod bip32;
use std::{error::Error, fmt::Display};
pub use elements::{G1Element, G2Element, G1_ELEMENT_SIZE, G2_ELEMENT_SIZE};
#[cfg(feature = "dash_helpers")]
pub use elements::{PublicKey, Signature};
pub use private_key::{PrivateKey, PRIVATE_KEY_SIZE};
pub use schemes::{AugSchemeMPL, BasicSchemeMPL, LegacySchemeMPL, Scheme};
#[derive(Debug, PartialEq)]
pub struct BlsError {
// Need to use owned version as each time BLS has an error its binding glue overwrites error
// message variable.
msg: String,
}
impl Display for BlsError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.msg)
}
}
impl Error for BlsError {}
#[cfg(test)]
mod tests {
use super::*;
use crate::schemes::{AugSchemeMPL, Scheme};
#[test]
fn basic_sign() {
let seed = b"seedweedseedweedseedweedseedweed";
let bad_seed = b"weedseedweedseedweedseedweedseed";
let scheme = AugSchemeMPL::new();
let private_key_before =
PrivateKey::key_gen(&scheme, seed).expect("unable to generate private key");
// Also test private key serialization
let private_key_bytes = private_key_before.to_bytes();
let private_key = PrivateKey::from_bytes(private_key_bytes.as_slice(), false)
.expect("cannot build private key from bytes");
drop(private_key_bytes);
let public_key = private_key.g1_element().expect("unable to get public key");
let private_key_bad =
PrivateKey::key_gen(&scheme, bad_seed).expect("unable to generate private key");
let public_key_bad = private_key_bad
.g1_element()
.expect("unable to get public key");
let message = b"Evgeny owns 1337 dash no cap";
let signature = scheme.sign(&private_key, message);
let verify = scheme.verify(&public_key, message, &signature);
assert!(verify);
let verify_bad = scheme.verify(&public_key_bad, message, &signature);
assert!(!verify_bad);
}
#[test]
fn bad_seed() {
let seed = b"lol";
let scheme = AugSchemeMPL::new();
let private_key = PrivateKey::key_gen(&scheme, seed);
assert!(matches!(
private_key,
Err(BlsError { msg }) if msg == "Seed size must be at least 32 bytes"
));
}
#[test]
fn hd_keys_deterministic() {
let seed = b"seedweedseedweedseedweedseedweed";
let scheme = AugSchemeMPL::new();
let master_sk = PrivateKey::key_gen(&scheme, seed).expect("unable to generate private key");
let master_pk = master_sk.g1_element().expect("unable to get public key");
let child_sk_u = master_sk.derive_child_private_key_unhardened(&scheme, 22);
let grandchild_sk_u = child_sk_u.derive_child_private_key_unhardened(&scheme, 0);
let child_pk_u = master_pk.derive_child_public_key_unhardened(&scheme, 22);
let grandchild_pk_u = child_pk_u.derive_child_public_key_unhardened(&scheme, 0);
assert_eq!(
grandchild_pk_u,
grandchild_sk_u.g1_element().expect("cannot get public key")
);
}
}

View File

@ -0,0 +1,315 @@
use std::{ffi::c_void, ops::Mul};
use bls_dash_sys::{
CoreMPLDeriveChildSk, CoreMPLDeriveChildSkUnhardened, CoreMPLKeyGen, G1ElementMul,
PrivateKeyFree, PrivateKeyFromBytes, PrivateKeyFromSeedBIP32, PrivateKeyGetG1Element,
PrivateKeyIsEqual, PrivateKeySerialize, ThresholdPrivateKeyRecover,
};
use rand::{prelude::StdRng, Rng};
#[cfg(feature = "use_serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::{schemes::Scheme, utils::{c_err_to_result, SecureBox}, BasicSchemeMPL, BlsError, G1Element, G2Element};
pub const PRIVATE_KEY_SIZE: usize = 32; // TODO somehow extract it from bls library
#[derive(Debug)]
pub struct PrivateKey {
pub(crate) c_private_key: *mut c_void,
}
impl PartialEq for PrivateKey {
fn eq(&self, other: &Self) -> bool {
unsafe { PrivateKeyIsEqual(self.c_private_key, other.c_private_key) }
}
}
impl Eq for PrivateKey {}
impl Mul<G1Element> for PrivateKey {
type Output = Result<G1Element, BlsError>;
fn mul(self, rhs: G1Element) -> Self::Output {
Ok(G1Element {
c_element: c_err_to_result(|_| unsafe {
G1ElementMul(rhs.c_element, self.c_private_key)
})?,
})
}
}
impl Mul<PrivateKey> for G1Element {
type Output = Result<G1Element, BlsError>;
fn mul(self, rhs: PrivateKey) -> Self::Output {
rhs * self
}
}
impl PrivateKey {
pub(crate) fn as_mut_ptr(&self) -> *mut c_void {
self.c_private_key
}
// TODO Rename to from_seed
pub fn key_gen(scheme: &impl Scheme, seed: &[u8]) -> Result<Self, BlsError> {
Ok(PrivateKey {
c_private_key: c_err_to_result(|did_err| unsafe {
CoreMPLKeyGen(
scheme.as_mut_ptr(),
seed.as_ptr() as *const _,
seed.len(),
did_err,
)
})?,
})
}
#[cfg(feature = "dash_helpers")]
pub fn generate_dash(rng: &mut StdRng) -> Result<Self, BlsError> {
let seed = rng.gen::<[u8; 32]>();
let scheme = BasicSchemeMPL::new();
Ok(PrivateKey {
c_private_key: c_err_to_result(|did_err| unsafe {
CoreMPLKeyGen(
scheme.as_mut_ptr(),
seed.as_ptr() as *const _,
seed.len(),
did_err,
)
})?,
})
}
#[cfg(feature = "dash_helpers")]
pub fn sign(&self, message: &[u8]) -> G2Element {
self.sign_basic(message)
}
pub fn sign_basic(&self, message: &[u8]) -> G2Element {
let scheme = BasicSchemeMPL::new();
scheme.sign(self, message)
}
#[cfg(feature = "dash_helpers")]
pub fn generate_dash_many(count: usize, rng: &mut StdRng) -> Result<Vec<Self>, BlsError> {
(0..count)
.into_iter()
.map(|_| Self::generate_dash(rng))
.collect()
}
pub fn g1_element(&self) -> Result<G1Element, BlsError> {
Ok(G1Element {
c_element: c_err_to_result(|did_err| unsafe {
PrivateKeyGetG1Element(self.c_private_key, did_err)
})?,
})
}
pub fn to_bytes(&self) -> SecureBox {
// `PrivateKeySerialize` internally securely allocates memory which we have to
// wrap safely
unsafe {
SecureBox::from_ptr(
PrivateKeySerialize(self.c_private_key) as *mut u8,
PRIVATE_KEY_SIZE,
)
}
}
pub fn from_bytes(bytes: &[u8], mod_order: bool) -> Result<Self, BlsError> {
if bytes.len() != PRIVATE_KEY_SIZE {
return Err(BlsError {
msg: format!(
"Private key size must be {}, got {}",
PRIVATE_KEY_SIZE,
bytes.len()
),
});
}
let c_private_key = c_err_to_result(|did_err| unsafe {
PrivateKeyFromBytes(bytes.as_ptr() as *const c_void, mod_order, did_err)
})?;
Ok(PrivateKey { c_private_key })
}
pub fn from_bip32_seed(bytes: &[u8]) -> Self {
let c_private_key =
unsafe { PrivateKeyFromSeedBIP32(bytes.as_ptr() as *const c_void, bytes.len()) };
PrivateKey { c_private_key }
}
pub fn derive_child_private_key(&self, scheme: &impl Scheme, index: u32) -> PrivateKey {
PrivateKey {
c_private_key: unsafe {
CoreMPLDeriveChildSk(scheme.as_mut_ptr(), self.c_private_key, index)
},
}
}
pub fn derive_child_private_key_unhardened(
&self,
scheme: &impl Scheme,
index: u32,
) -> PrivateKey {
PrivateKey {
c_private_key: unsafe {
CoreMPLDeriveChildSkUnhardened(scheme.as_mut_ptr(), self.c_private_key, index)
},
}
}
pub fn threshold_recover(
bls_ids_with_private_keys: &[(Vec<u8>, PrivateKey)],
) -> Result<Self, BlsError> {
unsafe {
let len = bls_ids_with_private_keys.len();
let (c_hashes, c_elements): (Vec<_>, Vec<_>) = bls_ids_with_private_keys
.iter()
.map(|(hash, element)| (hash.as_ptr() as *mut c_void, element.c_private_key))
.unzip();
let c_hashes_ptr = c_hashes.as_ptr() as *mut *mut c_void;
let c_elements_ptr = c_elements.as_ptr() as *mut *mut c_void;
Ok(PrivateKey {
c_private_key: c_err_to_result(|did_err| {
ThresholdPrivateKeyRecover(c_elements_ptr, len, c_hashes_ptr, len, did_err)
})?,
})
}
}
}
impl Clone for PrivateKey {
fn clone(&self) -> Self {
// Serialize the element
let bytes = self.to_bytes();
// We can panic
PrivateKey::from_bytes(bytes.as_slice(), false).expect("expected bytes to be valid")
}
}
#[cfg(feature = "use_serde")]
// Implement Serialize trait for G1Element
impl Serialize for PrivateKey {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bytes(self.to_bytes().as_slice())
}
}
#[cfg(feature = "use_serde")]
// Implement Deserialize trait for G1Element
impl<'de> Deserialize<'de> for PrivateKey {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct PrivateKeyElementVisitor;
impl<'de> serde::de::Visitor<'de> for PrivateKeyElementVisitor {
type Value = PrivateKey;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a byte array representing a Private Key")
}
fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
PrivateKey::from_bytes(bytes, false).map_err(serde::de::Error::custom)
}
}
deserializer.deserialize_bytes(PrivateKeyElementVisitor)
}
}
impl Drop for PrivateKey {
fn drop(&mut self) {
unsafe { PrivateKeyFree(self.c_private_key) }
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::schemes::AugSchemeMPL;
#[test]
fn serialize_deserialize() {
let seed = b"seedweedseedweedseedweedseedweed";
let scheme = AugSchemeMPL::new();
let sk1 = PrivateKey::key_gen(&scheme, seed).expect("unable to generate private key");
let sk1_bytes = sk1.to_bytes();
let sk2 = PrivateKey::from_bytes(sk1_bytes.as_slice(), false)
.expect("cannot build private key from bytes");
assert_eq!(sk1, sk2);
}
#[test]
fn should_return_private_key_from_bip32_bytes() {
let long_seed = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8,
9, 10, 1, 2,
];
let long_private_key_test_data = [
50, 67, 148, 112, 207, 6, 210, 118, 137, 125, 27, 144, 105, 189, 214, 228, 68, 83, 144,
205, 80, 105, 133, 222, 14, 26, 28, 136, 167, 111, 241, 118,
];
let long_private_key = PrivateKey::from_bip32_seed(&long_seed);
assert_eq!(*long_private_key.to_bytes(), long_private_key_test_data);
// Previously didn't work with seed with length != 32
let short_seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let short_private_key_test_data = [
70, 137, 28, 44, 236, 73, 89, 60, 129, 146, 30, 71, 61, 183, 72, 0, 41, 224, 252, 30,
185, 51, 198, 185, 61, 129, 245, 55, 14, 177, 159, 189,
];
let short_private_key = PrivateKey::from_bip32_seed(&short_seed);
assert_eq!(*short_private_key.to_bytes(), short_private_key_test_data);
}
#[test]
fn test_keys_multiplication() {
// 46891c2cec49593c81921e473db7480029e0fc1eb933c6b93d81f5370eb19fbd
let private_key_data = [
70, 137, 28, 44, 236, 73, 89, 60, 129, 146, 30, 71, 61, 183, 72, 0, 41, 224, 252, 30,
185, 51, 198, 185, 61, 129, 245, 55, 14, 177, 159, 189,
];
// 0e2f9055c17eb13221d8b41833468ab49f7d4e874ddf4b217f5126392a608fd48ccab3510548f1da4f397c1ad4f8e01a
let public_key_data = [
14, 47, 144, 85, 193, 126, 177, 50, 33, 216, 180, 24, 51, 70, 138, 180, 159, 125, 78,
135, 77, 223, 75, 33, 127, 81, 38, 57, 42, 96, 143, 212, 140, 202, 179, 81, 5, 72, 241,
218, 79, 57, 124, 26, 212, 248, 224, 26,
];
// 03fd387c4d4c66ec9dcdb31ef0c08ad881090dcda13d4b2c9cbc5ef264ff4dc7
let expected_data = [
3, 253, 56, 124, 77, 76, 102, 236, 157, 205, 179, 30, 240, 192, 138, 216, 129, 9, 13,
205, 161, 61, 75, 44, 156, 188, 94, 242, 100, 255, 77, 199,
];
let private_key = PrivateKey::from_bytes(&private_key_data, false).unwrap();
let public_key = G1Element::from_bytes_legacy(&public_key_data).unwrap();
let result = (private_key * public_key).unwrap();
assert_eq!(
&result.serialize_legacy()[..32],
&expected_data,
"should match"
);
let private_key = PrivateKey::from_bytes(&private_key_data, false).unwrap();
let public_key = G1Element::from_bytes_legacy(&public_key_data).unwrap();
let result = (public_key * private_key).unwrap();
assert_eq!(
&result.serialize_legacy()[..32],
&expected_data,
"should match"
);
}
}

View File

@ -0,0 +1,434 @@
use std::ffi::c_void;
use bls_dash_sys::{
AugSchemeMPLAggregateVerify, AugSchemeMPLFree, AugSchemeMPLSign, AugSchemeMPLVerify,
BasicSchemeMPLAggregateVerify, BasicSchemeMPLFree, CoreMPLAggregatePubKeys,
CoreMPLAggregateSigs, CoreMPLSign, CoreMPLVerify, CoreMPLVerifySecure,
LegacySchemeMPLAggregateVerify, LegacySchemeMPLSign, LegacySchemeMPLVerify,
LegacySchemeMPLVerifySecure, NewAugSchemeMPL, NewBasicSchemeMPL, NewLegacySchemeMPL,
};
// TODO Split into modules
use crate::{private_key::PrivateKey, G1Element, G2Element};
pub trait Scheme {
fn as_mut_ptr(&self) -> *mut c_void;
fn sign(&self, private_key: &PrivateKey, message: &[u8]) -> G2Element;
fn verify(&self, public_key: &G1Element, message: &[u8], signature: &G2Element) -> bool;
fn verify_secure<'a>(
&self,
public_keys: impl IntoIterator<Item = &'a G1Element>,
message: &[u8],
signature: &G2Element,
) -> bool {
let mut g1_pointers = public_keys
.into_iter()
.map(|g1| g1.c_element)
.collect::<Vec<_>>();
unsafe {
CoreMPLVerifySecure(
self.as_mut_ptr(),
g1_pointers.as_mut_ptr(),
g1_pointers.len(),
signature.c_element,
message.as_ptr() as *const _,
message.len(),
)
}
}
fn aggregate_public_keys<'a>(
&self,
public_keys: impl IntoIterator<Item = &'a G1Element>,
) -> G1Element {
let mut g1_pointers = public_keys
.into_iter()
.map(|g1| g1.c_element)
.collect::<Vec<_>>();
G1Element {
c_element: unsafe {
CoreMPLAggregatePubKeys(
self.as_mut_ptr(),
g1_pointers.as_mut_ptr(),
g1_pointers.len(),
)
},
}
}
fn aggregate_sigs<'a>(&self, sigs: impl IntoIterator<Item = &'a G2Element>) -> G2Element {
let mut g2_pointers = sigs.into_iter().map(|g2| g2.c_element).collect::<Vec<_>>();
G2Element {
c_element: unsafe {
CoreMPLAggregateSigs(
self.as_mut_ptr(),
g2_pointers.as_mut_ptr(),
g2_pointers.len(),
)
},
}
}
fn aggregate_verify<'a>(
&self,
public_keys: impl IntoIterator<Item = &'a G1Element>,
messages: impl IntoIterator<Item = &'a [u8]>,
signature: &G2Element,
) -> bool;
}
struct AggregateVerifyArgs {
g1_pointers: Vec<*mut c_void>,
messages_pointers: Vec<*const u8>,
messages_lengths: Vec<usize>,
}
// TODO put constructor inside struct?
fn prepare_aggregate_verify_args<'a>(
public_keys: impl IntoIterator<Item = &'a G1Element>,
messages: impl IntoIterator<Item = &'a [u8]>,
) -> AggregateVerifyArgs {
let g1_pointers = public_keys
.into_iter()
.map(|g1| g1.c_element)
.collect::<Vec<_>>();
let mut messages_pointers = Vec::new();
let mut messages_lengths = Vec::new();
for m in messages.into_iter() {
messages_pointers.push(m.as_ptr());
messages_lengths.push(m.len());
}
AggregateVerifyArgs {
g1_pointers,
messages_pointers,
messages_lengths,
}
}
pub struct BasicSchemeMPL {
scheme: *mut c_void,
}
impl BasicSchemeMPL {
pub fn new() -> Self {
BasicSchemeMPL {
scheme: unsafe { NewBasicSchemeMPL() },
}
}
}
impl Scheme for BasicSchemeMPL {
fn as_mut_ptr(&self) -> *mut c_void {
self.scheme
}
fn sign(&self, private_key: &PrivateKey, message: &[u8]) -> G2Element {
G2Element {
c_element: unsafe {
CoreMPLSign(
self.scheme,
private_key.as_mut_ptr(),
message.as_ptr() as *const _,
message.len(),
)
},
}
}
fn verify(&self, public_key: &G1Element, message: &[u8], signature: &G2Element) -> bool {
unsafe {
CoreMPLVerify(
self.scheme,
public_key.c_element,
message.as_ptr() as *const _,
message.len(),
signature.c_element,
)
}
}
fn aggregate_verify<'a>(
&self,
public_keys: impl IntoIterator<Item = &'a G1Element>,
messages: impl IntoIterator<Item = &'a [u8]>,
signature: &G2Element,
) -> bool {
let AggregateVerifyArgs {
mut g1_pointers,
mut messages_pointers,
messages_lengths: mut messages_lengthes,
} = prepare_aggregate_verify_args(public_keys, messages);
unsafe {
BasicSchemeMPLAggregateVerify(
self.as_mut_ptr(),
g1_pointers.as_mut_ptr(),
g1_pointers.len(),
messages_pointers.as_mut_ptr() as *mut _,
messages_lengthes.as_mut_ptr() as *mut _,
messages_pointers.len(),
signature.c_element,
)
}
}
}
pub struct LegacySchemeMPL {
scheme: *mut c_void,
}
impl LegacySchemeMPL {
pub fn new() -> Self {
LegacySchemeMPL {
scheme: unsafe { NewLegacySchemeMPL() },
}
}
}
impl Scheme for LegacySchemeMPL {
fn as_mut_ptr(&self) -> *mut c_void {
self.scheme
}
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(),
)
},
}
}
fn verify(&self, public_key: &G1Element, message: &[u8], signature: &G2Element) -> bool {
unsafe {
LegacySchemeMPLVerify(
self.scheme,
public_key.c_element,
message.as_ptr() as *const _,
message.len(),
signature.c_element,
)
}
}
fn verify_secure<'a>(
&self,
public_keys: impl IntoIterator<Item = &'a G1Element>,
message: &[u8],
signature: &G2Element,
) -> bool {
let mut g1_pointers = public_keys
.into_iter()
.map(|g1| g1.c_element)
.collect::<Vec<_>>();
unsafe {
LegacySchemeMPLVerifySecure(
self.as_mut_ptr(),
g1_pointers.as_mut_ptr(),
g1_pointers.len(),
signature.c_element,
message.as_ptr() as *const _,
message.len(),
)
}
}
fn aggregate_verify<'a>(
&self,
public_keys: impl IntoIterator<Item = &'a G1Element>,
messages: impl IntoIterator<Item = &'a [u8]>,
signature: &G2Element,
) -> bool {
let AggregateVerifyArgs {
mut g1_pointers,
mut messages_pointers,
messages_lengths: mut messages_lengthes,
} = prepare_aggregate_verify_args(public_keys, messages);
unsafe {
LegacySchemeMPLAggregateVerify(
self.as_mut_ptr(),
g1_pointers.as_mut_ptr(),
g1_pointers.len(),
messages_pointers.as_mut_ptr() as *mut _,
messages_lengthes.as_mut_ptr() as *mut _,
messages_pointers.len(),
signature.c_element,
)
}
}
}
impl Drop for BasicSchemeMPL {
fn drop(&mut self) {
unsafe { BasicSchemeMPLFree(self.scheme) }
}
}
pub struct AugSchemeMPL {
scheme: *mut c_void,
}
impl AugSchemeMPL {
pub fn new() -> Self {
AugSchemeMPL {
scheme: unsafe { NewAugSchemeMPL() },
}
}
}
impl Scheme for AugSchemeMPL {
fn as_mut_ptr(&self) -> *mut c_void {
self.scheme
}
fn sign(&self, private_key: &PrivateKey, message: &[u8]) -> G2Element {
G2Element {
c_element: unsafe {
AugSchemeMPLSign(
self.scheme,
private_key.as_mut_ptr(),
message.as_ptr() as *const _,
message.len(),
)
},
}
}
fn verify(&self, public_key: &G1Element, message: &[u8], signature: &G2Element) -> bool {
unsafe {
AugSchemeMPLVerify(
self.scheme,
public_key.c_element,
message.as_ptr() as *const _,
message.len(),
signature.c_element,
)
}
}
fn aggregate_verify<'a>(
&self,
public_keys: impl IntoIterator<Item = &'a G1Element>,
messages: impl IntoIterator<Item = &'a [u8]>,
signature: &G2Element,
) -> bool {
let AggregateVerifyArgs {
mut g1_pointers,
mut messages_pointers,
mut messages_lengths,
} = prepare_aggregate_verify_args(public_keys, messages);
unsafe {
AugSchemeMPLAggregateVerify(
self.as_mut_ptr(),
g1_pointers.as_mut_ptr(),
g1_pointers.len(),
messages_pointers.as_mut_ptr() as *mut _,
messages_lengths.as_mut_ptr() as *mut _,
messages_pointers.len(),
signature.c_element,
)
}
}
}
impl Drop for AugSchemeMPL {
fn drop(&mut self) {
unsafe { AugSchemeMPLFree(self.scheme) }
}
}
#[cfg(test)]
mod tests {
use super::*;
fn verify_aggregate(scheme: impl Scheme) {
let seed1 = b"seedweedseedweedseedweedseedweed";
let seed2 = b"weedseedweedseedweedseedweedseed";
let seed3 = b"seedseedseedseedweedweedweedweed";
let seed4 = b"weedweedweedweedweedweedweedweed";
let private_key_1 =
PrivateKey::key_gen(&scheme, seed1).expect("unable to generate private key");
let private_key_2 =
PrivateKey::key_gen(&scheme, seed2).expect("unable to generate private key");
let private_key_3 =
PrivateKey::key_gen(&scheme, seed3).expect("unable to generate private key");
let private_key_4 =
PrivateKey::key_gen(&scheme, seed4).expect("unable to generate private key");
let public_key_1 = private_key_1
.g1_element()
.expect("unable to get public key");
let public_key_2 = private_key_2
.g1_element()
.expect("unable to get public key");
let public_key_3 = private_key_3
.g1_element()
.expect("unable to get public key");
let public_key_4 = private_key_4
.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";
let signature_1 = scheme.sign(&private_key_1, message_1);
let signature_2 = scheme.sign(&private_key_2, message_2);
let signature_3 = scheme.sign(&private_key_3, message_3);
let signature_4 = scheme.sign(&private_key_4, message_4);
let signature_agg = scheme.aggregate_sigs([&signature_1, &signature_2, &signature_3]);
let verify = scheme.aggregate_verify(
[&public_key_1, &public_key_2, &public_key_3],
[message_1.as_ref(), message_2.as_ref(), message_3.as_ref()],
&signature_agg,
);
assert!(verify);
// Arbitrary trees of aggregates
let signature_agg_final = scheme.aggregate_sigs([&signature_agg, &signature_4]);
let verify_final = scheme.aggregate_verify(
[&public_key_1, &public_key_2, &public_key_3, &public_key_4],
[
message_1.as_ref(),
message_2.as_ref(),
message_3.as_ref(),
message_4.as_ref(),
],
&signature_agg_final,
);
assert!(verify_final);
}
#[test]
fn verify_aggregate_aug() {
verify_aggregate(AugSchemeMPL::new());
}
#[test]
fn verify_aggregate_basic() {
verify_aggregate(BasicSchemeMPL::new());
}
#[test]
fn verify_aggregate_legacy() {
verify_aggregate(LegacySchemeMPL::new());
}
}

View File

@ -0,0 +1,71 @@
use core::slice;
use std::{
ffi::{c_void, CStr},
ops::Deref,
};
use bls_dash_sys::{GetLastErrorMsg, SecAllocBytes, SecFree};
use crate::BlsError;
pub(crate) fn c_err_to_result<T, F>(f: F) -> Result<T, BlsError>
where
F: FnOnce(&mut bool) -> T,
{
let mut did_error = false;
let result = f(&mut did_error);
if did_error {
let error_message = unsafe { CStr::from_ptr(GetLastErrorMsg()) };
Err(BlsError {
msg: String::from_utf8_lossy(error_message.to_bytes()).into_owned(),
})
} else {
Ok(result)
}
}
pub struct SecureBox {
c_sec_alloc: *mut u8,
len: usize,
}
impl SecureBox {
#[allow(dead_code)]
pub(crate) fn new(len: usize) -> Self {
SecureBox {
c_sec_alloc: unsafe { SecAllocBytes(len) },
len,
}
}
pub(crate) unsafe fn from_ptr(ptr: *mut u8, len: usize) -> Self {
SecureBox {
c_sec_alloc: ptr,
len,
}
}
// Somewhere it returns *mut c_void
pub(crate) fn as_mut_ptr(&mut self) -> *mut c_void {
self.c_sec_alloc as *mut c_void
}
pub fn as_slice(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self.c_sec_alloc, self.len) }
}
}
impl Deref for SecureBox {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl Drop for SecureBox {
fn drop(&mut self) {
unsafe { SecFree(self.as_mut_ptr()) }
}
}

View File

@ -0,0 +1,7 @@
[package]
name = "example"
version = "0.1.0"
edition = "2021"
[dependencies]
bls-signatures = { path = "../bls-signatures" }

View File

@ -0,0 +1,51 @@
use bls_signatures::{bip32::ExtendedPrivateKey, LegacySchemeMPL, Scheme};
const SEED: &'static [u8] = b"seedweedseedweedseedweedseedweed";
fn check_bip32_hd_keys() {
println!("Check BIP32 hierarchical deterministic keys work");
let private_key =
ExtendedPrivateKey::from_seed(SEED).expect("cannot generate extended private key");
let public_key = private_key
.extended_public_key()
.expect("cannot get extended public key");
let private_child = private_key.private_child(1337);
let private_grandchild = private_child.private_child(420);
let public_child = public_key.public_child(1337);
let public_grandchild = public_child.public_child(420);
assert_eq!(
public_grandchild,
private_grandchild
.extended_public_key()
.expect("cannot get extended public key")
);
}
fn check_bip32_legacy_scheme() {
println!("Check BIP32 signing works");
let private_key =
ExtendedPrivateKey::from_seed(SEED).expect("cannot generate extended private key");
let public_key = private_key
.extended_public_key()
.expect("cannot get extended public key");
let scheme = LegacySchemeMPL::new();
let message = b"dash is og";
let signature = scheme.sign(&private_key.private_key(), message);
assert!(scheme.verify(&public_key.public_key(), message, &signature));
}
fn main() {
println!("Run some checks to see if everything is linked up to original BLS library:");
check_bip32_hd_keys();
check_bip32_legacy_scheme();
println!("All checks passed!");
}

View File

@ -0,0 +1,41 @@
diff --git a/include/relic_err.h b/include/relic_err.h
index e16f71fe..a4adb107 100644
--- a/include/relic_err.h
+++ b/include/relic_err.h
@@ -33,7 +33,6 @@
#define RLC_ERR_H
#include <stdint.h>
-#include <setjmp.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -43,6 +42,10 @@
#include "relic_util.h"
#include "relic_label.h"
+#ifdef CHECK
+#include <setjmp.h>
+#endif
+
/*============================================================================*/
/* Constant definitions */
/*============================================================================*/
@@ -94,6 +97,8 @@ enum errors {
*/
typedef int err_t;
+#ifdef CHECK
+
/**
* Type that describes an error status, including the error code and the program
* location where the error occurred.
@@ -107,6 +112,8 @@ typedef struct _sts_t {
int block;
} sts_t;
+#endif
+
/*============================================================================*/
/* Macro definitions */
/*============================================================================*/

View File

@ -11,8 +11,7 @@ add_library(dashbls
${CMAKE_CURRENT_SOURCE_DIR}/extendedpublickey.cpp
${CMAKE_CURRENT_SOURCE_DIR}/legacy.cpp
${CMAKE_CURRENT_SOURCE_DIR}/schemes.cpp
${CMAKE_CURRENT_SOURCE_DIR}/threshold.cpp
)
${CMAKE_CURRENT_SOURCE_DIR}/threshold.cpp)
target_include_directories(dashbls
PUBLIC

View File

@ -98,6 +98,14 @@ G1Element G1Element::FromNative(const g1_t element)
return ele;
}
G1Element G1Element::Copy() {
G1Element ele;
g1_copy(ele.p, this->p);
return ele;
}
G1Element G1Element::FromMessage(const std::vector<uint8_t>& message,
const uint8_t* dst,
int dst_len)
@ -246,6 +254,7 @@ G2Element G2Element::FromBytesUnchecked(Bytes const bytes, const bool fLegacy)
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);
@ -358,6 +367,14 @@ void G2Element::ToNative(g2_t output) const {
g2_copy(output, (g2_st*)q);
}
G2Element G2Element::Copy() {
G2Element ele;
g2_copy(ele.q, this->q);
return ele;
}
G2Element G2Element::Negate() const
{
G2Element ans;

View File

@ -56,7 +56,7 @@ void TestHKDF(string ikm_hex, string salt_hex, string info_hex, string prk_expec
TEST_CASE("class PrivateKey") {
uint8_t buffer[PrivateKey::PRIVATE_KEY_SIZE];
memcmp(buffer, getRandomSeed().data(), 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();