diff --git a/.github/workflows/build-ton-linux-android-tonlib.yml b/.github/workflows/build-ton-linux-android-tonlib.yml index a1a6bc99d..b1ef52818 100644 --- a/.github/workflows/build-ton-linux-android-tonlib.yml +++ b/.github/workflows/build-ton-linux-android-tonlib.yml @@ -21,6 +21,8 @@ jobs: - name: Build TON run: | + git submodule sync --recursive + git submodule update cp assembly/android/build-android-tonlib.sh . chmod +x build-android-tonlib.sh ./build-android-tonlib.sh -a diff --git a/.github/workflows/build-ton-linux-x86-64-shared.yml b/.github/workflows/build-ton-linux-x86-64-shared.yml index e28ecc742..bf78f7df1 100644 --- a/.github/workflows/build-ton-linux-x86-64-shared.yml +++ b/.github/workflows/build-ton-linux-x86-64-shared.yml @@ -35,6 +35,8 @@ jobs: - name: Build TON run: | + git submodule sync --recursive + git submodule update cp assembly/native/build-ubuntu-shared.sh . chmod +x build-ubuntu-shared.sh ./build-ubuntu-shared.sh -t -a diff --git a/.github/workflows/build-ton-macos-15-arm64-shared.yml b/.github/workflows/build-ton-macos-15-arm64-shared.yml index 8379a0b04..00d8f6392 100644 --- a/.github/workflows/build-ton-macos-15-arm64-shared.yml +++ b/.github/workflows/build-ton-macos-15-arm64-shared.yml @@ -14,6 +14,8 @@ jobs: - name: Build TON run: | + git submodule sync --recursive + git submodule update cp assembly/native/build-macos-shared.sh . chmod +x build-macos-shared.sh ./build-macos-shared.sh -t -a diff --git a/.github/workflows/build-ton-macos-arm64-shared.yml b/.github/workflows/build-ton-macos-arm64-shared.yml index aadd23dd0..7481f9ff6 100644 --- a/.github/workflows/build-ton-macos-arm64-shared.yml +++ b/.github/workflows/build-ton-macos-arm64-shared.yml @@ -14,6 +14,8 @@ jobs: - name: Build TON run: | + git submodule sync --recursive + git submodule update cp assembly/native/build-macos-shared.sh . chmod +x build-macos-shared.sh ./build-macos-shared.sh -t -a diff --git a/.github/workflows/build-ton-macos-x86-64-shared.yml b/.github/workflows/build-ton-macos-x86-64-shared.yml index c9331e3be..6a69b2e35 100644 --- a/.github/workflows/build-ton-macos-x86-64-shared.yml +++ b/.github/workflows/build-ton-macos-x86-64-shared.yml @@ -4,7 +4,7 @@ on: [push,workflow_dispatch,workflow_call] jobs: build: - runs-on: macos-12 + runs-on: macos-13 steps: - name: Check out repository @@ -14,6 +14,8 @@ jobs: - name: Build TON run: | + git submodule sync --recursive + git submodule update cp assembly/native/build-macos-shared.sh . chmod +x build-macos-shared.sh ./build-macos-shared.sh -t -a @@ -21,5 +23,5 @@ jobs: - name: Upload artifacts uses: actions/upload-artifact@master with: - name: ton-binaries-macos-12 + name: ton-binaries-macos-13 path: artifacts diff --git a/.github/workflows/build-ton-wasm-emscripten.yml b/.github/workflows/build-ton-wasm-emscripten.yml index 534d312fd..66fe5e93f 100644 --- a/.github/workflows/build-ton-wasm-emscripten.yml +++ b/.github/workflows/build-ton-wasm-emscripten.yml @@ -15,10 +15,12 @@ jobs: - name: Install system libraries run: | sudo apt-get update - sudo apt-get install -y build-essential git openssl cmake ninja-build zlib1g-dev libssl-dev libsecp256k1-dev libmicrohttpd-dev libsodium-dev liblz4-dev + sudo apt-get install -y build-essential git openssl cmake ninja-build zlib1g-dev libssl-dev libsecp256k1-dev libmicrohttpd-dev libsodium-dev liblz4-dev libjemalloc-dev - name: Build TON WASM artifacts run: | + git submodule sync --recursive + git submodule update cp assembly/wasm/fift-func-wasm-build-ubuntu.sh . chmod +x fift-func-wasm-build-ubuntu.sh ./fift-func-wasm-build-ubuntu.sh -a diff --git a/.github/workflows/ton-arm64-macos.yml b/.github/workflows/ton-arm64-macos.yml index affe22456..f128680c2 100644 --- a/.github/workflows/ton-arm64-macos.yml +++ b/.github/workflows/ton-arm64-macos.yml @@ -18,6 +18,8 @@ jobs: - name: Build TON run: | + git submodule sync --recursive + git submodule update cp assembly/nix/build-macos-nix.sh . chmod +x build-macos-nix.sh ./build-macos-nix.sh -t diff --git a/.github/workflows/ton-x86-64-linux.yml b/.github/workflows/ton-x86-64-linux.yml index b7ef9684e..4cdafa114 100644 --- a/.github/workflows/ton-x86-64-linux.yml +++ b/.github/workflows/ton-x86-64-linux.yml @@ -22,6 +22,8 @@ jobs: - name: Build TON run: | + git submodule sync --recursive + git submodule update cp assembly/nix/build-linux-x86-64-nix.sh . chmod +x build-linux-x86-64-nix.sh ./build-linux-x86-64-nix.sh -t diff --git a/.github/workflows/ton-x86-64-macos.yml b/.github/workflows/ton-x86-64-macos.yml index 1890dc344..41b8fa239 100644 --- a/.github/workflows/ton-x86-64-macos.yml +++ b/.github/workflows/ton-x86-64-macos.yml @@ -4,7 +4,7 @@ on: [push,workflow_dispatch,workflow_call] jobs: build: - runs-on: macos-12 + runs-on: macos-13 steps: - uses: actions/checkout@v3 @@ -18,6 +18,8 @@ jobs: - name: Build TON run: | + git submodule sync --recursive + git submodule update cp assembly/nix/build-macos-nix.sh . chmod +x build-macos-nix.sh ./build-macos-nix.sh -t diff --git a/.github/workflows/ton-x86-64-windows.yml b/.github/workflows/ton-x86-64-windows.yml index d5c9c243c..c3c06f905 100644 --- a/.github/workflows/ton-x86-64-windows.yml +++ b/.github/workflows/ton-x86-64-windows.yml @@ -23,6 +23,8 @@ jobs: - name: Build TON run: | + git submodule sync --recursive + git submodule update copy assembly\native\build-windows-github-2019.bat . copy assembly\native\build-windows-2019.bat . build-windows-github-2019.bat Enterprise diff --git a/.gitignore b/.gitignore index 9b94834b8..e5bb366ce 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,6 @@ zlib/ libsodium/ libmicrohttpd-0.9.77-w32-bin/ readline-5.0-1-lib/ -secp256k1/ openssl-3.1.4/ libsodium-1.0.18-stable-msvc.zip libmicrohttpd-0.9.77-w32-bin.zip diff --git a/.gitmodules b/.gitmodules index f201ed73c..325e3f4e0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,7 @@ [submodule "third-party/blst"] path = third-party/blst url = https://github.com/supranational/blst.git +[submodule "third-party/secp256k1"] + path = third-party/secp256k1 + url = https://github.com/bitcoin-core/secp256k1 + branch = v0.3.2 diff --git a/CMake/BuildSECP256K1.cmake b/CMake/BuildSECP256K1.cmake new file mode 100644 index 000000000..ac70b2559 --- /dev/null +++ b/CMake/BuildSECP256K1.cmake @@ -0,0 +1,54 @@ +if (NOT SECP256K1_LIBRARY) + + set(SECP256K1_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third-party/secp256k1) + set(SECP256K1_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/third-party/secp256k1) + set(SECP256K1_INCLUDE_DIR ${SECP256K1_BINARY_DIR}/include) + + file(MAKE_DIRECTORY ${SECP256K1_BINARY_DIR}) + + if (MSVC) + set(SECP256K1_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third-party/secp256k1) + set(SECP256K1_LIBRARY ${SECP256K1_SOURCE_DIR}/build/src/Release/libsecp256k1.lib) + set(SECP256K1_INCLUDE_DIR ${SECP256K1_BINARY_DIR}/include) + add_custom_command( + WORKING_DIRECTORY ${SECP256K1_SOURCE_DIR} + COMMAND cmake -E env CFLAGS="/WX" cmake -A x64 -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_ENABLE_MODULE_EXTRAKEYS=ON -DSECP256K1_BUILD_EXAMPLES=OFF -DBUILD_SHARED_LIBS=OFF + COMMAND cmake --build build --config Release + COMMENT "Build Secp256k1" + DEPENDS ${SECP256K1_SOURCE_DIR} + OUTPUT ${SECP256K1_LIBRARY} + ) + elseif (EMSCRIPTEN) + set(SECP256K1_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third-party/secp256k1) + set(SECP256K1_LIBRARY ${SECP256K1_BINARY_DIR}/.libs/libsecp256k1.a) + set(SECP256K1_INCLUDE_DIR ${SECP256K1_SOURCE_DIR}/include) + add_custom_command( + WORKING_DIRECTORY ${SECP256K1_SOURCE_DIR} + COMMAND ./autogen.sh + COMMAND emconfigure ./configure --enable-module-recovery --enable-module-extrakeys --disable-tests --disable-benchmark + COMMAND emmake make clean + COMMAND emmake make + COMMENT "Build Secp256k1 with emscripten" + DEPENDS ${SECP256K1_SOURCE_DIR} + OUTPUT ${SECP256K1_LIBRARY} + ) + else() + if (NOT NIX) + set(SECP256K1_LIBRARY ${SECP256K1_BINARY_DIR}/lib/libsecp256k1.a) + add_custom_command( + WORKING_DIRECTORY ${SECP256K1_SOURCE_DIR} + COMMAND ./autogen.sh + COMMAND ./configure -q --disable-option-checking --enable-module-recovery --enable-module-extrakeys --prefix ${SECP256K1_BINARY_DIR} --with-pic --disable-shared --enable-static --disable-tests --disable-benchmark + COMMAND make -j16 + COMMAND make install + COMMENT "Build secp256k1" + DEPENDS ${SECP256K1_SOURCE_DIR} + OUTPUT ${SECP256K1_LIBRARY} + ) + endif() + endif() +else() + message(STATUS "Use Secp256k1: ${SECP256K1_LIBRARY}") +endif() + +add_custom_target(secp256k1 DEPENDS ${SECP256K1_LIBRARY}) diff --git a/CMake/FindSecp256k1.cmake b/CMake/FindSecp256k1.cmake index 68a37c71f..1f7767963 100644 --- a/CMake/FindSecp256k1.cmake +++ b/CMake/FindSecp256k1.cmake @@ -1,9 +1,8 @@ -# - Try to find SECP256K1 +# - Try to find Secp256k1 # Once done this will define # -# SECP256K1_FOUND - system has SECP256K1 -# SECP256K1_INCLUDE_DIR - the SECP256K1 include directory -# SECP256K1_LIBRARY - Link these to use SECP256K1 +# SECP256K1_INCLUDE_DIR - the Secp256k1 include directory +# SECP256K1_LIBRARY - Link these to use Secp256k1 if (NOT SECP256K1_LIBRARY) find_path( diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d5b8da5c..af2640367 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -183,6 +183,7 @@ message("Add ton") set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH}) include(BuildBLST) +include(BuildSECP256K1) # Configure CCache if available find_program(CCACHE_FOUND ccache) @@ -237,6 +238,11 @@ if (TON_USE_JEMALLOC) find_package(jemalloc REQUIRED) endif() +if (NIX) + find_package(Secp256k1 REQUIRED) +endif() + + set(MEMPROF "" CACHE STRING "Use one of \"ON\", \"FAST\" or \"SAFE\" to enable memory profiling. \ Works under macOS and Linux when compiled using glibc. \ In FAST mode stack is unwinded only using frame pointers, which may fail. \ diff --git a/Dockerfile b/Dockerfile index f4ea43759..1ba1460ee 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM ubuntu:22.04 AS builder RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential cmake clang openssl libssl-dev zlib1g-dev gperf wget git ninja-build libsecp256k1-dev libsodium-dev libmicrohttpd-dev liblz4-dev pkg-config autoconf automake libtool libjemalloc-dev lsb-release software-properties-common gnupg + DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential cmake clang openssl libssl-dev zlib1g-dev gperf wget git ninja-build libsodium-dev libmicrohttpd-dev liblz4-dev pkg-config autoconf automake libtool libjemalloc-dev lsb-release software-properties-common gnupg RUN wget https://apt.llvm.org/llvm.sh && \ chmod +x llvm.sh && \ @@ -24,7 +24,7 @@ RUN mkdir build && \ FROM ubuntu:22.04 RUN apt-get update && \ - apt-get install -y wget curl libatomic1 openssl libsecp256k1-dev libsodium-dev libmicrohttpd-dev liblz4-dev libjemalloc-dev htop net-tools netcat iptraf-ng jq tcpdump pv plzip && \ + apt-get install -y wget curl libatomic1 openssl libsodium-dev libmicrohttpd-dev liblz4-dev libjemalloc-dev htop net-tools netcat iptraf-ng jq tcpdump pv plzip && \ rm -rf /var/lib/apt/lists/* RUN mkdir -p /var/ton-work/db /var/ton-work/scripts /usr/share/ton/smartcont/ /usr/lib/fift/ diff --git a/assembly/android/build-android-tonlib.sh b/assembly/android/build-android-tonlib.sh index e470f6022..29dbffc88 100644 --- a/assembly/android/build-android-tonlib.sh +++ b/assembly/android/build-android-tonlib.sh @@ -8,14 +8,19 @@ while getopts 'a' flag; do esac done +export CC=$(which clang-16) +export CXX=$(which clang++-16) +export CCACHE_DISABLE=1 + if [ ! -d android-ndk-r25b ]; then rm android-ndk-r25b-linux.zip + echo "Downloading https://dl.google.com/android/repository/android-ndk-r25b-linux.zip" wget -q https://dl.google.com/android/repository/android-ndk-r25b-linux.zip unzip -q android-ndk-r25b-linux.zip test $? -eq 0 || { echo "Can't unzip android-ndk-r25b-linux.zip"; exit 1; } - echo Android NDK extracted + echo "Android NDK extracted" else - echo Using extracted Android NDK + echo "Using extracted Android NDK" fi export JAVA_AWT_LIBRARY=NotNeeded diff --git a/assembly/native/build-macos-portable.sh b/assembly/native/build-macos-portable.sh index 389608fbc..ee3d63d71 100644 --- a/assembly/native/build-macos-portable.sh +++ b/assembly/native/build-macos-portable.sh @@ -52,21 +52,6 @@ else echo "Using compiled lz4" fi -if [ ! -d "secp256k1" ]; then -git clone https://github.com/bitcoin-core/secp256k1.git -cd secp256k1 -secp256k1Path=`pwd` -git checkout v0.3.2 -./autogen.sh -./configure --enable-module-recovery --enable-static --disable-tests --disable-benchmark --with-pic -make -j12 -test $? -eq 0 || { echo "Can't compile secp256k1"; exit 1; } -cd .. -else - secp256k1Path=$(pwd)/secp256k1 - echo "Using compiled secp256k1" -fi - if [ ! -d "libsodium" ]; then export LIBSODIUM_FULL_BUILD=1 git clone https://github.com/jedisct1/libsodium.git @@ -135,9 +120,6 @@ cmake -GNinja .. \ -DZLIB_FOUND=1 \ -DZLIB_INCLUDE_DIR=$zlibPath \ -DZLIB_LIBRARIES=$zlibPath/libz.a \ --DSECP256K1_FOUND=1 \ --DSECP256K1_INCLUDE_DIR=$secp256k1Path/include \ --DSECP256K1_LIBRARY=$secp256k1Path/.libs/libsecp256k1.a \ -DSODIUM_FOUND=1 \ -DSODIUM_INCLUDE_DIR=$sodiumPath/src/libsodium/include \ -DSODIUM_LIBRARY_RELEASE=$sodiumPath/src/libsodium/.libs/libsodium.a \ diff --git a/assembly/native/build-macos-shared.sh b/assembly/native/build-macos-shared.sh index 96a925843..d3b699b15 100644 --- a/assembly/native/build-macos-shared.sh +++ b/assembly/native/build-macos-shared.sh @@ -36,21 +36,6 @@ else fi export CCACHE_DISABLE=1 -if [ ! -d "secp256k1" ]; then - git clone https://github.com/bitcoin-core/secp256k1.git - cd secp256k1 - secp256k1Path=`pwd` - git checkout v0.3.2 - ./autogen.sh - ./configure --enable-module-recovery --enable-static --disable-tests --disable-benchmark - make -j12 - test $? -eq 0 || { echo "Can't compile secp256k1"; exit 1; } - cd .. -else - secp256k1Path=$(pwd)/secp256k1 - echo "Using compiled secp256k1" -fi - if [ ! -d "lz4" ]; then git clone https://github.com/lz4/lz4 cd lz4 @@ -70,9 +55,6 @@ brew unlink openssl@3 && brew link --overwrite openssl@3 cmake -GNinja -DCMAKE_BUILD_TYPE=Release .. \ -DCMAKE_CXX_FLAGS="-stdlib=libc++" \ --DSECP256K1_FOUND=1 \ --DSECP256K1_INCLUDE_DIR=$secp256k1Path/include \ --DSECP256K1_LIBRARY=$secp256k1Path/.libs/libsecp256k1.a \ -DLZ4_FOUND=1 \ -DLZ4_LIBRARIES=$lz4Path/lib/liblz4.a \ -DLZ4_INCLUDE_DIRS=$lz4Path/lib diff --git a/assembly/native/build-ubuntu-portable.sh b/assembly/native/build-ubuntu-portable.sh index 6839094bd..0c9c91ec3 100644 --- a/assembly/native/build-ubuntu-portable.sh +++ b/assembly/native/build-ubuntu-portable.sh @@ -43,23 +43,6 @@ else echo "Using compiled lz4" fi -if [ ! -d "secp256k1" ]; then -git clone https://github.com/bitcoin-core/secp256k1.git -cd secp256k1 -secp256k1Path=`pwd` -git checkout v0.3.2 -./autogen.sh -./configure --enable-module-recovery --enable-static --disable-tests --disable-benchmark --with-pic -make -j12 -test $? -eq 0 || { echo "Can't compile secp256k1"; exit 1; } -cd .. -# ./.libs/libsecp256k1.a -# ./include -else - secp256k1Path=$(pwd)/secp256k1 - echo "Using compiled secp256k1" -fi - if [ ! -d "libsodium" ]; then export LIBSODIUM_FULL_BUILD=1 git clone https://github.com/jedisct1/libsodium.git @@ -126,9 +109,6 @@ cmake -GNinja .. \ -DZLIB_FOUND=1 \ -DZLIB_INCLUDE_DIR=$zlibPath \ -DZLIB_LIBRARIES=$zlibPath/libz.a \ --DSECP256K1_FOUND=1 \ --DSECP256K1_INCLUDE_DIR=$secp256k1Path/include \ --DSECP256K1_LIBRARY=$secp256k1Path/.libs/libsecp256k1.a \ -DSODIUM_FOUND=1 \ -DSODIUM_INCLUDE_DIR=$sodiumPath/src/libsodium/include \ -DSODIUM_LIBRARY_RELEASE=$sodiumPath/src/libsodium/.libs/libsodium.a \ diff --git a/assembly/native/build-windows-2019.bat b/assembly/native/build-windows-2019.bat index fdfb6bcf6..a34d19643 100644 --- a/assembly/native/build-windows-2019.bat +++ b/assembly/native/build-windows-2019.bat @@ -58,26 +58,6 @@ cd ..\..\..\.. echo Using lz4... ) -if not exist "secp256k1" ( -git clone https://github.com/bitcoin-core/secp256k1.git -cd secp256k1 -git checkout v0.3.2 -cmake -G "Visual Studio 16 2019" -A x64 -S . -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DBUILD_SHARED_LIBS=OFF -IF %errorlevel% NEQ 0 ( - echo Can't configure secp256k1 - exit /b %errorlevel% -) -cmake --build build --config Release -IF %errorlevel% NEQ 0 ( - echo Can't install secp256k1 - exit /b %errorlevel% -) -cd .. -) else ( -echo Using secp256k1... -) - - curl --retry 5 --retry-delay 10 -Lo libsodium-1.0.18-stable-msvc.zip https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable-msvc.zip IF %errorlevel% NEQ 0 ( echo Can't download libsodium @@ -131,9 +111,6 @@ cd build cmake -GNinja -DCMAKE_BUILD_TYPE=Release ^ -DPORTABLE=1 ^ -DSODIUM_USE_STATIC_LIBS=1 ^ --DSECP256K1_FOUND=1 ^ --DSECP256K1_INCLUDE_DIR=%root%\secp256k1\include ^ --DSECP256K1_LIBRARY=%root%\secp256k1\build\src\Release\libsecp256k1.lib ^ -DLZ4_FOUND=1 ^ -DLZ4_INCLUDE_DIRS=%root%\lz4\lib ^ -DLZ4_LIBRARIES=%root%\lz4\build\VS2017\liblz4\bin\x64_Release\liblz4_static.lib ^ diff --git a/assembly/native/build-windows.bat b/assembly/native/build-windows.bat index e1ce9e473..9f50d264c 100644 --- a/assembly/native/build-windows.bat +++ b/assembly/native/build-windows.bat @@ -26,6 +26,8 @@ IF %errorlevel% NEQ 0 ( exit /b %errorlevel% ) +rd /s /q ".\third-party\secp256k1\build" + if not exist "zlib" ( git clone https://github.com/madler/zlib.git cd zlib @@ -58,26 +60,6 @@ cd ..\..\..\.. echo Using lz4... ) -if not exist "secp256k1" ( -git clone https://github.com/bitcoin-core/secp256k1.git -cd secp256k1 -git checkout v0.3.2 -cmake -G "Visual Studio 17 2022" -A x64 -S . -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DBUILD_SHARED_LIBS=OFF -IF %errorlevel% NEQ 0 ( - echo Can't configure secp256k1 - exit /b %errorlevel% -) -cmake --build build --config Release -IF %errorlevel% NEQ 0 ( - echo Can't install secp256k1 - exit /b %errorlevel% -) -cd .. -) else ( -echo Using secp256k1... -) - - if not exist "libsodium" ( curl -Lo libsodium-1.0.18-stable-msvc.zip https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable-msvc.zip IF %errorlevel% NEQ 0 ( @@ -132,9 +114,6 @@ cd build cmake -GNinja -DCMAKE_BUILD_TYPE=Release ^ -DPORTABLE=1 ^ -DSODIUM_USE_STATIC_LIBS=1 ^ --DSECP256K1_FOUND=1 ^ --DSECP256K1_INCLUDE_DIR=%root%\secp256k1\include ^ --DSECP256K1_LIBRARY=%root%\secp256k1\build\src\Release\libsecp256k1.lib ^ -DLZ4_FOUND=1 ^ -DLZ4_INCLUDE_DIRS=%root%\lz4\lib ^ -DLZ4_LIBRARIES=%root%\lz4\build\VS2017\liblz4\bin\x64_Release\liblz4_static.lib ^ diff --git a/assembly/wasm/fift-func-wasm-build-ubuntu.sh b/assembly/wasm/fift-func-wasm-build-ubuntu.sh index 2d3507b23..8c0069f37 100644 --- a/assembly/wasm/fift-func-wasm-build-ubuntu.sh +++ b/assembly/wasm/fift-func-wasm-build-ubuntu.sh @@ -2,7 +2,7 @@ # sudo apt update # sudo apt install -y build-essential git make cmake ninja-build clang libgflags-dev zlib1g-dev libssl-dev \ # libreadline-dev libmicrohttpd-dev pkg-config libgsl-dev python3 python3-dev python3-pip \ -# nodejs libsecp256k1-dev libsodium-dev automake libtool +# nodejs libsodium-dev automake libtool libjemalloc-dev # wget https://apt.llvm.org/llvm.sh # chmod +x llvm.sh @@ -26,13 +26,14 @@ export CCACHE_DISABLE=1 echo `pwd` if [ "$scratch_new" = true ]; then - echo Compiling openssl zlib lz4 emsdk secp256k1 libsodium emsdk ton - rm -rf openssl zlib lz4 emsdk secp256k1 libsodium build + echo Compiling openssl zlib lz4 emsdk libsodium emsdk ton + rm -rf openssl zlib lz4 emsdk libsodium build openssl_em fi if [ ! -d "openssl" ]; then git clone https://github.com/openssl/openssl.git + cp -r openssl openssl_em cd openssl git checkout openssl-3.1.4 ./config @@ -47,21 +48,20 @@ fi if [ ! -d "build" ]; then mkdir build cd build - cmake -GNinja -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_CXX_STANDARD=17 \ - -DOPENSSL_FOUND=1 \ + cmake -GNinja -DTON_USE_JEMALLOC=ON .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DOPENSSL_ROOT_DIR=$OPENSSL_DIR \ -DOPENSSL_INCLUDE_DIR=$OPENSSL_DIR/include \ - -DOPENSSL_CRYPTO_LIBRARY=$OPENSSL_DIR/libcrypto.so \ - -DTON_USE_ABSEIL=OFF .. + -DOPENSSL_CRYPTO_LIBRARY=$OPENSSL_DIR/libcrypto.so test $? -eq 0 || { echo "Can't configure TON build"; exit 1; } ninja fift smc-envelope test $? -eq 0 || { echo "Can't compile fift "; exit 1; } - rm -rf * + rm -rf * .ninja* CMakeCache.txt cd .. else echo cleaning build... - rm -rf build/* + rm -rf build/* build/.ninja* build/CMakeCache.txt fi if [ ! -d "emsdk" ]; then @@ -71,8 +71,8 @@ echo fi cd emsdk -./emsdk install 3.1.19 -./emsdk activate 3.1.19 +./emsdk install 3.1.40 +./emsdk activate 3.1.40 EMSDK_DIR=`pwd` . $EMSDK_DIR/emsdk_env.sh @@ -82,9 +82,8 @@ export CCACHE_DISABLE=1 cd .. -if [ ! -f "openssl/openssl_em" ]; then - cd openssl - make clean +if [ ! -f "openssl_em/openssl_em" ]; then + cd openssl_em emconfigure ./Configure linux-generic32 no-shared no-dso no-engine no-unit-test no-tests no-fuzz-afl no-fuzz-libfuzzer sed -i 's/CROSS_COMPILE=.*/CROSS_COMPILE=/g' Makefile sed -i 's/-ldl//g' Makefile @@ -92,10 +91,12 @@ if [ ! -f "openssl/openssl_em" ]; then emmake make depend emmake make -j16 test $? -eq 0 || { echo "Can't compile OpenSSL with emmake "; exit 1; } + OPENSSL_DIR=`pwd` touch openssl_em cd .. else - echo Using compiled openssl with emscripten + OPENSSL_DIR=`pwd`/openssl_em + echo Using compiled with empscripten openssl at $OPENSSL_DIR fi if [ ! -d "zlib" ]; then @@ -125,21 +126,6 @@ else echo Using compiled lz4 with emscripten at $LZ4_DIR fi -if [ ! -d "secp256k1" ]; then - git clone https://github.com/bitcoin-core/secp256k1.git - cd secp256k1 - git checkout v0.3.2 - ./autogen.sh - SECP256K1_DIR=`pwd` - emconfigure ./configure --enable-module-recovery - emmake make -j16 - test $? -eq 0 || { echo "Can't compile secp256k1 with emmake "; exit 1; } - cd .. -else - SECP256K1_DIR=`pwd`/secp256k1 - echo Using compiled secp256k1 with emscripten at $SECP256K1_DIR -fi - if [ ! -d "libsodium" ]; then git clone https://github.com/jedisct1/libsodium cd libsodium @@ -168,9 +154,9 @@ emcmake cmake -DUSE_EMSCRIPTEN=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_VERBOSE_MAK -DOPENSSL_CRYPTO_LIBRARY=$OPENSSL_DIR/libcrypto.a \ -DCMAKE_TOOLCHAIN_FILE=$EMSDK_DIR/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \ -DCMAKE_CXX_FLAGS="-sUSE_ZLIB=1" \ --DSECP256K1_INCLUDE_DIR=$SECP256K1_DIR/include \ --DSECP256K1_LIBRARY=$SECP256K1_DIR/.libs/libsecp256k1.a \ +-DSODIUM_FOUND=1 \ -DSODIUM_INCLUDE_DIR=$SODIUM_DIR/src/libsodium/include \ +-DSODIUM_USE_STATIC_LIBS=1 \ -DSODIUM_LIBRARY_RELEASE=$SODIUM_DIR/src/libsodium/.libs/libsodium.a \ .. @@ -194,5 +180,3 @@ if [ "$with_artifacts" = true ]; then cp -R crypto/smartcont artifacts cp -R crypto/fift/lib artifacts fi - - diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt index c2a737149..069083381 100644 --- a/crypto/CMakeLists.txt +++ b/crypto/CMakeLists.txt @@ -318,20 +318,20 @@ endif() target_include_directories(ton_crypto SYSTEM PUBLIC $) add_dependencies(ton_crypto blst) +add_dependencies(ton_crypto_core secp256k1) + target_include_directories(ton_crypto PRIVATE ${BLST_INCLUDE_DIR}) target_link_libraries(ton_crypto PRIVATE ${BLST_LIB}) -if (NOT USE_EMSCRIPTEN) - find_package(Secp256k1 REQUIRED) -endif() +target_include_directories(ton_crypto_core PUBLIC $) if (MSVC) find_package(Sodium REQUIRED) target_compile_definitions(ton_crypto PUBLIC SODIUM_STATIC) - target_include_directories(ton_crypto_core PUBLIC $) + target_link_libraries(ton_crypto_core PUBLIC ${SECP256K1_LIBRARY}) target_link_libraries(ton_crypto PUBLIC ${SECP256K1_LIBRARY}) -elseif (ANDROID OR EMSCRIPTEN) - target_include_directories(ton_crypto_core PUBLIC $) +elseif (EMSCRIPTEN) + target_link_libraries(ton_crypto_core PUBLIC $) target_link_libraries(ton_crypto PUBLIC $) else() if (NOT SODIUM_FOUND) @@ -340,11 +340,10 @@ else() message(STATUS "Using Sodium ${SODIUM_LIBRARY_RELEASE}") endif() target_compile_definitions(ton_crypto PUBLIC SODIUM_STATIC) - target_include_directories(ton_crypto_core PUBLIC $) + target_link_libraries(ton_crypto_core PUBLIC ${SECP256K1_LIBRARY}) target_link_libraries(ton_crypto PUBLIC ${SECP256K1_LIBRARY}) endif() -target_link_libraries(ton_crypto_core PUBLIC ${SECP256K1_LIBRARY}) target_include_directories(ton_crypto_core PUBLIC $) target_link_libraries(ton_crypto PUBLIC ${SODIUM_LIBRARY_RELEASE}) diff --git a/crypto/ellcurve/secp256k1.cpp b/crypto/ellcurve/secp256k1.cpp index e890117a4..b98eea7be 100644 --- a/crypto/ellcurve/secp256k1.cpp +++ b/crypto/ellcurve/secp256k1.cpp @@ -17,13 +17,22 @@ #include "secp256k1.h" #include "td/utils/check.h" +#include "td/utils/logging.h" + #include +#include #include -namespace td { +namespace td::secp256k1 { -bool ecrecover(const unsigned char* hash, const unsigned char* signature, unsigned char* public_key) { +static const secp256k1_context* get_context() { static secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); + LOG_CHECK(ctx) << "Failed to create secp256k1_context"; + return ctx; +} + +bool ecrecover(const unsigned char* hash, const unsigned char* signature, unsigned char* public_key) { + const secp256k1_context* ctx = get_context(); secp256k1_ecdsa_recoverable_signature ecdsa_signature; if (signature[64] > 3 || !secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &ecdsa_signature, signature, signature[64])) { @@ -39,4 +48,22 @@ bool ecrecover(const unsigned char* hash, const unsigned char* signature, unsign return true; } +bool xonly_pubkey_tweak_add(const unsigned char* xonly_pubkey_bytes, const unsigned char* tweak, + unsigned char* output_pubkey_bytes) { + const secp256k1_context* ctx = get_context(); + + secp256k1_xonly_pubkey xonly_pubkey; + secp256k1_pubkey output_pubkey; + if (!secp256k1_xonly_pubkey_parse(ctx, &xonly_pubkey, xonly_pubkey_bytes)) { + return false; + } + if (!secp256k1_xonly_pubkey_tweak_add(ctx, &output_pubkey, &xonly_pubkey, tweak)) { + return false; + } + size_t len = 65; + secp256k1_ec_pubkey_serialize(ctx, output_pubkey_bytes, &len, &output_pubkey, SECP256K1_EC_UNCOMPRESSED); + CHECK(len == 65); + return true; } + +} // namespace td::secp256k1 diff --git a/crypto/ellcurve/secp256k1.h b/crypto/ellcurve/secp256k1.h index 80ab6a873..20f0b66b3 100644 --- a/crypto/ellcurve/secp256k1.h +++ b/crypto/ellcurve/secp256k1.h @@ -16,8 +16,10 @@ */ #pragma once -namespace td { +namespace td::secp256k1 { bool ecrecover(const unsigned char* hash, const unsigned char* signature, unsigned char* public_key); +bool xonly_pubkey_tweak_add(const unsigned char* xonly_pubkey_bytes, const unsigned char* tweak, + unsigned char* output_pubkey_bytes); -} +} // namespace td::secp256k1 diff --git a/crypto/fift/lib/Asm.fif b/crypto/fift/lib/Asm.fif index 964db4417..39cb759d1 100644 --- a/crypto/fift/lib/Asm.fif +++ b/crypto/fift/lib/Asm.fif @@ -1015,6 +1015,10 @@ x{EDC} dup @Defop(c) SAVEBOTH @Defop(c) SAVEBOTHCTR x{EDE0} @Defop PUSHCTRX x{EDE1} @Defop POPCTRX x{EDE2} @Defop SETCONTCTRX +x{EDE3} @Defop(8u) SETCONTCTRMANY +x{EDE3} @Defop(8u) SETCONTMANY +x{EDE4} @Defop SETCONTCTRMANYX +x{EDE4} @Defop SETCONTMANYX x{EDF0} dup @Defop BOOLAND @Defop COMPOS x{EDF1} dup @Defop BOOLOR @Defop COMPOSALT x{EDF2} @Defop COMPOSBOTH @@ -1354,6 +1358,7 @@ x{F90704} @Defop HASHEXTAR_KECCAK512 x{F910} @Defop CHKSIGNU x{F911} @Defop CHKSIGNS x{F912} @Defop ECRECOVER +x{F913} @Defop SECP256K1_XONLY_PUBKEY_TWEAK_ADD x{F914} @Defop P256_CHKSIGNU x{F915} @Defop P256_CHKSIGNS diff --git a/crypto/test/fift.cpp b/crypto/test/fift.cpp index 3f370ee58..9a92e0b1e 100644 --- a/crypto/test/fift.cpp +++ b/crypto/test/fift.cpp @@ -167,3 +167,7 @@ TEST(Fift, test_bls_ops) { TEST(Fift, test_levels) { run_fift("levels.fif"); } + +TEST(Fift, test_secp256k1) { + run_fift("secp256k1.fif"); +} diff --git a/crypto/test/fift/secp256k1.fif b/crypto/test/fift/secp256k1.fif new file mode 100644 index 000000000..9a0e51788 --- /dev/null +++ b/crypto/test/fift/secp256k1.fif @@ -0,0 +1,82 @@ +"Asm.fif" include +"FiftExt.fif" include + +{ + =: expected_result + =: tweak + =: pubkey + B{e80fe1639c9ca050e3af1b39c143c63e429cbceb15d940fbb5c5a1f4af57c5e9e80fe1639c9ca050e3af1b39c143c63e429cbceb15d940fbb5c5a1f4af57c5e9} + @' pubkey 256 u>B @' tweak 256 u>B B+ B+ Bhashu =: tweak2 + @' pubkey @' tweak2 + [[ <{ SECP256K1_XONLY_PUBKEY_TWEAK_ADD }>s ]] 0 runvmx + abort"exitcode != 0" -1 <> abort"xonly_pubkey_tweak_add failed" + drop + =: result + ."Pubkey = " @' pubkey x. cr + ."Tweak = " @' tweak x. cr + ."Tweak2 = " @' tweak2 x. cr + @' expected_result @' result <> { ."Expected = " @' expected_result x. cr ."Found = " @' result x. cr -1 abort"result mismatch" } if + ."Result = " @' result x. cr + 4 <> abort"first byte is expected to be 4" + cr +} : run-test + +0x4be5f2020ebe2f37b65fb1bcd8aecf2ab0a333427208a5e6dd3dc691f1fb6ae2 +0x7eeda5cc8b219363ffc29a77d170f923dbb939ea5164b71db862d4a192f2680f +0x5a001d32f9fc59c2965ef36d9ff154469a3ba87f00b95879f3b5198bb557494d +run-test + +0x3ad84c3844e66aa255a121ed46d0e69e7b98f31233941c5197917c97c7aeaec5 +0x3f339347d8b1dde7edade3dc59fc63d18cb21fc2326ffbd30f0711a02d25075a +0xc621ca417b8915474020c0c9471a13918b6a02fd20d48a0e526c896923457fcd +run-test + +0x57bb69f0d446ee2cf9f77a2bdca7a3a462a61d85997a1154f2321a2717951b02 +0x3197d6b03d78ebbe694d2b89945a21a5a671ca78393481d44739b7351767adef +0xcbf0da3bbb498fd575506060d04db426164cb9d1477f07481fc6e3a2f84b01ea +run-test + +0x4af537be1a1ae11770eef23e6087f83ce1019fbee7a5876837107f84929a1d19 +0xcf9bfedc7251c2f8e233ae1e2c8b7a6cbe25d96a46a38b79e45d5684d026b64c +0x19b1aa4551bf08363b2533c146c02fa61e26941336aaa16cdd4393a5440392ea +run-test + +0x4be5f2020ebe2f37b65fb1bcd8aecf2ab0a333427208a5e6dd3dc691f1fb6ae2 +0x1762cbfa935318fb1395b50c64f961baab3ecaed4afad3068ba2f7f3a9d15cec +0x38be4b9791c0cb4952b9fb944eb0fe9256ce0d48be7b92129caafdf2f521248a +run-test + +0x3ad84c3844e66aa255a121ed46d0e69e7b98f31233941c5197917c97c7aeaec5 +0x099ec2e6ee1c40f533a61abca2860733727204c2f31d078297194d5e93e148f7 +0x8e9d15851e9aeb652216378f6bc0b88fb66b491697c9b9588f37c11d0b0fbced +run-test + +0x57bb69f0d446ee2cf9f77a2bdca7a3a462a61d85997a1154f2321a2717951b02 +0x63494cee8217ca2a10076e2031534fdda39f132dbdf91606aa65021709cb3116 +0x5dd1aa62a438469f4934e1ab9ada9ba3945651a2641316ec91d0780ca71891f8 +run-test + +0x4af537be1a1ae11770eef23e6087f83ce1019fbee7a5876837107f84929a1d19 +0x36e26133dc62474040eae511ce89610dae6bb0359aa80738baf812ecfa03d2a1 +0xf9ab8bbbee0ad1e90492c952b362d43d56412debdd1224e9729dc79aff931943 +run-test + +0x4be5f2020ebe2f37b65fb1bcd8aecf2ab0a333427208a5e6dd3dc691f1fb6ae2 +0x94f8fb43dd6001bb8acd2c53d094f9c919766dad596498d3d582cebdb39c63da +0xf7b4c76d79925f62e7969cb0e4af0673808f646add78563f711dc33a2687dc1b +run-test + +0x3ad84c3844e66aa255a121ed46d0e69e7b98f31233941c5197917c97c7aeaec5 +0xa2f55c34c4eee5881584714bd5c7a63c397ef38ff1afedd04ada10fdeb541cef +0x73f9a15b76612ca4254e6c2758508589c0112eb724f42dbb4c65ff8b025d2103 +run-test + +0x57bb69f0d446ee2cf9f77a2bdca7a3a462a61d85997a1154f2321a2717951b02 +0x05130a68853e5e4aff579fa21ff10010410a3be47b94d908e203f69ec9dc7d00 +0x4ce6b5b1bd77b1666d33a0c9fd37b98952078bcc451d6de2d0bff65e8f2b46ed +run-test + +0x4af537be1a1ae11770eef23e6087f83ce1019fbee7a5876837107f84929a1d19 +0x9765369cb4467bebc8a468d44aa60f0154f04ee32fbcf1c8bdf646d4840163d1 +0x118953c642b8f25fea3519bcaab3ae6cea25402088e11a8efdc2e0bd222958ad +run-test \ No newline at end of file diff --git a/crypto/vm/contops.cpp b/crypto/vm/contops.cpp index 9610e4aa6..3b8926586 100644 --- a/crypto/vm/contops.cpp +++ b/crypto/vm/contops.cpp @@ -923,6 +923,41 @@ int exec_setcont_ctr_var(VmState* st) { return 0; } +int exec_setcont_ctr_many(VmState* st, unsigned args) { + unsigned mask = args & 255; + VM_LOG(st) << "execute SETCONTCTRMANY " << mask; + if (mask & (1 << 6)) { + throw VmError{Excno::range_chk, "no control register c6"}; + } + Stack& stack = st->get_stack(); + auto cont = stack.pop_cont(); + for (int i = 0; i < 8; ++i) { + if (mask & (1 << i)) { + throw_typechk(force_cregs(cont)->define(i, st->get(i))); + } + } + st->get_stack().push_cont(std::move(cont)); + return 0; +} + +int exec_setcont_ctr_many_var(VmState* st) { + VM_LOG(st) << "execute SETCONTCTRMANYX"; + Stack& stack = st->get_stack(); + stack.check_underflow(2); + int mask = stack.pop_smallint_range(255); + if (mask & (1 << 6)) { + throw VmError{Excno::range_chk, "no control register c6"}; + } + auto cont = stack.pop_cont(); + for (int i = 0; i < 8; ++i) { + if (mask & (1 << i)) { + throw_typechk(force_cregs(cont)->define(i, st->get(i))); + } + } + st->get_stack().push_cont(std::move(cont)); + return 0; +} + int exec_compos(VmState* st, unsigned mask, const char* name) { Stack& stack = st->get_stack(); VM_LOG(st) << "execute " << name; @@ -1037,6 +1072,8 @@ void register_continuation_change_ops(OpcodeTable& cp0) { cp0.insert(OpcodeInstr::mksimple(0xede0, 16, "PUSHCTRX", exec_push_ctr_var)) .insert(OpcodeInstr::mksimple(0xede1, 16, "POPCTRX", exec_pop_ctr_var)) .insert(OpcodeInstr::mksimple(0xede2, 16, "SETCONTCTRX", exec_setcont_ctr_var)) + .insert(OpcodeInstr::mkfixed(0xede3, 16, 8, instr::dump_1c_l_add(1, "SETCONTCTRMANY "), exec_setcont_ctr_many)->require_version(9)) + .insert(OpcodeInstr::mksimple(0xede4, 16, "SETCONTCTRMANYX", exec_setcont_ctr_many_var)->require_version(9)) .insert(OpcodeInstr::mksimple(0xedf0, 16, "BOOLAND", std::bind(exec_compos, _1, 1, "BOOLAND"))) .insert(OpcodeInstr::mksimple(0xedf1, 16, "BOOLOR", std::bind(exec_compos, _1, 2, "BOOLOR"))) .insert(OpcodeInstr::mksimple(0xedf2, 16, "COMPOSBOTH", std::bind(exec_compos, _1, 3, "COMPOSBOTH"))) diff --git a/crypto/vm/tonops.cpp b/crypto/vm/tonops.cpp index 4b2d1734e..6c698df4b 100644 --- a/crypto/vm/tonops.cpp +++ b/crypto/vm/tonops.cpp @@ -661,7 +661,38 @@ int exec_ecrecover(VmState* st) { } st->consume_gas(VmState::ecrecover_gas_price); unsigned char public_key[65]; - if (td::ecrecover(hash_bytes, signature, public_key)) { + if (td::secp256k1::ecrecover(hash_bytes, signature, public_key)) { + td::uint8 h = public_key[0]; + td::RefInt256 x1{true}, x2{true}; + CHECK(x1.write().import_bytes(public_key + 1, 32, false)); + CHECK(x2.write().import_bytes(public_key + 33, 32, false)); + stack.push_smallint(h); + stack.push_int(std::move(x1)); + stack.push_int(std::move(x2)); + stack.push_bool(true); + } else { + stack.push_bool(false); + } + return 0; +} + +int exec_secp256k1_xonly_pubkey_tweak_add(VmState* st) { + VM_LOG(st) << "execute SECP256K1_XONLY_PUBKEY_TWEAK_ADD"; + Stack& stack = st->get_stack(); + stack.check_underflow(2); + auto tweak_int = stack.pop_int(); + auto key_int = stack.pop_int(); + + unsigned char key[32], tweak[32]; + if (!key_int->export_bytes(key, 32, false)) { + throw VmError{Excno::range_chk, "key must fit in an unsigned 256-bit integer"}; + } + if (!tweak_int->export_bytes(tweak, 32, false)) { + throw VmError{Excno::range_chk, "tweak must fit in an unsigned 256-bit integer"}; + } + st->consume_gas(VmState::secp256k1_xonly_pubkey_tweak_add_gas_price); + unsigned char public_key[65]; + if (td::secp256k1::xonly_pubkey_tweak_add(key, tweak, public_key)) { td::uint8 h = public_key[0]; td::RefInt256 x1{true}, x2{true}; CHECK(x1.write().import_bytes(public_key + 1, 32, false)); @@ -1214,6 +1245,7 @@ void register_ton_crypto_ops(OpcodeTable& cp0) { .insert(OpcodeInstr::mksimple(0xf910, 16, "CHKSIGNU", std::bind(exec_ed25519_check_signature, _1, false))) .insert(OpcodeInstr::mksimple(0xf911, 16, "CHKSIGNS", std::bind(exec_ed25519_check_signature, _1, true))) .insert(OpcodeInstr::mksimple(0xf912, 16, "ECRECOVER", exec_ecrecover)->require_version(4)) + .insert(OpcodeInstr::mksimple(0xf913, 16, "SECP256K1_XONLY_PUBKEY_TWEAK_ADD", exec_secp256k1_xonly_pubkey_tweak_add)->require_version(9)) .insert(OpcodeInstr::mksimple(0xf914, 16, "P256_CHKSIGNU", std::bind(exec_p256_chksign, _1, false))->require_version(4)) .insert(OpcodeInstr::mksimple(0xf915, 16, "P256_CHKSIGNS", std::bind(exec_p256_chksign, _1, true))->require_version(4)) diff --git a/crypto/vm/vm.h b/crypto/vm/vm.h index 7afa355c3..cf5322938 100644 --- a/crypto/vm/vm.h +++ b/crypto/vm/vm.h @@ -127,6 +127,7 @@ class VmState final : public VmStateInterface { rist255_validate_gas_price = 200, ecrecover_gas_price = 1500, + secp256k1_xonly_pubkey_tweak_add_gas_price = 1250, chksgn_free_count = 10, chksgn_gas_price = 4000, p256_chksgn_gas_price = 3500, diff --git a/doc/GlobalVersions.md b/doc/GlobalVersions.md index 36d1ab360..5db1ab768 100644 --- a/doc/GlobalVersions.md +++ b/doc/GlobalVersions.md @@ -113,6 +113,13 @@ Operations for working with Merkle proofs, where cells can have non-zero level a ## Version 9 +### New TVM instructions +- `SECP256K1_XONLY_PUBKEY_TWEAK_ADD` (`key tweak - 0 or f x y -1`) - performs [`secp256k1_xonly_pubkey_tweak_add`](https://github.com/bitcoin-core/secp256k1/blob/master/include/secp256k1_extrakeys.h#L120). +`key` and `tweak` are 256-bit unsigned integers. 65-byte public key is returned as `uint8 f`, `uint256 x, y` (as in `ECRECOVER`). Gas cost: `1276`. +- `mask SETCONTCTRMANY` (`cont - cont'`) - takes continuation, performs the equivalent of `c[i] PUSHCTR SWAP c[i] SETCONTCNR` for each `i` that is set in `mask` (mask is in `0..255`). +- `SETCONTCTRMANYX` (`cont mask - cont'`) - same as `SETCONTCTRMANY`, but takes `mask` from stack. + +### Other changes - Fix `RAWRESERVE` action with flag `4` (use original balance of the account) by explicitly setting `original_balance` to `balance - msg_balance_remaining`. - Previously it did not work if storage fee was greater than the original balance. - Jumps to nested continuations of depth more than 8 consume 1 gas for eact subsequent continuation (this does not affect most of TVM code). \ No newline at end of file diff --git a/example/android/CMakeLists.txt b/example/android/CMakeLists.txt index b9651f61b..0101ab641 100644 --- a/example/android/CMakeLists.txt +++ b/example/android/CMakeLists.txt @@ -3,7 +3,9 @@ # Sets the minimum version of CMake required to build the native library. -cmake_minimum_required(VERSION 3.4.1 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +project(TON_ANDROID VERSION 0.5 LANGUAGES C CXX) option(TONLIB_ENABLE_JNI "Enable JNI-compatible TonLib API" ON) diff --git a/example/android/build.sh b/example/android/build.sh index cd75f9d75..dc0618e94 100755 --- a/example/android/build.sh +++ b/example/android/build.sh @@ -48,7 +48,6 @@ mkdir -p build-$ARCH cd build-$ARCH cmake .. -GNinja \ --DPORTABLE=1 \ -DTON_ONLY_TONLIB=ON \ -DTON_ARCH="" \ -DANDROID_ABI=x86 \ @@ -58,12 +57,12 @@ cmake .. -GNinja \ -DCMAKE_BUILD_TYPE=Release \ -DANDROID_ABI=${ABI} \ -DOPENSSL_ROOT_DIR=${OPENSSL_DIR}/${ORIG_ARCH} \ --DSECP256K1_FOUND=1 \ -DSECP256K1_INCLUDE_DIR=${SECP256K1_INCLUDE_DIR} \ -DSECP256K1_LIBRARY=${SECP256K1_LIBRARY} \ -DLZ4_FOUND=1 \ -DLZ4_INCLUDE_DIRS=${LZ4_INCLUDE_DIR} \ -DLZ4_LIBRARIES=${LZ4_LIBRARY} \ +-DSODIUM_FOUND=1 \ -DSODIUM_INCLUDE_DIR=${SODIUM_INCLUDE_DIR} \ -DSODIUM_LIBRARY_RELEASE=${SODIUM_LIBRARY_RELEASE} \ -DSODIUM_USE_STATIC_LIBS=1 \ diff --git a/example/android/third_party/secp256k1/armv7/libsecp256k1.a b/example/android/third_party/secp256k1/armv7/libsecp256k1.a index 70464cbab..f80ead615 100644 Binary files a/example/android/third_party/secp256k1/armv7/libsecp256k1.a and b/example/android/third_party/secp256k1/armv7/libsecp256k1.a differ diff --git a/example/android/third_party/secp256k1/armv7/libsecp256k1.so b/example/android/third_party/secp256k1/armv7/libsecp256k1.so deleted file mode 100644 index b5d939abd..000000000 Binary files a/example/android/third_party/secp256k1/armv7/libsecp256k1.so and /dev/null differ diff --git a/example/android/third_party/secp256k1/armv8/libsecp256k1.a b/example/android/third_party/secp256k1/armv8/libsecp256k1.a index 5b16c4abc..1b79e3af0 100644 Binary files a/example/android/third_party/secp256k1/armv8/libsecp256k1.a and b/example/android/third_party/secp256k1/armv8/libsecp256k1.a differ diff --git a/example/android/third_party/secp256k1/armv8/libsecp256k1.so b/example/android/third_party/secp256k1/armv8/libsecp256k1.so deleted file mode 100644 index 6712bedfe..000000000 Binary files a/example/android/third_party/secp256k1/armv8/libsecp256k1.so and /dev/null differ diff --git a/example/android/third_party/secp256k1/build.sh b/example/android/third_party/secp256k1/build.sh old mode 100644 new mode 100755 index d4251b44d..68da67931 --- a/example/android/third_party/secp256k1/build.sh +++ b/example/android/third_party/secp256k1/build.sh @@ -5,28 +5,32 @@ export CC= export CXX= rm -rf secp256k1 -git clone https://github.com/libbitcoin/secp256k1.git +git clone https://github.com/bitcoin-core/secp256k1 cd secp256k1 +git checkout v0.3.2 ./autogen.sh +mkdir build +cd build -./configure --enable-module-recovery --enable-experimental --with-asm=arm --host=arm-linux-androideabi CC=armv7a-linux-androideabi21-clang CFLAGS="-mthumb -march=armv7-a" CCASFLAGS="-Wa,-mthumb -Wa,-march=armv7-a" +cmake .. -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI=armeabi-v7a -DANDROID_PLATFORM=21 -DBUILD_SHARED_LIBS=OFF -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi make -cp .libs/libsecp256k1.a ../armv7/ -cp .libs/libsecp256k1.so ../armv7/ +cp lib/libsecp256k1.a ../../armv7/ +rm -rf * -./configure --enable-module-recovery --host=aarch64-linux-android CC=aarch64-linux-android21-clang CFLAGS="-mthumb -march=armv8-a" CCASFLAGS="-Wa,-mthumb -Wa,-march=armv8-a" +cmake .. -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=21 -DBUILD_SHARED_LIBS=OFF -DANDROID_TOOLCHAIN_NAME=aarch64-linux-android make -cp .libs/libsecp256k1.a ../armv8/ -cp .libs/libsecp256k1.so ../armv8/ +cp lib/libsecp256k1.a ../../armv8/ +rm -rf * -./configure --enable-module-recovery --host=x86_64-linux-android CC=x86_64-linux-android21-clang +cmake .. -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI=x86_64 -DANDROID_PLATFORM=21 -DBUILD_SHARED_LIBS=OFF -DANDROID_TOOLCHAIN_NAME=x86_64 make -cp .libs/libsecp256k1.a ../x86-64/ -cp .libs/libsecp256k1.so ../x86-64/ +cp lib/libsecp256k1.a ../../x86-64/ +rm -rf * -./configure --enable-module-recovery --host=i686-linux-android CC=i686-linux-android21-clang +cmake .. -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI= -DANDROID_PLATFORM=21 -DBUILD_SHARED_LIBS=OFF -DANDROID_TOOLCHAIN_NAME=x86- make -cp .libs/libsecp256k1.a ../i686/ -cp .libs/libsecp256k1.so ../i686/ +cp lib/libsecp256k1.a ../../i686/ +rm -rf * +rm -rf ../secp256k1 diff --git a/example/android/third_party/secp256k1/i686/libsecp256k1.a b/example/android/third_party/secp256k1/i686/libsecp256k1.a index 01ebe1793..014b1fc7d 100644 Binary files a/example/android/third_party/secp256k1/i686/libsecp256k1.a and b/example/android/third_party/secp256k1/i686/libsecp256k1.a differ diff --git a/example/android/third_party/secp256k1/i686/libsecp256k1.so b/example/android/third_party/secp256k1/i686/libsecp256k1.so deleted file mode 100644 index e245a7242..000000000 Binary files a/example/android/third_party/secp256k1/i686/libsecp256k1.so and /dev/null differ diff --git a/example/android/third_party/secp256k1/include/secp256k1.h b/example/android/third_party/secp256k1/include/secp256k1.h index 36020e516..c6e9417f0 100644 --- a/example/android/third_party/secp256k1/include/secp256k1.h +++ b/example/android/third_party/secp256k1/include/secp256k1.h @@ -7,14 +7,16 @@ extern "C" { #include -/* These rules specify the order of arguments in API calls: +/** Unless explicitly stated all pointer arguments must not be NULL. + * + * The following rules specify the order of arguments in API calls: * * 1. Context pointers go first, followed by output arguments, combined * output/input arguments, and finally input-only arguments. - * 2. Array lengths always immediately the follow the argument whose length + * 2. Array lengths always immediately follow the argument whose length * they describe, even if this violates rule 1. * 3. Within the OUT/OUTIN/IN groups, pointers to data that is typically generated - * later go first. This means: signatures, public nonces, private nonces, + * later go first. This means: signatures, public nonces, secret nonces, * messages, public keys, secret keys, tweaks. * 4. Arguments that are not data pointers go last, from more complex to less * complex: function pointers, algorithm names, messages, void pointers, @@ -22,15 +24,19 @@ extern "C" { * 5. Opaque data pointers follow the function pointer they are to be passed to. */ -/** Opaque data structure that holds context information (precomputed tables etc.). +/** Opaque data structure that holds context information * - * The purpose of context structures is to cache large precomputed data tables - * that are expensive to construct, and also to maintain the randomization data - * for blinding. + * The primary purpose of context objects is to store randomization data for + * enhanced protection against side-channel leakage. This protection is only + * effective if the context is randomized after its creation. See + * secp256k1_context_create for creation of contexts and + * secp256k1_context_randomize for randomization. * - * Do not create a new context object for each operation, as construction is - * far slower than all other API calls (~100 times slower than an ECDSA - * verification). + * A secondary purpose of context objects is to store pointers to callback + * functions that the library will call when certain error states arise. See + * secp256k1_context_set_error_callback as well as + * secp256k1_context_set_illegal_callback for details. Future library versions + * may use context objects for additional purposes. * * A constructed context can safely be used from multiple threads * simultaneously, but API calls that take a non-const pointer to a context @@ -43,32 +49,20 @@ extern "C" { */ typedef struct secp256k1_context_struct secp256k1_context; -/** Opaque data structure that holds rewriteable "scratch space" - * - * The purpose of this structure is to replace dynamic memory allocations, - * because we target architectures where this may not be available. It is - * essentially a resizable (within specified parameters) block of bytes, - * which is initially created either by memory allocation or TODO as a pointer - * into some fixed rewritable space. - * - * Unlike the context object, this cannot safely be shared between threads - * without additional synchronization logic. - */ -typedef struct secp256k1_scratch_space_struct secp256k1_scratch_space; - /** Opaque data structure that holds a parsed and valid public key. * * The exact representation of data inside is implementation defined and not * guaranteed to be portable between different platforms or versions. It is * however guaranteed to be 64 bytes in size, and can be safely copied/moved. - * If you need to convert to a format suitable for storage, transmission, or - * comparison, use secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse. + * If you need to convert to a format suitable for storage or transmission, + * use secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse. To + * compare keys, use secp256k1_ec_pubkey_cmp. */ -typedef struct { +typedef struct secp256k1_pubkey { unsigned char data[64]; } secp256k1_pubkey; -/** Opaque data structured that holds a parsed ECDSA signature. +/** Opaque data structure that holds a parsed ECDSA signature. * * The exact representation of data inside is implementation defined and not * guaranteed to be portable between different platforms or versions. It is @@ -77,7 +71,7 @@ typedef struct { * comparison, use the secp256k1_ecdsa_signature_serialize_* and * secp256k1_ecdsa_signature_parse_* functions. */ -typedef struct { +typedef struct secp256k1_ecdsa_signature { unsigned char data[64]; } secp256k1_ecdsa_signature; @@ -115,35 +109,62 @@ typedef int (*secp256k1_nonce_function)( # endif # endif -# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) -# if SECP256K1_GNUC_PREREQ(2,7) -# define SECP256K1_INLINE __inline__ -# elif (defined(_MSC_VER)) -# define SECP256K1_INLINE __inline +/* When this header is used at build-time the SECP256K1_BUILD define needs to be set + * to correctly setup export attributes and nullness checks. This is normally done + * by secp256k1.c but to guard against this header being included before secp256k1.c + * has had a chance to set the define (e.g. via test harnesses that just includes + * secp256k1.c) we set SECP256K1_NO_BUILD when this header is processed without the + * BUILD define so this condition can be caught. + */ +#ifndef SECP256K1_BUILD +# define SECP256K1_NO_BUILD +#endif + +/* Symbol visibility. */ +#if defined(_WIN32) + /* GCC for Windows (e.g., MinGW) accepts the __declspec syntax + * for MSVC compatibility. A __declspec declaration implies (but is not + * exactly equivalent to) __attribute__ ((visibility("default"))), and so we + * actually want __declspec even on GCC, see "Microsoft Windows Function + * Attributes" in the GCC manual and the recommendations in + * https://gcc.gnu.org/wiki/Visibility. */ +# if defined(SECP256K1_BUILD) +# if defined(DLL_EXPORT) || defined(SECP256K1_DLL_EXPORT) + /* Building libsecp256k1 as a DLL. + * 1. If using Libtool, it defines DLL_EXPORT automatically. + * 2. In other cases, SECP256K1_DLL_EXPORT must be defined. */ +# define SECP256K1_API extern __declspec (dllexport) # else -# define SECP256K1_INLINE + /* Building libsecp256k1 as a static library on Windows. + * No declspec is needed, and so we would want the non-Windows-specific + * logic below take care of this case. However, this may result in setting + * __attribute__ ((visibility("default"))), which is supposed to be a noop + * on Windows but may trigger warnings when compiling with -flto due to a + * bug in GCC, see + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116478 . */ +# define SECP256K1_API extern # endif -# else -# define SECP256K1_INLINE inline + /* The user must define SECP256K1_STATIC when consuming libsecp256k1 as a static + * library on Windows. */ +# elif !defined(SECP256K1_STATIC) + /* Consuming libsecp256k1 as a DLL. */ +# define SECP256K1_API extern __declspec (dllimport) # endif - +#endif #ifndef SECP256K1_API -# if defined(_WIN32) -# ifdef SECP256K1_BUILD -# define SECP256K1_API __declspec(dllexport) -# else -# define SECP256K1_API -# endif -# elif defined(__GNUC__) && defined(SECP256K1_BUILD) -# define SECP256K1_API __attribute__ ((visibility ("default"))) +/* All cases not captured by the Windows-specific logic. */ +# if defined(__GNUC__) && (__GNUC__ >= 4) && defined(SECP256K1_BUILD) + /* Building libsecp256k1 using GCC or compatible. */ +# define SECP256K1_API extern __attribute__ ((visibility ("default"))) # else -# define SECP256K1_API + /* Fall back to standard C's extern. */ +# define SECP256K1_API extern # endif #endif -/**Warning attributes - * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out - * some paranoid null checks. */ +/* Warning attributes + * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out + * some paranoid null checks. */ # if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) # define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) # else @@ -155,20 +176,37 @@ typedef int (*secp256k1_nonce_function)( # define SECP256K1_ARG_NONNULL(_x) # endif -/** All flags' lower 8 bits indicate what they're for. Do not use directly. */ +/* Attribute for marking functions, types, and variables as deprecated */ +#if !defined(SECP256K1_BUILD) && defined(__has_attribute) +# if __has_attribute(__deprecated__) +# define SECP256K1_DEPRECATED(_msg) __attribute__ ((__deprecated__(_msg))) +# else +# define SECP256K1_DEPRECATED(_msg) +# endif +#else +# define SECP256K1_DEPRECATED(_msg) +#endif + +/* All flags' lower 8 bits indicate what they're for. Do not use directly. */ #define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1) #define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0) #define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1) -/** The higher bits contain the actual data. Do not use directly. */ +/* The higher bits contain the actual data. Do not use directly. */ #define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8) #define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9) +#define SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY (1 << 10) #define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8) -/** Flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size, and +/** Context flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size, and * secp256k1_context_preallocated_create. */ +#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) + +/** Deprecated context flags. These flags are treated equivalent to SECP256K1_CONTEXT_NONE. */ #define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) #define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN) -#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) + +/* Testing flag. Do not use. */ +#define SECP256K1_CONTEXT_DECLASSIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_DECLASSIFY) /** Flag to pass to secp256k1_ec_pubkey_serialize. */ #define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) @@ -181,25 +219,68 @@ typedef int (*secp256k1_nonce_function)( #define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06 #define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07 -/** A simple secp256k1 context object with no precomputed tables. These are useful for - * type serialization/parsing functions which require a context object to maintain - * API consistency, but currently do not require expensive precomputations or dynamic - * allocations. +/** A built-in constant secp256k1 context object with static storage duration, to be + * used in conjunction with secp256k1_selftest. + * + * This context object offers *only limited functionality* , i.e., it cannot be used + * for API functions that perform computations involving secret keys, e.g., signing + * and public key generation. If this restriction applies to a specific API function, + * it is mentioned in its documentation. See secp256k1_context_create if you need a + * full context object that supports all functionality offered by the library. + * + * It is highly recommended to call secp256k1_selftest before using this context. */ -SECP256K1_API extern const secp256k1_context *secp256k1_context_no_precomp; +SECP256K1_API const secp256k1_context *secp256k1_context_static; + +/** Deprecated alias for secp256k1_context_static. */ +SECP256K1_API const secp256k1_context *secp256k1_context_no_precomp +SECP256K1_DEPRECATED("Use secp256k1_context_static instead"); + +/** Perform basic self tests (to be used in conjunction with secp256k1_context_static) + * + * This function performs self tests that detect some serious usage errors and + * similar conditions, e.g., when the library is compiled for the wrong endianness. + * This is a last resort measure to be used in production. The performed tests are + * very rudimentary and are not intended as a replacement for running the test + * binaries. + * + * It is highly recommended to call this before using secp256k1_context_static. + * It is not necessary to call this function before using a context created with + * secp256k1_context_create (or secp256k1_context_preallocated_create), which will + * take care of performing the self tests. + * + * If the tests fail, this function will call the default error handler to abort the + * program (see secp256k1_context_set_error_callback). + */ +SECP256K1_API void secp256k1_selftest(void); + /** Create a secp256k1 context object (in dynamically allocated memory). * * This function uses malloc to allocate memory. It is guaranteed that malloc is * called at most once for every call of this function. If you need to avoid dynamic - * memory allocation entirely, see the functions in secp256k1_preallocated.h. + * memory allocation entirely, see secp256k1_context_static and the functions in + * secp256k1_preallocated.h. + * + * Returns: pointer to a newly created context object. + * In: flags: Always set to SECP256K1_CONTEXT_NONE (see below). + * + * The only valid non-deprecated flag in recent library versions is + * SECP256K1_CONTEXT_NONE, which will create a context sufficient for all functionality + * offered by the library. All other (deprecated) flags will be treated as equivalent + * to the SECP256K1_CONTEXT_NONE flag. Though the flags parameter primarily exists for + * historical reasons, future versions of the library may introduce new flags. * - * Returns: a newly created context object. - * In: flags: which parts of the context to initialize. + * If the context is intended to be used for API functions that perform computations + * involving secret keys, e.g., signing and public key generation, then it is highly + * recommended to call secp256k1_context_randomize on the context before calling + * those API functions. This will provide enhanced protection against side-channel + * leakage, see secp256k1_context_randomize for details. * - * See also secp256k1_context_randomize. + * Do not create a new context object for each operation, as construction and + * randomization can take non-negligible time. */ -SECP256K1_API secp256k1_context* secp256k1_context_create( +SECP256K1_API secp256k1_context *secp256k1_context_create( unsigned int flags ) SECP256K1_WARN_UNUSED_RESULT; @@ -209,11 +290,14 @@ SECP256K1_API secp256k1_context* secp256k1_context_create( * called at most once for every call of this function. If you need to avoid dynamic * memory allocation entirely, see the functions in secp256k1_preallocated.h. * - * Returns: a newly created context object. - * Args: ctx: an existing context to copy (cannot be NULL) + * Cloning secp256k1_context_static is not possible, and should not be emulated by + * the caller (e.g., using memcpy). Create a new context instead. + * + * Returns: pointer to a newly created context object. + * Args: ctx: pointer to a context to copy (not secp256k1_context_static). */ -SECP256K1_API secp256k1_context* secp256k1_context_clone( - const secp256k1_context* ctx +SECP256K1_API secp256k1_context *secp256k1_context_clone( + const secp256k1_context *ctx ) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; /** Destroy a secp256k1 context object (created in dynamically allocated memory). @@ -226,12 +310,13 @@ SECP256K1_API secp256k1_context* secp256k1_context_clone( * behaviour is undefined. In that case, secp256k1_context_preallocated_destroy must * be used instead. * - * Args: ctx: an existing context to destroy, constructed using + * Args: ctx: pointer to a context to destroy, constructed using * secp256k1_context_create or secp256k1_context_clone + * (i.e., not secp256k1_context_static). */ SECP256K1_API void secp256k1_context_destroy( - secp256k1_context* ctx -); + secp256k1_context *ctx +) SECP256K1_ARG_NONNULL(1); /** Set a callback function to be called when an illegal argument is passed to * an API call. It will only trigger for violations that are mentioned @@ -248,36 +333,39 @@ SECP256K1_API void secp256k1_context_destroy( * undefined. * * When this function has not been called (or called with fn==NULL), then the - * default handler will be used. The library provides a default handler which + * default handler will be used. The library provides a default handler which * writes the message to stderr and calls abort. This default handler can be * replaced at link time if the preprocessor macro * USE_EXTERNAL_DEFAULT_CALLBACKS is defined, which is the case if the build * has been configured with --enable-external-default-callbacks. Then the * following two symbols must be provided to link against: - * - void secp256k1_default_illegal_callback_fn(const char* message, void* data); - * - void secp256k1_default_error_callback_fn(const char* message, void* data); + * - void secp256k1_default_illegal_callback_fn(const char *message, void *data); + * - void secp256k1_default_error_callback_fn(const char *message, void *data); * The library can call these default handlers even before a proper callback data * pointer could have been set using secp256k1_context_set_illegal_callback or * secp256k1_context_set_error_callback, e.g., when the creation of a context * fails. In this case, the corresponding default handler will be called with * the data pointer argument set to NULL. * - * Args: ctx: an existing context object (cannot be NULL) - * In: fun: a pointer to a function to call when an illegal argument is + * Args: ctx: pointer to a context object. + * In: fun: pointer to a function to call when an illegal argument is * passed to the API, taking a message and an opaque pointer. * (NULL restores the default handler.) - * data: the opaque pointer to pass to fun above. + * data: the opaque pointer to pass to fun above, must be NULL for the default handler. * * See also secp256k1_context_set_error_callback. */ SECP256K1_API void secp256k1_context_set_illegal_callback( - secp256k1_context* ctx, - void (*fun)(const char* message, void* data), - const void* data + secp256k1_context *ctx, + void (*fun)(const char *message, void *data), + const void *data ) SECP256K1_ARG_NONNULL(1); /** Set a callback function to be called when an internal consistency check - * fails. The default is crashing. + * fails. + * + * The default callback writes an error message to stderr and calls abort + * to abort the program. * * This can only trigger in case of a hardware failure, miscompilation, * memory corruption, serious bug in the library, or other error would can @@ -286,49 +374,26 @@ SECP256K1_API void secp256k1_context_set_illegal_callback( * for that). After this callback returns, anything may happen, including * crashing. * - * Args: ctx: an existing context object (cannot be NULL) - * In: fun: a pointer to a function to call when an internal error occurs, + * Args: ctx: pointer to a context object. + * In: fun: pointer to a function to call when an internal error occurs, * taking a message and an opaque pointer (NULL restores the * default handler, see secp256k1_context_set_illegal_callback * for details). - * data: the opaque pointer to pass to fun above. + * data: the opaque pointer to pass to fun above, must be NULL for the default handler. * * See also secp256k1_context_set_illegal_callback. */ SECP256K1_API void secp256k1_context_set_error_callback( - secp256k1_context* ctx, - void (*fun)(const char* message, void* data), - const void* data -) SECP256K1_ARG_NONNULL(1); - -/** Create a secp256k1 scratch space object. - * - * Returns: a newly created scratch space. - * Args: ctx: an existing context object (cannot be NULL) - * In: size: amount of memory to be available as scratch space. Some extra - * (<100 bytes) will be allocated for extra accounting. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_scratch_space* secp256k1_scratch_space_create( - const secp256k1_context* ctx, - size_t size -) SECP256K1_ARG_NONNULL(1); - -/** Destroy a secp256k1 scratch space. - * - * The pointer may not be used afterwards. - * Args: ctx: a secp256k1 context object. - * scratch: space to destroy - */ -SECP256K1_API void secp256k1_scratch_space_destroy( - const secp256k1_context* ctx, - secp256k1_scratch_space* scratch + secp256k1_context *ctx, + void (*fun)(const char *message, void *data), + const void *data ) SECP256K1_ARG_NONNULL(1); /** Parse a variable-length public key into the pubkey object. * * Returns: 1 if the public key was fully valid. * 0 if the public key could not be parsed or is invalid. - * Args: ctx: a secp256k1 context object. + * Args: ctx: pointer to a context object. * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a * parsed version of input. If not, its value is undefined. * In: input: pointer to a serialized public key @@ -339,8 +404,8 @@ SECP256K1_API void secp256k1_scratch_space_destroy( * byte 0x06 or 0x07) format public keys. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse( - const secp256k1_context* ctx, - secp256k1_pubkey* pubkey, + const secp256k1_context *ctx, + secp256k1_pubkey *pubkey, const unsigned char *input, size_t inputlen ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -348,65 +413,94 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse( /** Serialize a pubkey object into a serialized byte sequence. * * Returns: 1 always. - * Args: ctx: a secp256k1 context object. - * Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if + * Args: ctx: pointer to a context object. + * Out: output: pointer to a 65-byte (if compressed==0) or 33-byte (if * compressed==1) byte array to place the serialized key * in. - * In/Out: outputlen: a pointer to an integer which is initially set to the + * In/Out: outputlen: pointer to an integer which is initially set to the * size of output, and is overwritten with the written * size. - * In: pubkey: a pointer to a secp256k1_pubkey containing an + * In: pubkey: pointer to a secp256k1_pubkey containing an * initialized public key. * flags: SECP256K1_EC_COMPRESSED if serialization should be in * compressed format, otherwise SECP256K1_EC_UNCOMPRESSED. */ SECP256K1_API int secp256k1_ec_pubkey_serialize( - const secp256k1_context* ctx, + const secp256k1_context *ctx, unsigned char *output, size_t *outputlen, - const secp256k1_pubkey* pubkey, + const secp256k1_pubkey *pubkey, unsigned int flags ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); +/** Compare two public keys using lexicographic (of compressed serialization) order + * + * Returns: <0 if the first public key is less than the second + * >0 if the first public key is greater than the second + * 0 if the two public keys are equal + * Args: ctx: pointer to a context object + * In: pubkey1: first public key to compare + * pubkey2: second public key to compare + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_cmp( + const secp256k1_context *ctx, + const secp256k1_pubkey *pubkey1, + const secp256k1_pubkey *pubkey2 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Sort public keys using lexicographic (of compressed serialization) order + * + * Returns: 0 if the arguments are invalid. 1 otherwise. + * + * Args: ctx: pointer to a context object + * In: pubkeys: array of pointers to pubkeys to sort + * n_pubkeys: number of elements in the pubkeys array + */ +SECP256K1_API int secp256k1_ec_pubkey_sort( + const secp256k1_context *ctx, + const secp256k1_pubkey **pubkeys, + size_t n_pubkeys +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + /** Parse an ECDSA signature in compact (64 bytes) format. * * Returns: 1 when the signature could be parsed, 0 otherwise. - * Args: ctx: a secp256k1 context object - * Out: sig: a pointer to a signature object - * In: input64: a pointer to the 64-byte array to parse + * Args: ctx: pointer to a context object + * Out: sig: pointer to a signature object + * In: input64: pointer to the 64-byte array to parse * * The signature must consist of a 32-byte big endian R value, followed by a * 32-byte big endian S value. If R or S fall outside of [0..order-1], the * encoding is invalid. R and S with value 0 are allowed in the encoding. * * After the call, sig will always be initialized. If parsing failed or R or - * S are zero, the resulting sig value is guaranteed to fail validation for any - * message and public key. + * S are zero, the resulting sig value is guaranteed to fail verification for + * any message and public key. */ SECP256K1_API int secp256k1_ecdsa_signature_parse_compact( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, + const secp256k1_context *ctx, + secp256k1_ecdsa_signature *sig, const unsigned char *input64 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Parse a DER ECDSA signature. * * Returns: 1 when the signature could be parsed, 0 otherwise. - * Args: ctx: a secp256k1 context object - * Out: sig: a pointer to a signature object - * In: input: a pointer to the signature to be parsed + * Args: ctx: pointer to a context object + * Out: sig: pointer to a signature object + * In: input: pointer to the signature to be parsed * inputlen: the length of the array pointed to be input * * This function will accept any valid DER encoded signature, even if the * encoded numbers are out of range. * * After the call, sig will always be initialized. If parsing failed or the - * encoded numbers are out of range, signature validation with it is + * encoded numbers are out of range, signature verification with it is * guaranteed to fail for every message and public key. */ SECP256K1_API int secp256k1_ecdsa_signature_parse_der( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, + const secp256k1_context *ctx, + secp256k1_ecdsa_signature *sig, const unsigned char *input, size_t inputlen ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -414,71 +508,77 @@ SECP256K1_API int secp256k1_ecdsa_signature_parse_der( /** Serialize an ECDSA signature in DER format. * * Returns: 1 if enough space was available to serialize, 0 otherwise - * Args: ctx: a secp256k1 context object - * Out: output: a pointer to an array to store the DER serialization - * In/Out: outputlen: a pointer to a length integer. Initially, this integer + * Args: ctx: pointer to a context object + * Out: output: pointer to an array to store the DER serialization + * In/Out: outputlen: pointer to a length integer. Initially, this integer * should be set to the length of output. After the call * it will be set to the length of the serialization (even * if 0 was returned). - * In: sig: a pointer to an initialized signature object + * In: sig: pointer to an initialized signature object */ SECP256K1_API int secp256k1_ecdsa_signature_serialize_der( - const secp256k1_context* ctx, + const secp256k1_context *ctx, unsigned char *output, size_t *outputlen, - const secp256k1_ecdsa_signature* sig + const secp256k1_ecdsa_signature *sig ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Serialize an ECDSA signature in compact (64 byte) format. * * Returns: 1 - * Args: ctx: a secp256k1 context object - * Out: output64: a pointer to a 64-byte array to store the compact serialization - * In: sig: a pointer to an initialized signature object + * Args: ctx: pointer to a context object + * Out: output64: pointer to a 64-byte array to store the compact serialization + * In: sig: pointer to an initialized signature object * * See secp256k1_ecdsa_signature_parse_compact for details about the encoding. */ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact( - const secp256k1_context* ctx, + const secp256k1_context *ctx, unsigned char *output64, - const secp256k1_ecdsa_signature* sig + const secp256k1_ecdsa_signature *sig ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Verify an ECDSA signature. * * Returns: 1: correct signature * 0: incorrect or unparseable signature - * Args: ctx: a secp256k1 context object, initialized for verification. - * In: sig: the signature being verified (cannot be NULL) - * msg32: the 32-byte message hash being verified (cannot be NULL) - * pubkey: pointer to an initialized public key to verify with (cannot be NULL) + * Args: ctx: pointer to a context object + * In: sig: the signature being verified. + * msghash32: the 32-byte message hash being verified. + * The verifier must make sure to apply a cryptographic + * hash function to the message by itself and not accept an + * msghash32 value directly. Otherwise, it would be easy to + * create a "valid" signature without knowledge of the + * secret key. See also + * https://bitcoin.stackexchange.com/a/81116/35586 for more + * background on this topic. + * pubkey: pointer to an initialized public key to verify with. * * To avoid accepting malleable signatures, only ECDSA signatures in lower-S * form are accepted. * * If you need to accept ECDSA signatures from sources that do not obey this * rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to - * validation, but be aware that doing so results in malleable signatures. + * verification, but be aware that doing so results in malleable signatures. * * For details, see the comments for that function. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( - const secp256k1_context* ctx, + const secp256k1_context *ctx, const secp256k1_ecdsa_signature *sig, - const unsigned char *msg32, + const unsigned char *msghash32, const secp256k1_pubkey *pubkey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Convert a signature to a normalized lower-S form. * * Returns: 1 if sigin was not normalized, 0 if it already was. - * Args: ctx: a secp256k1 context object - * Out: sigout: a pointer to a signature to fill with the normalized form, + * Args: ctx: pointer to a context object + * Out: sigout: pointer to a signature to fill with the normalized form, * or copy if the input was already normalized. (can be NULL if * you're only interested in whether the input was already * normalized). - * In: sigin: a pointer to a signature to check/normalize (cannot be NULL, - * can be identical to sigout) + * In: sigin: pointer to a signature to check/normalize (can be identical to sigout) * * With ECDSA a third-party can forge a second distinct signature of the same * message, given a single initial signature, but without knowing the key. This @@ -512,7 +612,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( * secp256k1_ecdsa_signature_normalize must be called before verification. */ SECP256K1_API int secp256k1_ecdsa_signature_normalize( - const secp256k1_context* ctx, + const secp256k1_context *ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); @@ -521,185 +621,276 @@ SECP256K1_API int secp256k1_ecdsa_signature_normalize( * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of * extra entropy. */ -SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; +SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; /** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */ -SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_default; +SECP256K1_API const secp256k1_nonce_function secp256k1_nonce_function_default; /** Create an ECDSA signature. * * Returns: 1: signature created - * 0: the nonce generation function failed, or the private key was invalid. - * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) - * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) - * In: msg32: the 32-byte message hash being signed (cannot be NULL) - * seckey: pointer to a 32-byte secret key (cannot be NULL) - * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used - * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) + * 0: the nonce generation function failed, or the secret key was invalid. + * Args: ctx: pointer to a context object (not secp256k1_context_static). + * Out: sig: pointer to an array where the signature will be placed. + * In: msghash32: the 32-byte message hash being signed. + * seckey: pointer to a 32-byte secret key. + * noncefp: pointer to a nonce generation function. If NULL, + * secp256k1_nonce_function_default is used. + * ndata: pointer to arbitrary data used by the nonce generation function + * (can be NULL). If it is non-NULL and + * secp256k1_nonce_function_default is used, then ndata must be a + * pointer to 32-bytes of additional data. * * The created signature is always in lower-S form. See * secp256k1_ecdsa_signature_normalize for more details. */ SECP256K1_API int secp256k1_ecdsa_sign( - const secp256k1_context* ctx, + const secp256k1_context *ctx, secp256k1_ecdsa_signature *sig, - const unsigned char *msg32, + const unsigned char *msghash32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void *ndata ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); -/** Verify an ECDSA secret key. +/** Verify an elliptic curve secret key. + * + * A secret key is valid if it is not 0 and less than the secp256k1 curve order + * when interpreted as an integer (most significant byte first). The + * probability of choosing a 32-byte string uniformly at random which is an + * invalid secret key is negligible. However, if it does happen it should + * be assumed that the randomness source is severely broken and there should + * be no retry. * * Returns: 1: secret key is valid * 0: secret key is invalid - * Args: ctx: pointer to a context object (cannot be NULL) - * In: seckey: pointer to a 32-byte secret key (cannot be NULL) + * Args: ctx: pointer to a context object. + * In: seckey: pointer to a 32-byte secret key. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify( - const secp256k1_context* ctx, + const secp256k1_context *ctx, const unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); /** Compute the public key for a secret key. * - * Returns: 1: secret was valid, public key stores - * 0: secret was invalid, try again - * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) - * Out: pubkey: pointer to the created public key (cannot be NULL) - * In: seckey: pointer to a 32-byte private key (cannot be NULL) + * Returns: 1: secret was valid, public key stores. + * 0: secret was invalid, try again. + * Args: ctx: pointer to a context object (not secp256k1_context_static). + * Out: pubkey: pointer to the created public key. + * In: seckey: pointer to a 32-byte secret key. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( - const secp256k1_context* ctx, + const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -/** Negates a private key in place. +/** Negates a secret key in place. * - * Returns: 1 always - * Args: ctx: pointer to a context object - * In/Out: seckey: pointer to the 32-byte private key to be negated (cannot be NULL) + * Returns: 0 if the given secret key is invalid according to + * secp256k1_ec_seckey_verify. 1 otherwise + * Args: ctx: pointer to a context object + * In/Out: seckey: pointer to the 32-byte secret key to be negated. If the + * secret key is invalid according to + * secp256k1_ec_seckey_verify, this function returns 0 and + * seckey will be set to some unspecified value. */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate( - const secp256k1_context* ctx, +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_negate( + const secp256k1_context *ctx, unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); +/** Same as secp256k1_ec_seckey_negate, but DEPRECATED. Will be removed in + * future versions. */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate( + const secp256k1_context *ctx, + unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) + SECP256K1_DEPRECATED("Use secp256k1_ec_seckey_negate instead"); + /** Negates a public key in place. * * Returns: 1 always * Args: ctx: pointer to a context object - * In/Out: pubkey: pointer to the public key to be negated (cannot be NULL) + * In/Out: pubkey: pointer to the public key to be negated. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate( - const secp256k1_context* ctx, + const secp256k1_context *ctx, secp256k1_pubkey *pubkey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); -/** Tweak a private key by adding tweak to it. - * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for - * uniformly random 32-byte arrays, or if the resulting private key - * would be invalid (only when the tweak is the complement of the - * private key). 1 otherwise. - * Args: ctx: pointer to a context object (cannot be NULL). - * In/Out: seckey: pointer to a 32-byte private key. - * In: tweak: pointer to a 32-byte tweak. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( - const secp256k1_context* ctx, +/** Tweak a secret key by adding tweak to it. + * + * Returns: 0 if the arguments are invalid or the resulting secret key would be + * invalid (only when the tweak is the negation of the secret key). 1 + * otherwise. + * Args: ctx: pointer to a context object. + * In/Out: seckey: pointer to a 32-byte secret key. If the secret key is + * invalid according to secp256k1_ec_seckey_verify, this + * function returns 0. seckey will be set to some unspecified + * value if this function returns 0. + * In: tweak32: pointer to a 32-byte tweak, which must be valid according to + * secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly + * random 32-byte tweaks, the chance of being invalid is + * negligible (around 1 in 2^128). + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_add( + const secp256k1_context *ctx, unsigned char *seckey, - const unsigned char *tweak + const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); +/** Same as secp256k1_ec_seckey_tweak_add, but DEPRECATED. Will be removed in + * future versions. */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( + const secp256k1_context *ctx, + unsigned char *seckey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) + SECP256K1_DEPRECATED("Use secp256k1_ec_seckey_tweak_add instead"); + /** Tweak a public key by adding tweak times the generator to it. - * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for - * uniformly random 32-byte arrays, or if the resulting public key - * would be invalid (only when the tweak is the complement of the - * corresponding private key). 1 otherwise. - * Args: ctx: pointer to a context object initialized for validation - * (cannot be NULL). - * In/Out: pubkey: pointer to a public key object. - * In: tweak: pointer to a 32-byte tweak. + * + * Returns: 0 if the arguments are invalid or the resulting public key would be + * invalid (only when the tweak is the negation of the corresponding + * secret key). 1 otherwise. + * Args: ctx: pointer to a context object. + * In/Out: pubkey: pointer to a public key object. pubkey will be set to an + * invalid value if this function returns 0. + * In: tweak32: pointer to a 32-byte tweak, which must be valid according to + * secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly + * random 32-byte tweaks, the chance of being invalid is + * negligible (around 1 in 2^128). */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( - const secp256k1_context* ctx, + const secp256k1_context *ctx, secp256k1_pubkey *pubkey, - const unsigned char *tweak + const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -/** Tweak a private key by multiplying it by a tweak. - * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for - * uniformly random 32-byte arrays, or equal to zero. 1 otherwise. - * Args: ctx: pointer to a context object (cannot be NULL). - * In/Out: seckey: pointer to a 32-byte private key. - * In: tweak: pointer to a 32-byte tweak. - */ -SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( - const secp256k1_context* ctx, +/** Tweak a secret key by multiplying it by a tweak. + * + * Returns: 0 if the arguments are invalid. 1 otherwise. + * Args: ctx: pointer to a context object. + * In/Out: seckey: pointer to a 32-byte secret key. If the secret key is + * invalid according to secp256k1_ec_seckey_verify, this + * function returns 0. seckey will be set to some unspecified + * value if this function returns 0. + * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to + * secp256k1_ec_seckey_verify, this function returns 0. For + * uniformly random 32-byte arrays the chance of being invalid + * is negligible (around 1 in 2^128). + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_tweak_mul( + const secp256k1_context *ctx, unsigned char *seckey, - const unsigned char *tweak + const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); +/** Same as secp256k1_ec_seckey_tweak_mul, but DEPRECATED. Will be removed in + * future versions. */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( + const secp256k1_context *ctx, + unsigned char *seckey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) + SECP256K1_DEPRECATED("Use secp256k1_ec_seckey_tweak_mul instead"); + /** Tweak a public key by multiplying it by a tweak value. - * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for - * uniformly random 32-byte arrays, or equal to zero. 1 otherwise. - * Args: ctx: pointer to a context object initialized for validation - * (cannot be NULL). - * In/Out: pubkey: pointer to a public key object. - * In: tweak: pointer to a 32-byte tweak. + * + * Returns: 0 if the arguments are invalid. 1 otherwise. + * Args: ctx: pointer to a context object. + * In/Out: pubkey: pointer to a public key object. pubkey will be set to an + * invalid value if this function returns 0. + * In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according to + * secp256k1_ec_seckey_verify, this function returns 0. For + * uniformly random 32-byte arrays the chance of being invalid + * is negligible (around 1 in 2^128). */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( - const secp256k1_context* ctx, + const secp256k1_context *ctx, secp256k1_pubkey *pubkey, - const unsigned char *tweak + const unsigned char *tweak32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -/** Updates the context randomization to protect against side-channel leakage. - * Returns: 1: randomization successfully updated or nothing to randomize +/** Randomizes the context to provide enhanced protection against side-channel leakage. + * + * Returns: 1: randomization successful * 0: error - * Args: ctx: pointer to a context object (cannot be NULL) - * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state) + * Args: ctx: pointer to a context object (not secp256k1_context_static). + * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state). * - * While secp256k1 code is written to be constant-time no matter what secret - * values are, it's possible that a future compiler may output code which isn't, + * While secp256k1 code is written and tested to be constant-time no matter what + * secret values are, it is possible that a compiler may output code which is not, * and also that the CPU may not emit the same radio frequencies or draw the same - * amount power for all values. - * - * This function provides a seed which is combined into the blinding value: that - * blinding value is added before each multiplication (and removed afterwards) so - * that it does not affect function results, but shields against attacks which - * rely on any input-dependent behaviour. - * - * This function has currently an effect only on contexts initialized for signing - * because randomization is currently used only for signing. However, this is not - * guaranteed and may change in the future. It is safe to call this function on - * contexts not initialized for signing; then it will have no effect and return 1. - * - * You should call this after secp256k1_context_create or - * secp256k1_context_clone (and secp256k1_context_preallocated_create or - * secp256k1_context_clone, resp.), and you may call this repeatedly afterwards. + * amount of power for all values. Randomization of the context shields against + * side-channel observations which aim to exploit secret-dependent behaviour in + * certain computations which involve secret keys. + * + * It is highly recommended to call this function on contexts returned from + * secp256k1_context_create or secp256k1_context_clone (or from the corresponding + * functions in secp256k1_preallocated.h) before using these contexts to call API + * functions that perform computations involving secret keys, e.g., signing and + * public key generation. It is possible to call this function more than once on + * the same context, and doing so before every few computations involving secret + * keys is recommended as a defense-in-depth measure. Randomization of the static + * context secp256k1_context_static is not supported. + * + * Currently, the random seed is mainly used for blinding multiplications of a + * secret scalar with the elliptic curve base point. Multiplications of this + * kind are performed by exactly those API functions which are documented to + * require a context that is not secp256k1_context_static. As a rule of thumb, + * these are all functions which take a secret key (or a keypair) as an input. + * A notable exception to that rule is the ECDH module, which relies on a different + * kind of elliptic curve point multiplication and thus does not benefit from + * enhanced protection against side-channel leakage currently. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( - secp256k1_context* ctx, + secp256k1_context *ctx, const unsigned char *seed32 ) SECP256K1_ARG_NONNULL(1); /** Add a number of public keys together. + * * Returns: 1: the sum of the public keys is valid. * 0: the sum of the public keys is not valid. - * Args: ctx: pointer to a context object - * Out: out: pointer to a public key object for placing the resulting public key - * (cannot be NULL) - * In: ins: pointer to array of pointers to public keys (cannot be NULL) - * n: the number of public keys to add together (must be at least 1) + * Args: ctx: pointer to a context object. + * Out: out: pointer to a public key object for placing the resulting public key. + * In: ins: pointer to array of pointers to public keys. + * n: the number of public keys to add together (must be at least 1). */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine( - const secp256k1_context* ctx, + const secp256k1_context *ctx, secp256k1_pubkey *out, - const secp256k1_pubkey * const * ins, + const secp256k1_pubkey * const *ins, size_t n -) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Compute a tagged hash as defined in BIP-340. + * + * This is useful for creating a message hash and achieving domain separation + * through an application-specific tag. This function returns + * SHA256(SHA256(tag)||SHA256(tag)||msg). Therefore, tagged hash + * implementations optimized for a specific tag can precompute the SHA256 state + * after hashing the tag hashes. + * + * Returns: 1 always. + * Args: ctx: pointer to a context object + * Out: hash32: pointer to a 32-byte array to store the resulting hash + * In: tag: pointer to an array containing the tag + * taglen: length of the tag array + * msg: pointer to an array containing the message + * msglen: length of the message array + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_tagged_sha256( + const secp256k1_context *ctx, + unsigned char *hash32, + const unsigned char *tag, + size_t taglen, + const unsigned char *msg, + size_t msglen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5); #ifdef __cplusplus } diff --git a/example/android/third_party/secp256k1/include/secp256k1_ecdh.h b/example/android/third_party/secp256k1/include/secp256k1_ecdh.h index df5fde235..4d9da3461 100644 --- a/example/android/third_party/secp256k1/include/secp256k1_ecdh.h +++ b/example/android/third_party/secp256k1/include/secp256k1_ecdh.h @@ -7,43 +7,51 @@ extern "C" { #endif -/** A pointer to a function that applies hash function to a point +/** A pointer to a function that hashes an EC point to obtain an ECDH secret * - * Returns: 1 if a point was successfully hashed. 0 will cause ecdh to fail - * Out: output: pointer to an array to be filled by the function - * In: x: pointer to a 32-byte x coordinate - * y: pointer to a 32-byte y coordinate - * data: Arbitrary data pointer that is passed through + * Returns: 1 if the point was successfully hashed. + * 0 will cause secp256k1_ecdh to fail and return 0. + * Other return values are not allowed, and the behaviour of + * secp256k1_ecdh is undefined for other return values. + * Out: output: pointer to an array to be filled by the function + * In: x32: pointer to a 32-byte x coordinate + * y32: pointer to a 32-byte y coordinate + * data: arbitrary data pointer that is passed through */ typedef int (*secp256k1_ecdh_hash_function)( unsigned char *output, - const unsigned char *x, - const unsigned char *y, + const unsigned char *x32, + const unsigned char *y32, void *data ); -/** An implementation of SHA256 hash function that applies to compressed public key. */ -SECP256K1_API extern const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256; +/** An implementation of SHA256 hash function that applies to compressed public key. + * Populates the output parameter with 32 bytes. */ +SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256; -/** A default ecdh hash function (currently equal to secp256k1_ecdh_hash_function_sha256). */ -SECP256K1_API extern const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default; +/** A default ECDH hash function (currently equal to secp256k1_ecdh_hash_function_sha256). + * Populates the output parameter with 32 bytes. */ +SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default; /** Compute an EC Diffie-Hellman secret in constant time + * * Returns: 1: exponentiation was successful - * 0: scalar was invalid (zero or overflow) - * Args: ctx: pointer to a context object (cannot be NULL) - * Out: output: pointer to an array to be filled by the function - * In: pubkey: a pointer to a secp256k1_pubkey containing an - * initialized public key - * privkey: a 32-byte scalar with which to multiply the point - * hashfp: pointer to a hash function. If NULL, secp256k1_ecdh_hash_function_sha256 is used - * data: Arbitrary data pointer that is passed through + * 0: scalar was invalid (zero or overflow) or hashfp returned 0 + * Args: ctx: pointer to a context object. + * Out: output: pointer to an array to be filled by hashfp. + * In: pubkey: pointer to a secp256k1_pubkey containing an initialized public key. + * seckey: a 32-byte scalar with which to multiply the point. + * hashfp: pointer to a hash function. If NULL, + * secp256k1_ecdh_hash_function_sha256 is used + * (in which case, 32 bytes will be written to output). + * data: arbitrary data pointer that is passed through to hashfp + * (can be NULL for secp256k1_ecdh_hash_function_sha256). */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh( - const secp256k1_context* ctx, + const secp256k1_context *ctx, unsigned char *output, const secp256k1_pubkey *pubkey, - const unsigned char *privkey, + const unsigned char *seckey, secp256k1_ecdh_hash_function hashfp, void *data ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); diff --git a/example/android/third_party/secp256k1/include/secp256k1_ellswift.h b/example/android/third_party/secp256k1/include/secp256k1_ellswift.h new file mode 100644 index 000000000..0d1293e94 --- /dev/null +++ b/example/android/third_party/secp256k1/include/secp256k1_ellswift.h @@ -0,0 +1,200 @@ +#ifndef SECP256K1_ELLSWIFT_H +#define SECP256K1_ELLSWIFT_H + +#include "secp256k1.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This module provides an implementation of ElligatorSwift as well as a + * version of x-only ECDH using it (including compatibility with BIP324). + * + * ElligatorSwift is described in https://eprint.iacr.org/2022/759 by + * Chavez-Saab, Rodriguez-Henriquez, and Tibouchi. It permits encoding + * uniformly chosen public keys as 64-byte arrays which are indistinguishable + * from uniformly random arrays. + * + * Let f be the function from pairs of field elements to point X coordinates, + * defined as follows (all operations modulo p = 2^256 - 2^32 - 977) + * f(u,t): + * - Let C = 0xa2d2ba93507f1df233770c2a797962cc61f6d15da14ecd47d8d27ae1cd5f852, + * a square root of -3. + * - If u=0, set u=1 instead. + * - If t=0, set t=1 instead. + * - If u^3 + t^2 + 7 = 0, multiply t by 2. + * - Let X = (u^3 + 7 - t^2) / (2 * t) + * - Let Y = (X + t) / (C * u) + * - Return the first in [u + 4 * Y^2, (-X/Y - u) / 2, (X/Y - u) / 2] that is an + * X coordinate on the curve (at least one of them is, for any u and t). + * + * Then an ElligatorSwift encoding of x consists of the 32-byte big-endian + * encodings of field elements u and t concatenated, where f(u,t) = x. + * The encoding algorithm is described in the paper, and effectively picks a + * uniformly random pair (u,t) among those which encode x. + * + * If the Y coordinate is relevant, it is given the same parity as t. + * + * Changes w.r.t. the paper: + * - The u=0, t=0, and u^3+t^2+7=0 conditions result in decoding to the point + * at infinity in the paper. Here they are remapped to finite points. + * - The paper uses an additional encoding bit for the parity of y. Here the + * parity of t is used (negating t does not affect the decoded x coordinate, + * so this is possible). + * + * For mathematical background about the scheme, see the doc/ellswift.md file. + */ + +/** A pointer to a function used by secp256k1_ellswift_xdh to hash the shared X + * coordinate along with the encoded public keys to a uniform shared secret. + * + * Returns: 1 if a shared secret was successfully computed. + * 0 will cause secp256k1_ellswift_xdh to fail and return 0. + * Other return values are not allowed, and the behaviour of + * secp256k1_ellswift_xdh is undefined for other return values. + * Out: output: pointer to an array to be filled by the function + * In: x32: pointer to the 32-byte serialized X coordinate + * of the resulting shared point (will not be NULL) + * ell_a64: pointer to the 64-byte encoded public key of party A + * (will not be NULL) + * ell_b64: pointer to the 64-byte encoded public key of party B + * (will not be NULL) + * data: arbitrary data pointer that is passed through + */ +typedef int (*secp256k1_ellswift_xdh_hash_function)( + unsigned char *output, + const unsigned char *x32, + const unsigned char *ell_a64, + const unsigned char *ell_b64, + void *data +); + +/** An implementation of an secp256k1_ellswift_xdh_hash_function which uses + * SHA256(prefix64 || ell_a64 || ell_b64 || x32), where prefix64 is the 64-byte + * array pointed to by data. */ +SECP256K1_API const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix; + +/** An implementation of an secp256k1_ellswift_xdh_hash_function compatible with + * BIP324. It returns H_tag(ell_a64 || ell_b64 || x32), where H_tag is the + * BIP340 tagged hash function with tag "bip324_ellswift_xonly_ecdh". Equivalent + * to secp256k1_ellswift_xdh_hash_function_prefix with prefix64 set to + * SHA256("bip324_ellswift_xonly_ecdh")||SHA256("bip324_ellswift_xonly_ecdh"). + * The data argument is ignored. */ +SECP256K1_API const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324; + +/** Construct a 64-byte ElligatorSwift encoding of a given pubkey. + * + * Returns: 1 always. + * Args: ctx: pointer to a context object + * Out: ell64: pointer to a 64-byte array to be filled + * In: pubkey: pointer to a secp256k1_pubkey containing an + * initialized public key + * rnd32: pointer to 32 bytes of randomness + * + * It is recommended that rnd32 consists of 32 uniformly random bytes, not + * known to any adversary trying to detect whether public keys are being + * encoded, though 16 bytes of randomness (padded to an array of 32 bytes, + * e.g., with zeros) suffice to make the result indistinguishable from + * uniform. The randomness in rnd32 must not be a deterministic function of + * the pubkey (it can be derived from the private key, though). + * + * It is not guaranteed that the computed encoding is stable across versions + * of the library, even if all arguments to this function (including rnd32) + * are the same. + * + * This function runs in variable time. + */ +SECP256K1_API int secp256k1_ellswift_encode( + const secp256k1_context *ctx, + unsigned char *ell64, + const secp256k1_pubkey *pubkey, + const unsigned char *rnd32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Decode a 64-bytes ElligatorSwift encoded public key. + * + * Returns: always 1 + * Args: ctx: pointer to a context object + * Out: pubkey: pointer to a secp256k1_pubkey that will be filled + * In: ell64: pointer to a 64-byte array to decode + * + * This function runs in variable time. + */ +SECP256K1_API int secp256k1_ellswift_decode( + const secp256k1_context *ctx, + secp256k1_pubkey *pubkey, + const unsigned char *ell64 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Compute an ElligatorSwift public key for a secret key. + * + * Returns: 1: secret was valid, public key was stored. + * 0: secret was invalid, try again. + * Args: ctx: pointer to a context object + * Out: ell64: pointer to a 64-byte array to receive the ElligatorSwift + * public key + * In: seckey32: pointer to a 32-byte secret key + * auxrnd32: (optional) pointer to 32 bytes of randomness + * + * Constant time in seckey and auxrnd32, but not in the resulting public key. + * + * It is recommended that auxrnd32 contains 32 uniformly random bytes, though + * it is optional (and does result in encodings that are indistinguishable from + * uniform even without any auxrnd32). It differs from the (mandatory) rnd32 + * argument to secp256k1_ellswift_encode in this regard. + * + * This function can be used instead of calling secp256k1_ec_pubkey_create + * followed by secp256k1_ellswift_encode. It is safer, as it uses the secret + * key as entropy for the encoding (supplemented with auxrnd32, if provided). + * + * Like secp256k1_ellswift_encode, this function does not guarantee that the + * computed encoding is stable across versions of the library, even if all + * arguments (including auxrnd32) are the same. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ellswift_create( + const secp256k1_context *ctx, + unsigned char *ell64, + const unsigned char *seckey32, + const unsigned char *auxrnd32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Given a private key, and ElligatorSwift public keys sent in both directions, + * compute a shared secret using x-only Elliptic Curve Diffie-Hellman (ECDH). + * + * Returns: 1: shared secret was successfully computed + * 0: secret was invalid or hashfp returned 0 + * Args: ctx: pointer to a context object. + * Out: output: pointer to an array to be filled by hashfp. + * In: ell_a64: pointer to the 64-byte encoded public key of party A + * (will not be NULL) + * ell_b64: pointer to the 64-byte encoded public key of party B + * (will not be NULL) + * seckey32: pointer to our 32-byte secret key + * party: boolean indicating which party we are: zero if we are + * party A, non-zero if we are party B. seckey32 must be + * the private key corresponding to that party's ell_?64. + * This correspondence is not checked. + * hashfp: pointer to a hash function. + * data: arbitrary data pointer passed through to hashfp. + * + * Constant time in seckey32. + * + * This function is more efficient than decoding the public keys, and performing + * ECDH on them. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ellswift_xdh( + const secp256k1_context *ctx, + unsigned char *output, + const unsigned char *ell_a64, + const unsigned char *ell_b64, + const unsigned char *seckey32, + int party, + secp256k1_ellswift_xdh_hash_function hashfp, + void *data +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(7); + +#ifdef __cplusplus +} +#endif + +#endif /* SECP256K1_ELLSWIFT_H */ diff --git a/example/android/third_party/secp256k1/include/secp256k1_extrakeys.h b/example/android/third_party/secp256k1/include/secp256k1_extrakeys.h new file mode 100644 index 000000000..48c98693c --- /dev/null +++ b/example/android/third_party/secp256k1/include/secp256k1_extrakeys.h @@ -0,0 +1,250 @@ +#ifndef SECP256K1_EXTRAKEYS_H +#define SECP256K1_EXTRAKEYS_H + +#include "secp256k1.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Opaque data structure that holds a parsed and valid "x-only" public key. + * An x-only pubkey encodes a point whose Y coordinate is even. It is + * serialized using only its X coordinate (32 bytes). See BIP-340 for more + * information about x-only pubkeys. + * + * The exact representation of data inside is implementation defined and not + * guaranteed to be portable between different platforms or versions. It is + * however guaranteed to be 64 bytes in size, and can be safely copied/moved. + * If you need to convert to a format suitable for storage, transmission, use + * use secp256k1_xonly_pubkey_serialize and secp256k1_xonly_pubkey_parse. To + * compare keys, use secp256k1_xonly_pubkey_cmp. + */ +typedef struct secp256k1_xonly_pubkey { + unsigned char data[64]; +} secp256k1_xonly_pubkey; + +/** Opaque data structure that holds a keypair consisting of a secret and a + * public key. + * + * The exact representation of data inside is implementation defined and not + * guaranteed to be portable between different platforms or versions. It is + * however guaranteed to be 96 bytes in size, and can be safely copied/moved. + */ +typedef struct secp256k1_keypair { + unsigned char data[96]; +} secp256k1_keypair; + +/** Parse a 32-byte sequence into a xonly_pubkey object. + * + * Returns: 1 if the public key was fully valid. + * 0 if the public key could not be parsed or is invalid. + * + * Args: ctx: pointer to a context object. + * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a + * parsed version of input. If not, it's set to an invalid value. + * In: input32: pointer to a serialized xonly_pubkey. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_parse( + const secp256k1_context *ctx, + secp256k1_xonly_pubkey *pubkey, + const unsigned char *input32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize an xonly_pubkey object into a 32-byte sequence. + * + * Returns: 1 always. + * + * Args: ctx: pointer to a context object. + * Out: output32: pointer to a 32-byte array to place the serialized key in. + * In: pubkey: pointer to a secp256k1_xonly_pubkey containing an initialized public key. + */ +SECP256K1_API int secp256k1_xonly_pubkey_serialize( + const secp256k1_context *ctx, + unsigned char *output32, + const secp256k1_xonly_pubkey *pubkey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Compare two x-only public keys using lexicographic order + * + * Returns: <0 if the first public key is less than the second + * >0 if the first public key is greater than the second + * 0 if the two public keys are equal + * Args: ctx: pointer to a context object. + * In: pubkey1: first public key to compare + * pubkey2: second public key to compare + */ +SECP256K1_API int secp256k1_xonly_pubkey_cmp( + const secp256k1_context *ctx, + const secp256k1_xonly_pubkey *pk1, + const secp256k1_xonly_pubkey *pk2 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Converts a secp256k1_pubkey into a secp256k1_xonly_pubkey. + * + * Returns: 1 always. + * + * Args: ctx: pointer to a context object. + * Out: xonly_pubkey: pointer to an x-only public key object for placing the converted public key. + * pk_parity: Ignored if NULL. Otherwise, pointer to an integer that + * will be set to 1 if the point encoded by xonly_pubkey is + * the negation of the pubkey and set to 0 otherwise. + * In: pubkey: pointer to a public key that is converted. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubkey( + const secp256k1_context *ctx, + secp256k1_xonly_pubkey *xonly_pubkey, + int *pk_parity, + const secp256k1_pubkey *pubkey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4); + +/** Tweak an x-only public key by adding the generator multiplied with tweak32 + * to it. + * + * Note that the resulting point can not in general be represented by an x-only + * pubkey because it may have an odd Y coordinate. Instead, the output_pubkey + * is a normal secp256k1_pubkey. + * + * Returns: 0 if the arguments are invalid or the resulting public key would be + * invalid (only when the tweak is the negation of the corresponding + * secret key). 1 otherwise. + * + * Args: ctx: pointer to a context object. + * Out: output_pubkey: pointer to a public key to store the result. Will be set + * to an invalid value if this function returns 0. + * In: internal_pubkey: pointer to an x-only pubkey to apply the tweak to. + * tweak32: pointer to a 32-byte tweak, which must be valid + * according to secp256k1_ec_seckey_verify or 32 zero + * bytes. For uniformly random 32-byte tweaks, the chance of + * being invalid is negligible (around 1 in 2^128). + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add( + const secp256k1_context *ctx, + secp256k1_pubkey *output_pubkey, + const secp256k1_xonly_pubkey *internal_pubkey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Checks that a tweaked pubkey is the result of calling + * secp256k1_xonly_pubkey_tweak_add with internal_pubkey and tweak32. + * + * The tweaked pubkey is represented by its 32-byte x-only serialization and + * its pk_parity, which can both be obtained by converting the result of + * tweak_add to a secp256k1_xonly_pubkey. + * + * Note that this alone does _not_ verify that the tweaked pubkey is a + * commitment. If the tweak is not chosen in a specific way, the tweaked pubkey + * can easily be the result of a different internal_pubkey and tweak. + * + * Returns: 0 if the arguments are invalid or the tweaked pubkey is not the + * result of tweaking the internal_pubkey with tweak32. 1 otherwise. + * Args: ctx: pointer to a context object. + * In: tweaked_pubkey32: pointer to a serialized xonly_pubkey. + * tweaked_pk_parity: the parity of the tweaked pubkey (whose serialization + * is passed in as tweaked_pubkey32). This must match the + * pk_parity value that is returned when calling + * secp256k1_xonly_pubkey with the tweaked pubkey, or + * this function will fail. + * internal_pubkey: pointer to an x-only public key object to apply the tweak to. + * tweak32: pointer to a 32-byte tweak. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add_check( + const secp256k1_context *ctx, + const unsigned char *tweaked_pubkey32, + int tweaked_pk_parity, + const secp256k1_xonly_pubkey *internal_pubkey, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); + +/** Compute the keypair for a valid secret key. + * + * See the documentation of `secp256k1_ec_seckey_verify` for more information + * about the validity of secret keys. + * + * Returns: 1: secret key is valid + * 0: secret key is invalid + * Args: ctx: pointer to a context object (not secp256k1_context_static). + * Out: keypair: pointer to the created keypair. + * In: seckey: pointer to a 32-byte secret key. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_create( + const secp256k1_context *ctx, + secp256k1_keypair *keypair, + const unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Get the secret key from a keypair. + * + * Returns: 1 always. + * Args: ctx: pointer to a context object. + * Out: seckey: pointer to a 32-byte buffer for the secret key. + * In: keypair: pointer to a keypair. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_sec( + const secp256k1_context *ctx, + unsigned char *seckey, + const secp256k1_keypair *keypair +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Get the public key from a keypair. + * + * Returns: 1 always. + * Args: ctx: pointer to a context object. + * Out: pubkey: pointer to a pubkey object, set to the keypair public key. + * In: keypair: pointer to a keypair. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_pub( + const secp256k1_context *ctx, + secp256k1_pubkey *pubkey, + const secp256k1_keypair *keypair +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Get the x-only public key from a keypair. + * + * This is the same as calling secp256k1_keypair_pub and then + * secp256k1_xonly_pubkey_from_pubkey. + * + * Returns: 1 always. + * Args: ctx: pointer to a context object. + * Out: pubkey: pointer to an xonly_pubkey object, set to the keypair + * public key after converting it to an xonly_pubkey. + * pk_parity: Ignored if NULL. Otherwise, pointer to an integer that will be set to the + * pk_parity argument of secp256k1_xonly_pubkey_from_pubkey. + * In: keypair: pointer to a keypair. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub( + const secp256k1_context *ctx, + secp256k1_xonly_pubkey *pubkey, + int *pk_parity, + const secp256k1_keypair *keypair +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4); + +/** Tweak a keypair by adding tweak32 to the secret key and updating the public + * key accordingly. + * + * Calling this function and then secp256k1_keypair_pub results in the same + * public key as calling secp256k1_keypair_xonly_pub and then + * secp256k1_xonly_pubkey_tweak_add. + * + * Returns: 0 if the arguments are invalid or the resulting keypair would be + * invalid (only when the tweak is the negation of the keypair's + * secret key). 1 otherwise. + * + * Args: ctx: pointer to a context object. + * In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to + * an invalid value if this function returns 0. + * In: tweak32: pointer to a 32-byte tweak, which must be valid according to + * secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly + * random 32-byte tweaks, the chance of being invalid is + * negligible (around 1 in 2^128). + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_tweak_add( + const secp256k1_context *ctx, + secp256k1_keypair *keypair, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +#ifdef __cplusplus +} +#endif + +#endif /* SECP256K1_EXTRAKEYS_H */ diff --git a/example/android/third_party/secp256k1/include/secp256k1_musig.h b/example/android/third_party/secp256k1/include/secp256k1_musig.h new file mode 100644 index 000000000..11b8f08c8 --- /dev/null +++ b/example/android/third_party/secp256k1/include/secp256k1_musig.h @@ -0,0 +1,588 @@ +#ifndef SECP256K1_MUSIG_H +#define SECP256K1_MUSIG_H + +#include "secp256k1_extrakeys.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** This module implements BIP 327 "MuSig2 for BIP340-compatible + * Multi-Signatures" + * (https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki) + * v1.0.0. You can find an example demonstrating the musig module in + * examples/musig.c. + * + * The module also supports BIP 341 ("Taproot") public key tweaking. + * + * It is recommended to read the documentation in this include file carefully. + * Further notes on API usage can be found in doc/musig.md + * + * Since the first version of MuSig is essentially replaced by MuSig2, we use + * MuSig, musig and MuSig2 synonymously unless noted otherwise. + */ + +/** Opaque data structures + * + * The exact representation of data inside the opaque data structures is + * implementation defined and not guaranteed to be portable between different + * platforms or versions. With the exception of `secp256k1_musig_secnonce`, the + * data structures can be safely copied/moved. If you need to convert to a + * format suitable for storage, transmission, or comparison, use the + * corresponding serialization and parsing functions. + */ + +/** Opaque data structure that caches information about public key aggregation. + * + * Guaranteed to be 197 bytes in size. No serialization and parsing functions + * (yet). + */ +typedef struct secp256k1_musig_keyagg_cache { + unsigned char data[197]; +} secp256k1_musig_keyagg_cache; + +/** Opaque data structure that holds a signer's _secret_ nonce. + * + * Guaranteed to be 132 bytes in size. + * + * WARNING: This structure MUST NOT be copied or read or written to directly. A + * signer who is online throughout the whole process and can keep this + * structure in memory can use the provided API functions for a safe standard + * workflow. + * + * Copying this data structure can result in nonce reuse which will leak the + * secret signing key. + */ +typedef struct secp256k1_musig_secnonce { + unsigned char data[132]; +} secp256k1_musig_secnonce; + +/** Opaque data structure that holds a signer's public nonce. + * + * Guaranteed to be 132 bytes in size. Serialized and parsed with + * `musig_pubnonce_serialize` and `musig_pubnonce_parse`. + */ +typedef struct secp256k1_musig_pubnonce { + unsigned char data[132]; +} secp256k1_musig_pubnonce; + +/** Opaque data structure that holds an aggregate public nonce. + * + * Guaranteed to be 132 bytes in size. Serialized and parsed with + * `musig_aggnonce_serialize` and `musig_aggnonce_parse`. + */ +typedef struct secp256k1_musig_aggnonce { + unsigned char data[132]; +} secp256k1_musig_aggnonce; + +/** Opaque data structure that holds a MuSig session. + * + * This structure is not required to be kept secret for the signing protocol to + * be secure. Guaranteed to be 133 bytes in size. No serialization and parsing + * functions (yet). + */ +typedef struct secp256k1_musig_session { + unsigned char data[133]; +} secp256k1_musig_session; + +/** Opaque data structure that holds a partial MuSig signature. + * + * Guaranteed to be 36 bytes in size. Serialized and parsed with + * `musig_partial_sig_serialize` and `musig_partial_sig_parse`. + */ +typedef struct secp256k1_musig_partial_sig { + unsigned char data[36]; +} secp256k1_musig_partial_sig; + +/** Parse a signer's public nonce. + * + * Returns: 1 when the nonce could be parsed, 0 otherwise. + * Args: ctx: pointer to a context object + * Out: nonce: pointer to a nonce object + * In: in66: pointer to the 66-byte nonce to be parsed + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubnonce_parse( + const secp256k1_context *ctx, + secp256k1_musig_pubnonce *nonce, + const unsigned char *in66 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize a signer's public nonce + * + * Returns: 1 always + * Args: ctx: pointer to a context object + * Out: out66: pointer to a 66-byte array to store the serialized nonce + * In: nonce: pointer to the nonce + */ +SECP256K1_API int secp256k1_musig_pubnonce_serialize( + const secp256k1_context *ctx, + unsigned char *out66, + const secp256k1_musig_pubnonce *nonce +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Parse an aggregate public nonce. + * + * Returns: 1 when the nonce could be parsed, 0 otherwise. + * Args: ctx: pointer to a context object + * Out: nonce: pointer to a nonce object + * In: in66: pointer to the 66-byte nonce to be parsed + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_aggnonce_parse( + const secp256k1_context *ctx, + secp256k1_musig_aggnonce *nonce, + const unsigned char *in66 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize an aggregate public nonce + * + * Returns: 1 always + * Args: ctx: pointer to a context object + * Out: out66: pointer to a 66-byte array to store the serialized nonce + * In: nonce: pointer to the nonce + */ +SECP256K1_API int secp256k1_musig_aggnonce_serialize( + const secp256k1_context *ctx, + unsigned char *out66, + const secp256k1_musig_aggnonce *nonce +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Parse a MuSig partial signature. + * + * Returns: 1 when the signature could be parsed, 0 otherwise. + * Args: ctx: pointer to a context object + * Out: sig: pointer to a signature object + * In: in32: pointer to the 32-byte signature to be parsed + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_parse( + const secp256k1_context *ctx, + secp256k1_musig_partial_sig *sig, + const unsigned char *in32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize a MuSig partial signature + * + * Returns: 1 always + * Args: ctx: pointer to a context object + * Out: out32: pointer to a 32-byte array to store the serialized signature + * In: sig: pointer to the signature + */ +SECP256K1_API int secp256k1_musig_partial_sig_serialize( + const secp256k1_context *ctx, + unsigned char *out32, + const secp256k1_musig_partial_sig *sig +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Computes an aggregate public key and uses it to initialize a keyagg_cache + * + * Different orders of `pubkeys` result in different `agg_pk`s. + * + * Before aggregating, the pubkeys can be sorted with `secp256k1_ec_pubkey_sort` + * which ensures the same `agg_pk` result for the same multiset of pubkeys. + * This is useful to do before `pubkey_agg`, such that the order of pubkeys + * does not affect the aggregate public key. + * + * Returns: 0 if the arguments are invalid, 1 otherwise + * Args: ctx: pointer to a context object + * Out: agg_pk: the MuSig-aggregated x-only public key. If you do not need it, + * this arg can be NULL. + * keyagg_cache: if non-NULL, pointer to a musig_keyagg_cache struct that + * is required for signing (or observing the signing session + * and verifying partial signatures). + * In: pubkeys: input array of pointers to public keys to aggregate. The order + * is important; a different order will result in a different + * aggregate public key. + * n_pubkeys: length of pubkeys array. Must be greater than 0. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_agg( + const secp256k1_context *ctx, + secp256k1_xonly_pubkey *agg_pk, + secp256k1_musig_keyagg_cache *keyagg_cache, + const secp256k1_pubkey * const *pubkeys, + size_t n_pubkeys +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(4); + +/** Obtain the aggregate public key from a keyagg_cache. + * + * This is only useful if you need the non-xonly public key, in particular for + * plain (non-xonly) tweaking or batch-verifying multiple key aggregations + * (not implemented). + * + * Returns: 0 if the arguments are invalid, 1 otherwise + * Args: ctx: pointer to a context object + * Out: agg_pk: the MuSig-aggregated public key. + * In: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by + * `musig_pubkey_agg` + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_get( + const secp256k1_context *ctx, + secp256k1_pubkey *agg_pk, + const secp256k1_musig_keyagg_cache *keyagg_cache +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Apply plain "EC" tweaking to a public key in a given keyagg_cache by adding + * the generator multiplied with `tweak32` to it. This is useful for deriving + * child keys from an aggregate public key via BIP 32 where `tweak32` is set to + * a hash as defined in BIP 32. + * + * Callers are responsible for deriving `tweak32` in a way that does not reduce + * the security of MuSig (for example, by following BIP 32). + * + * The tweaking method is the same as `secp256k1_ec_pubkey_tweak_add`. So after + * the following pseudocode buf and buf2 have identical contents (absent + * earlier failures). + * + * secp256k1_musig_pubkey_agg(..., keyagg_cache, pubkeys, ...) + * secp256k1_musig_pubkey_get(..., agg_pk, keyagg_cache) + * secp256k1_musig_pubkey_ec_tweak_add(..., output_pk, tweak32, keyagg_cache) + * secp256k1_ec_pubkey_serialize(..., buf, ..., output_pk, ...) + * secp256k1_ec_pubkey_tweak_add(..., agg_pk, tweak32) + * secp256k1_ec_pubkey_serialize(..., buf2, ..., agg_pk, ...) + * + * This function is required if you want to _sign_ for a tweaked aggregate key. + * If you are only computing a public key but not intending to create a + * signature for it, use `secp256k1_ec_pubkey_tweak_add` instead. + * + * Returns: 0 if the arguments are invalid, 1 otherwise + * Args: ctx: pointer to a context object + * Out: output_pubkey: pointer to a public key to store the result. Will be set + * to an invalid value if this function returns 0. If you + * do not need it, this arg can be NULL. + * In/Out: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by + * `musig_pubkey_agg` + * In: tweak32: pointer to a 32-byte tweak. The tweak is valid if it passes + * `secp256k1_ec_seckey_verify` and is not equal to the + * secret key corresponding to the public key represented + * by keyagg_cache or its negation. For uniformly random + * 32-byte arrays the chance of being invalid is + * negligible (around 1 in 2^128). + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_ec_tweak_add( + const secp256k1_context *ctx, + secp256k1_pubkey *output_pubkey, + secp256k1_musig_keyagg_cache *keyagg_cache, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Apply x-only tweaking to a public key in a given keyagg_cache by adding the + * generator multiplied with `tweak32` to it. This is useful for creating + * Taproot outputs where `tweak32` is set to a TapTweak hash as defined in BIP + * 341. + * + * Callers are responsible for deriving `tweak32` in a way that does not reduce + * the security of MuSig (for example, by following Taproot BIP 341). + * + * The tweaking method is the same as `secp256k1_xonly_pubkey_tweak_add`. So in + * the following pseudocode xonly_pubkey_tweak_add_check (absent earlier + * failures) returns 1. + * + * secp256k1_musig_pubkey_agg(..., agg_pk, keyagg_cache, pubkeys, ...) + * secp256k1_musig_pubkey_xonly_tweak_add(..., output_pk, keyagg_cache, tweak32) + * secp256k1_xonly_pubkey_serialize(..., buf, output_pk) + * secp256k1_xonly_pubkey_tweak_add_check(..., buf, ..., agg_pk, tweak32) + * + * This function is required if you want to _sign_ for a tweaked aggregate key. + * If you are only computing a public key but not intending to create a + * signature for it, use `secp256k1_xonly_pubkey_tweak_add` instead. + * + * Returns: 0 if the arguments are invalid, 1 otherwise + * Args: ctx: pointer to a context object + * Out: output_pubkey: pointer to a public key to store the result. Will be set + * to an invalid value if this function returns 0. If you + * do not need it, this arg can be NULL. + * In/Out: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by + * `musig_pubkey_agg` + * In: tweak32: pointer to a 32-byte tweak. The tweak is valid if it passes + * `secp256k1_ec_seckey_verify` and is not equal to the + * secret key corresponding to the public key represented + * by keyagg_cache or its negation. For uniformly random + * 32-byte arrays the chance of being invalid is + * negligible (around 1 in 2^128). + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_xonly_tweak_add( + const secp256k1_context *ctx, + secp256k1_pubkey *output_pubkey, + secp256k1_musig_keyagg_cache *keyagg_cache, + const unsigned char *tweak32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Starts a signing session by generating a nonce + * + * This function outputs a secret nonce that will be required for signing and a + * corresponding public nonce that is intended to be sent to other signers. + * + * MuSig differs from regular Schnorr signing in that implementers _must_ take + * special care to not reuse a nonce. This can be ensured by following these rules: + * + * 1. Each call to this function must have a UNIQUE session_secrand32 that must + * NOT BE REUSED in subsequent calls to this function and must be KEPT + * SECRET (even from other signers). + * 2. If you already know the seckey, message or aggregate public key + * cache, they can be optionally provided to derive the nonce and increase + * misuse-resistance. The extra_input32 argument can be used to provide + * additional data that does not repeat in normal scenarios, such as the + * current time. + * 3. Avoid copying (or serializing) the secnonce. This reduces the possibility + * that it is used more than once for signing. + * + * If you don't have access to good randomness for session_secrand32, but you + * have access to a non-repeating counter, then see + * secp256k1_musig_nonce_gen_counter. + * + * Remember that nonce reuse will leak the secret key! + * Note that using the same seckey for multiple MuSig sessions is fine. + * + * Returns: 0 if the arguments are invalid and 1 otherwise + * Args: ctx: pointer to a context object (not secp256k1_context_static) + * Out: secnonce: pointer to a structure to store the secret nonce + * pubnonce: pointer to a structure to store the public nonce + * In/Out: + * session_secrand32: a 32-byte session_secrand32 as explained above. Must be unique to this + * call to secp256k1_musig_nonce_gen and must be uniformly + * random. If the function call is successful, the + * session_secrand32 buffer is invalidated to prevent reuse. + * In: + * seckey: the 32-byte secret key that will later be used for signing, if + * already known (can be NULL) + * pubkey: public key of the signer creating the nonce. The secnonce + * output of this function cannot be used to sign for any + * other public key. While the public key should correspond + * to the provided seckey, a mismatch will not cause the + * function to return 0. + * msg32: the 32-byte message that will later be signed, if already known + * (can be NULL) + * keyagg_cache: pointer to the keyagg_cache that was used to create the aggregate + * (and potentially tweaked) public key if already known + * (can be NULL) + * extra_input32: an optional 32-byte array that is input to the nonce + * derivation function (can be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_gen( + const secp256k1_context *ctx, + secp256k1_musig_secnonce *secnonce, + secp256k1_musig_pubnonce *pubnonce, + unsigned char *session_secrand32, + const unsigned char *seckey, + const secp256k1_pubkey *pubkey, + const unsigned char *msg32, + const secp256k1_musig_keyagg_cache *keyagg_cache, + const unsigned char *extra_input32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(6); + + +/** Alternative way to generate a nonce and start a signing session + * + * This function outputs a secret nonce that will be required for signing and a + * corresponding public nonce that is intended to be sent to other signers. + * + * This function differs from `secp256k1_musig_nonce_gen` by accepting a + * non-repeating counter value instead of a secret random value. This requires + * that a secret key is provided to `secp256k1_musig_nonce_gen_counter` + * (through the keypair argument), as opposed to `secp256k1_musig_nonce_gen` + * where the seckey argument is optional. + * + * MuSig differs from regular Schnorr signing in that implementers _must_ take + * special care to not reuse a nonce. This can be ensured by following these rules: + * + * 1. The nonrepeating_cnt argument must be a counter value that never repeats, + * i.e., you must never call `secp256k1_musig_nonce_gen_counter` twice with + * the same keypair and nonrepeating_cnt value. For example, this implies + * that if the same keypair is used with `secp256k1_musig_nonce_gen_counter` + * on multiple devices, none of the devices should have the same counter + * value as any other device. + * 2. If the seckey, message or aggregate public key cache is already available + * at this stage, any of these can be optionally provided, in which case + * they will be used in the derivation of the nonce and increase + * misuse-resistance. The extra_input32 argument can be used to provide + * additional data that does not repeat in normal scenarios, such as the + * current time. + * 3. Avoid copying (or serializing) the secnonce. This reduces the possibility + * that it is used more than once for signing. + * + * Remember that nonce reuse will leak the secret key! + * Note that using the same keypair for multiple MuSig sessions is fine. + * + * Returns: 0 if the arguments are invalid and 1 otherwise + * Args: ctx: pointer to a context object (not secp256k1_context_static) + * Out: secnonce: pointer to a structure to store the secret nonce + * pubnonce: pointer to a structure to store the public nonce + * In: + * nonrepeating_cnt: the value of a counter as explained above. Must be + * unique to this call to secp256k1_musig_nonce_gen. + * keypair: keypair of the signer creating the nonce. The secnonce + * output of this function cannot be used to sign for any + * other keypair. + * msg32: the 32-byte message that will later be signed, if already known + * (can be NULL) + * keyagg_cache: pointer to the keyagg_cache that was used to create the aggregate + * (and potentially tweaked) public key if already known + * (can be NULL) + * extra_input32: an optional 32-byte array that is input to the nonce + * derivation function (can be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_gen_counter( + const secp256k1_context *ctx, + secp256k1_musig_secnonce *secnonce, + secp256k1_musig_pubnonce *pubnonce, + uint64_t nonrepeating_cnt, + const secp256k1_keypair *keypair, + const unsigned char *msg32, + const secp256k1_musig_keyagg_cache *keyagg_cache, + const unsigned char *extra_input32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5); + +/** Aggregates the nonces of all signers into a single nonce + * + * This can be done by an untrusted party to reduce the communication + * between signers. Instead of everyone sending nonces to everyone else, there + * can be one party receiving all nonces, aggregating the nonces with this + * function and then sending only the aggregate nonce back to the signers. + * + * If the aggregator does not compute the aggregate nonce correctly, the final + * signature will be invalid. + * + * Returns: 0 if the arguments are invalid, 1 otherwise + * Args: ctx: pointer to a context object + * Out: aggnonce: pointer to an aggregate public nonce object for + * musig_nonce_process + * In: pubnonces: array of pointers to public nonces sent by the + * signers + * n_pubnonces: number of elements in the pubnonces array. Must be + * greater than 0. + */ +SECP256K1_API int secp256k1_musig_nonce_agg( + const secp256k1_context *ctx, + secp256k1_musig_aggnonce *aggnonce, + const secp256k1_musig_pubnonce * const *pubnonces, + size_t n_pubnonces +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Takes the aggregate nonce and creates a session that is required for signing + * and verification of partial signatures. + * + * Returns: 0 if the arguments are invalid, 1 otherwise + * Args: ctx: pointer to a context object + * Out: session: pointer to a struct to store the session + * In: aggnonce: pointer to an aggregate public nonce object that is the + * output of musig_nonce_agg + * msg32: the 32-byte message to sign + * keyagg_cache: pointer to the keyagg_cache that was used to create the + * aggregate (and potentially tweaked) pubkey + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_process( + const secp256k1_context *ctx, + secp256k1_musig_session *session, + const secp256k1_musig_aggnonce *aggnonce, + const unsigned char *msg32, + const secp256k1_musig_keyagg_cache *keyagg_cache +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); + +/** Produces a partial signature + * + * This function overwrites the given secnonce with zeros and will abort if given a + * secnonce that is all zeros. This is a best effort attempt to protect against nonce + * reuse. However, this is of course easily defeated if the secnonce has been + * copied (or serialized). Remember that nonce reuse will leak the secret key! + * + * For signing to succeed, the secnonce provided to this function must have + * been generated for the provided keypair. This means that when signing for a + * keypair consisting of a seckey and pubkey, the secnonce must have been + * created by calling musig_nonce_gen with that pubkey. Otherwise, the + * illegal_callback is called. + * + * This function does not verify the output partial signature, deviating from + * the BIP 327 specification. It is recommended to verify the output partial + * signature with `secp256k1_musig_partial_sig_verify` to prevent random or + * adversarially provoked computation errors. + * + * Returns: 0 if the arguments are invalid or the provided secnonce has already + * been used for signing, 1 otherwise + * Args: ctx: pointer to a context object + * Out: partial_sig: pointer to struct to store the partial signature + * In/Out: secnonce: pointer to the secnonce struct created in + * musig_nonce_gen that has been never used in a + * partial_sign call before and has been created for the + * keypair + * In: keypair: pointer to keypair to sign the message with + * keyagg_cache: pointer to the keyagg_cache that was output when the + * aggregate public key for this session + * session: pointer to the session that was created with + * musig_nonce_process + */ +SECP256K1_API int secp256k1_musig_partial_sign( + const secp256k1_context *ctx, + secp256k1_musig_partial_sig *partial_sig, + secp256k1_musig_secnonce *secnonce, + const secp256k1_keypair *keypair, + const secp256k1_musig_keyagg_cache *keyagg_cache, + const secp256k1_musig_session *session +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6); + +/** Verifies an individual signer's partial signature + * + * The signature is verified for a specific signing session. In order to avoid + * accidentally verifying a signature from a different or non-existing signing + * session, you must ensure the following: + * 1. The `keyagg_cache` argument is identical to the one used to create the + * `session` with `musig_nonce_process`. + * 2. The `pubkey` argument must be identical to the one sent by the signer + * before aggregating it with `musig_pubkey_agg` to create the + * `keyagg_cache`. + * 3. The `pubnonce` argument must be identical to the one sent by the signer + * before aggregating it with `musig_nonce_agg` and using the result to + * create the `session` with `musig_nonce_process`. + * + * It is not required to call this function in regular MuSig sessions, because + * if any partial signature does not verify, the final signature will not + * verify either, so the problem will be caught. However, this function + * provides the ability to identify which specific partial signature fails + * verification. + * + * Returns: 0 if the arguments are invalid or the partial signature does not + * verify, 1 otherwise + * Args ctx: pointer to a context object + * In: partial_sig: pointer to partial signature to verify, sent by + * the signer associated with `pubnonce` and `pubkey` + * pubnonce: public nonce of the signer in the signing session + * pubkey: public key of the signer in the signing session + * keyagg_cache: pointer to the keyagg_cache that was output when the + * aggregate public key for this signing session + * session: pointer to the session that was created with + * `musig_nonce_process` + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_verify( + const secp256k1_context *ctx, + const secp256k1_musig_partial_sig *partial_sig, + const secp256k1_musig_pubnonce *pubnonce, + const secp256k1_pubkey *pubkey, + const secp256k1_musig_keyagg_cache *keyagg_cache, + const secp256k1_musig_session *session +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6); + +/** Aggregates partial signatures + * + * Returns: 0 if the arguments are invalid, 1 otherwise (which does NOT mean + * the resulting signature verifies). + * Args: ctx: pointer to a context object + * Out: sig64: complete (but possibly invalid) Schnorr signature + * In: session: pointer to the session that was created with + * musig_nonce_process + * partial_sigs: array of pointers to partial signatures to aggregate + * n_sigs: number of elements in the partial_sigs array. Must be + * greater than 0. + */ +SECP256K1_API int secp256k1_musig_partial_sig_agg( + const secp256k1_context *ctx, + unsigned char *sig64, + const secp256k1_musig_session *session, + const secp256k1_musig_partial_sig * const *partial_sigs, + size_t n_sigs +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/example/android/third_party/secp256k1/include/secp256k1_preallocated.h b/example/android/third_party/secp256k1/include/secp256k1_preallocated.h index a9ae15d5a..f2d95c245 100644 --- a/example/android/third_party/secp256k1/include/secp256k1_preallocated.h +++ b/example/android/third_party/secp256k1/include/secp256k1_preallocated.h @@ -52,17 +52,19 @@ SECP256K1_API size_t secp256k1_context_preallocated_size( * in the memory. In simpler words, the prealloc pointer (or any pointer derived * from it) should not be used during the lifetime of the context object. * - * Returns: a newly created context object. - * In: prealloc: a pointer to a rewritable contiguous block of memory of + * Returns: pointer to newly created context object. + * In: prealloc: pointer to a rewritable contiguous block of memory of * size at least secp256k1_context_preallocated_size(flags) - * bytes, as detailed above (cannot be NULL) + * bytes, as detailed above. * flags: which parts of the context to initialize. * + * See secp256k1_context_create (in secp256k1.h) for further details. + * * See also secp256k1_context_randomize (in secp256k1.h) * and secp256k1_context_preallocated_destroy. */ -SECP256K1_API secp256k1_context* secp256k1_context_preallocated_create( - void* prealloc, +SECP256K1_API secp256k1_context *secp256k1_context_preallocated_create( + void *prealloc, unsigned int flags ) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; @@ -70,10 +72,10 @@ SECP256K1_API secp256k1_context* secp256k1_context_preallocated_create( * caller-provided memory. * * Returns: the required size of the caller-provided memory block. - * In: ctx: an existing context to copy (cannot be NULL) + * In: ctx: pointer to a context to copy. */ SECP256K1_API size_t secp256k1_context_preallocated_clone_size( - const secp256k1_context* ctx + const secp256k1_context *ctx ) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; /** Copy a secp256k1 context object into caller-provided memory. @@ -86,15 +88,18 @@ SECP256K1_API size_t secp256k1_context_preallocated_clone_size( * the lifetime of this context object, see the description of * secp256k1_context_preallocated_create for details. * - * Returns: a newly created context object. - * Args: ctx: an existing context to copy (cannot be NULL) - * In: prealloc: a pointer to a rewritable contiguous block of memory of + * Cloning secp256k1_context_static is not possible, and should not be emulated by + * the caller (e.g., using memcpy). Create a new context instead. + * + * Returns: pointer to a newly created context object. + * Args: ctx: pointer to a context to copy (not secp256k1_context_static). + * In: prealloc: pointer to a rewritable contiguous block of memory of * size at least secp256k1_context_preallocated_size(flags) - * bytes, as detailed above (cannot be NULL) + * bytes, as detailed above. */ -SECP256K1_API secp256k1_context* secp256k1_context_preallocated_clone( - const secp256k1_context* ctx, - void* prealloc +SECP256K1_API secp256k1_context *secp256k1_context_preallocated_clone( + const secp256k1_context *ctx, + void *prealloc ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_WARN_UNUSED_RESULT; /** Destroy a secp256k1 context object that has been created in @@ -113,13 +118,14 @@ SECP256K1_API secp256k1_context* secp256k1_context_preallocated_clone( * preallocated pointer given to secp256k1_context_preallocated_create or * secp256k1_context_preallocated_clone. * - * Args: ctx: an existing context to destroy, constructed using + * Args: ctx: pointer to a context to destroy, constructed using * secp256k1_context_preallocated_create or - * secp256k1_context_preallocated_clone (cannot be NULL) + * secp256k1_context_preallocated_clone + * (i.e., not secp256k1_context_static). */ SECP256K1_API void secp256k1_context_preallocated_destroy( - secp256k1_context* ctx -); + secp256k1_context *ctx +) SECP256K1_ARG_NONNULL(1); #ifdef __cplusplus } diff --git a/example/android/third_party/secp256k1/include/secp256k1_recovery.h b/example/android/third_party/secp256k1/include/secp256k1_recovery.h index cf6c5ed7f..93a2e4ccb 100644 --- a/example/android/third_party/secp256k1/include/secp256k1_recovery.h +++ b/example/android/third_party/secp256k1/include/secp256k1_recovery.h @@ -7,7 +7,7 @@ extern "C" { #endif -/** Opaque data structured that holds a parsed ECDSA signature, +/** Opaque data structure that holds a parsed ECDSA signature, * supporting pubkey recovery. * * The exact representation of data inside is implementation defined and not @@ -21,21 +21,21 @@ extern "C" { * recoverability) will have identical representation, so they can be * memcmp'ed. */ -typedef struct { +typedef struct secp256k1_ecdsa_recoverable_signature { unsigned char data[65]; } secp256k1_ecdsa_recoverable_signature; /** Parse a compact ECDSA signature (64 bytes + recovery id). * * Returns: 1 when the signature could be parsed, 0 otherwise - * Args: ctx: a secp256k1 context object - * Out: sig: a pointer to a signature object - * In: input64: a pointer to a 64-byte compact signature + * Args: ctx: pointer to a context object + * Out: sig: pointer to a signature object + * In: input64: pointer to a 64-byte compact signature * recid: the recovery id (0, 1, 2 or 3) */ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact( - const secp256k1_context* ctx, - secp256k1_ecdsa_recoverable_signature* sig, + const secp256k1_context *ctx, + secp256k1_ecdsa_recoverable_signature *sig, const unsigned char *input64, int recid ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); @@ -43,45 +43,48 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact( /** Convert a recoverable signature into a normal signature. * * Returns: 1 - * Out: sig: a pointer to a normal signature (cannot be NULL). - * In: sigin: a pointer to a recoverable signature (cannot be NULL). + * Args: ctx: pointer to a context object. + * Out: sig: pointer to a normal signature. + * In: sigin: pointer to a recoverable signature. */ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert( - const secp256k1_context* ctx, - secp256k1_ecdsa_signature* sig, - const secp256k1_ecdsa_recoverable_signature* sigin + const secp256k1_context *ctx, + secp256k1_ecdsa_signature *sig, + const secp256k1_ecdsa_recoverable_signature *sigin ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Serialize an ECDSA signature in compact format (64 bytes + recovery id). * * Returns: 1 - * Args: ctx: a secp256k1 context object - * Out: output64: a pointer to a 64-byte array of the compact signature (cannot be NULL) - * recid: a pointer to an integer to hold the recovery id (can be NULL). - * In: sig: a pointer to an initialized signature object (cannot be NULL) + * Args: ctx: pointer to a context object. + * Out: output64: pointer to a 64-byte array of the compact signature. + * recid: pointer to an integer to hold the recovery id. + * In: sig: pointer to an initialized signature object. */ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact( - const secp256k1_context* ctx, + const secp256k1_context *ctx, unsigned char *output64, int *recid, - const secp256k1_ecdsa_recoverable_signature* sig + const secp256k1_ecdsa_recoverable_signature *sig ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Create a recoverable ECDSA signature. * * Returns: 1: signature created - * 0: the nonce generation function failed, or the private key was invalid. - * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) - * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) - * In: msg32: the 32-byte message hash being signed (cannot be NULL) - * seckey: pointer to a 32-byte secret key (cannot be NULL) - * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used - * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) + * 0: the nonce generation function failed, or the secret key was invalid. + * Args: ctx: pointer to a context object (not secp256k1_context_static). + * Out: sig: pointer to an array where the signature will be placed. + * In: msghash32: the 32-byte message hash being signed. + * seckey: pointer to a 32-byte secret key. + * noncefp: pointer to a nonce generation function. If NULL, + * secp256k1_nonce_function_default is used. + * ndata: pointer to arbitrary data used by the nonce generation function + * (can be NULL for secp256k1_nonce_function_default). */ SECP256K1_API int secp256k1_ecdsa_sign_recoverable( - const secp256k1_context* ctx, + const secp256k1_context *ctx, secp256k1_ecdsa_recoverable_signature *sig, - const unsigned char *msg32, + const unsigned char *msghash32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void *ndata @@ -91,16 +94,16 @@ SECP256K1_API int secp256k1_ecdsa_sign_recoverable( * * Returns: 1: public key successfully recovered (which guarantees a correct signature). * 0: otherwise. - * Args: ctx: pointer to a context object, initialized for verification (cannot be NULL) - * Out: pubkey: pointer to the recovered public key (cannot be NULL) - * In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL) - * msg32: the 32-byte message hash assumed to be signed (cannot be NULL) + * Args: ctx: pointer to a context object. + * Out: pubkey: pointer to the recovered public key. + * In: sig: pointer to initialized signature that supports pubkey recovery. + * msghash32: the 32-byte message hash assumed to be signed. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover( - const secp256k1_context* ctx, + const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const secp256k1_ecdsa_recoverable_signature *sig, - const unsigned char *msg32 + const unsigned char *msghash32 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); #ifdef __cplusplus diff --git a/example/android/third_party/secp256k1/include/secp256k1_schnorrsig.h b/example/android/third_party/secp256k1/include/secp256k1_schnorrsig.h new file mode 100644 index 000000000..013d4ee73 --- /dev/null +++ b/example/android/third_party/secp256k1/include/secp256k1_schnorrsig.h @@ -0,0 +1,190 @@ +#ifndef SECP256K1_SCHNORRSIG_H +#define SECP256K1_SCHNORRSIG_H + +#include "secp256k1.h" +#include "secp256k1_extrakeys.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** This module implements a variant of Schnorr signatures compliant with + * Bitcoin Improvement Proposal 340 "Schnorr Signatures for secp256k1" + * (https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki). + */ + +/** A pointer to a function to deterministically generate a nonce. + * + * Same as secp256k1_nonce function with the exception of accepting an + * additional pubkey argument and not requiring an attempt argument. The pubkey + * argument can protect signature schemes with key-prefixed challenge hash + * inputs against reusing the nonce when signing with the wrong precomputed + * pubkey. + * + * Returns: 1 if a nonce was successfully generated. 0 will cause signing to + * return an error. + * Out: nonce32: pointer to a 32-byte array to be filled by the function + * In: msg: the message being verified. Is NULL if and only if msglen + * is 0. + * msglen: the length of the message + * key32: pointer to a 32-byte secret key (will not be NULL) + * xonly_pk32: the 32-byte serialized xonly pubkey corresponding to key32 + * (will not be NULL) + * algo: pointer to an array describing the signature + * algorithm (will not be NULL) + * algolen: the length of the algo array + * data: arbitrary data pointer that is passed through + * + * Except for test cases, this function should compute some cryptographic hash of + * the message, the key, the pubkey, the algorithm description, and data. + */ +typedef int (*secp256k1_nonce_function_hardened)( + unsigned char *nonce32, + const unsigned char *msg, + size_t msglen, + const unsigned char *key32, + const unsigned char *xonly_pk32, + const unsigned char *algo, + size_t algolen, + void *data +); + +/** An implementation of the nonce generation function as defined in Bitcoin + * Improvement Proposal 340 "Schnorr Signatures for secp256k1" + * (https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki). + * + * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of + * auxiliary random data as defined in BIP-340. If the data pointer is NULL, + * the nonce derivation procedure follows BIP-340 by setting the auxiliary + * random data to zero. The algo argument must be non-NULL, otherwise the + * function will fail and return 0. The hash will be tagged with algo. + * Therefore, to create BIP-340 compliant signatures, algo must be set to + * "BIP0340/nonce" and algolen to 13. + */ +SECP256K1_API const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340; + +/** Data structure that contains additional arguments for schnorrsig_sign_custom. + * + * A schnorrsig_extraparams structure object can be initialized correctly by + * setting it to SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT. + * + * Members: + * magic: set to SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC at initialization + * and has no other function than making sure the object is + * initialized. + * noncefp: pointer to a nonce generation function. If NULL, + * secp256k1_nonce_function_bip340 is used + * ndata: pointer to arbitrary data used by the nonce generation function + * (can be NULL). If it is non-NULL and + * secp256k1_nonce_function_bip340 is used, then ndata must be a + * pointer to 32-byte auxiliary randomness as per BIP-340. + */ +typedef struct secp256k1_schnorrsig_extraparams { + unsigned char magic[4]; + secp256k1_nonce_function_hardened noncefp; + void *ndata; +} secp256k1_schnorrsig_extraparams; + +#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC { 0xda, 0x6f, 0xb3, 0x8c } +#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT {\ + SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC,\ + NULL,\ + NULL\ +} + +/** Create a Schnorr signature. + * + * Does _not_ strictly follow BIP-340 because it does not verify the resulting + * signature. Instead, you can manually use secp256k1_schnorrsig_verify and + * abort if it fails. + * + * This function only signs 32-byte messages. If you have messages of a + * different size (or the same size but without a context-specific tag + * prefix), it is recommended to create a 32-byte message hash with + * secp256k1_tagged_sha256 and then sign the hash. Tagged hashing allows + * providing an context-specific tag for domain separation. This prevents + * signatures from being valid in multiple contexts by accident. + * + * Returns 1 on success, 0 on failure. + * Args: ctx: pointer to a context object (not secp256k1_context_static). + * Out: sig64: pointer to a 64-byte array to store the serialized signature. + * In: msg32: the 32-byte message being signed. + * keypair: pointer to an initialized keypair. + * aux_rand32: 32 bytes of fresh randomness. While recommended to provide + * this, it is only supplemental to security and can be NULL. A + * NULL argument is treated the same as an all-zero one. See + * BIP-340 "Default Signing" for a full explanation of this + * argument and for guidance if randomness is expensive. + */ +SECP256K1_API int secp256k1_schnorrsig_sign32( + const secp256k1_context *ctx, + unsigned char *sig64, + const unsigned char *msg32, + const secp256k1_keypair *keypair, + const unsigned char *aux_rand32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Same as secp256k1_schnorrsig_sign32, but DEPRECATED. Will be removed in + * future versions. */ +SECP256K1_API int secp256k1_schnorrsig_sign( + const secp256k1_context *ctx, + unsigned char *sig64, + const unsigned char *msg32, + const secp256k1_keypair *keypair, + const unsigned char *aux_rand32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) + SECP256K1_DEPRECATED("Use secp256k1_schnorrsig_sign32 instead"); + +/** Create a Schnorr signature with a more flexible API. + * + * Same arguments as secp256k1_schnorrsig_sign except that it allows signing + * variable length messages and accepts a pointer to an extraparams object that + * allows customizing signing by passing additional arguments. + * + * Equivalent to secp256k1_schnorrsig_sign32(..., aux_rand32) if msglen is 32 + * and extraparams is initialized as follows: + * ``` + * secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT; + * extraparams.ndata = (unsigned char*)aux_rand32; + * ``` + * + * Returns 1 on success, 0 on failure. + * Args: ctx: pointer to a context object (not secp256k1_context_static). + * Out: sig64: pointer to a 64-byte array to store the serialized signature. + * In: msg: the message being signed. Can only be NULL if msglen is 0. + * msglen: length of the message. + * keypair: pointer to an initialized keypair. + * extraparams: pointer to an extraparams object (can be NULL). + */ +SECP256K1_API int secp256k1_schnorrsig_sign_custom( + const secp256k1_context *ctx, + unsigned char *sig64, + const unsigned char *msg, + size_t msglen, + const secp256k1_keypair *keypair, + secp256k1_schnorrsig_extraparams *extraparams +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(5); + +/** Verify a Schnorr signature. + * + * Returns: 1: correct signature + * 0: incorrect signature + * Args: ctx: pointer to a context object. + * In: sig64: pointer to the 64-byte signature to verify. + * msg: the message being verified. Can only be NULL if msglen is 0. + * msglen: length of the message + * pubkey: pointer to an x-only public key to verify with + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorrsig_verify( + const secp256k1_context *ctx, + const unsigned char *sig64, + const unsigned char *msg, + size_t msglen, + const secp256k1_xonly_pubkey *pubkey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(5); + +#ifdef __cplusplus +} +#endif + +#endif /* SECP256K1_SCHNORRSIG_H */ diff --git a/example/android/third_party/secp256k1/libsecp256k1.a b/example/android/third_party/secp256k1/libsecp256k1.a deleted file mode 100644 index 0b3daaab7..000000000 Binary files a/example/android/third_party/secp256k1/libsecp256k1.a and /dev/null differ diff --git a/example/android/third_party/secp256k1/libsecp256k1.so b/example/android/third_party/secp256k1/libsecp256k1.so deleted file mode 100644 index 784af2617..000000000 Binary files a/example/android/third_party/secp256k1/libsecp256k1.so and /dev/null differ diff --git a/example/android/third_party/secp256k1/x86-64/libsecp256k1.a b/example/android/third_party/secp256k1/x86-64/libsecp256k1.a index 9f1a28d81..869dc5e62 100644 Binary files a/example/android/third_party/secp256k1/x86-64/libsecp256k1.a and b/example/android/third_party/secp256k1/x86-64/libsecp256k1.a differ diff --git a/example/android/third_party/secp256k1/x86-64/libsecp256k1.so b/example/android/third_party/secp256k1/x86-64/libsecp256k1.so deleted file mode 100644 index 077f47acc..000000000 Binary files a/example/android/third_party/secp256k1/x86-64/libsecp256k1.so and /dev/null differ diff --git a/test/regression-tests.ans b/test/regression-tests.ans index bfea70895..14d5958b2 100644 --- a/test/regression-tests.ans +++ b/test/regression-tests.ans @@ -21,6 +21,7 @@ Test_Fift_test_hmap_default c269246882039824bb5822e896c3e6e82ef8e1251b6b251f5af8 Test_Fift_test_levels_default 9fba4a7c98aec9000f42846d6e5fd820343ba61d68f9139dd16c88ccda757cf3 Test_Fift_test_namespaces_default e6419619c51332fb5e8bf22043ef415db686c47fe24f03061e5ad831014e7c6c Test_Fift_test_rist255_default f4d7558f200a656934f986145c19b1dedbe2ad029292a5a975576d6891e25fc4 +Test_Fift_test_secp256k1_default 3118450dace6af05fcdbd54a87d9446162ce11ac6ef6dfc57998cf113587d602 Test_Fift_test_sort2_default 9b57d47e6a10e7d1bbb565db35400debf2f963031f434742a702ec76555a5d3a Test_Fift_test_sort_default 9b57d47e6a10e7d1bbb565db35400debf2f963031f434742a702ec76555a5d3a Test_Fift_test_tvm_runvm_default ff3d2a4031b543c18d6b555f0a1f1a891c7825e6d1e2e9beb4bf13b37441450b diff --git a/third-party/secp256k1 b/third-party/secp256k1 new file mode 160000 index 000000000..acf5c55ae --- /dev/null +++ b/third-party/secp256k1 @@ -0,0 +1 @@ +Subproject commit acf5c55ae6a94e5ca847e07def40427547876101