Skip to content

Add an experimental batch module #1134

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 34 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ env:
SCHNORRSIG: 'no'
MUSIG: 'no'
ELLSWIFT: 'no'
BATCH: 'no'
### test options
SECP256K1_TEST_ITERS: 64
BENCH: 'yes'
Expand Down Expand Up @@ -74,18 +75,18 @@ jobs:
matrix:
configuration:
- env_vars: { WIDEMUL: 'int64', RECOVERY: 'yes' }
- env_vars: { WIDEMUL: 'int64', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
- env_vars: { WIDEMUL: 'int64', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
- env_vars: { WIDEMUL: 'int128' }
- env_vars: { WIDEMUL: 'int128_struct', ELLSWIFT: 'yes' }
- env_vars: { WIDEMUL: 'int128', RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
- env_vars: { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes' }
- env_vars: { WIDEMUL: 'int128', RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
- env_vars: { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
- env_vars: { WIDEMUL: 'int128', ASM: 'x86_64', ELLSWIFT: 'yes' }
- env_vars: { RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes' }
- env_vars: { CTIMETESTS: 'no', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', CPPFLAGS: '-DVERIFY' }
- env_vars: { RECOVERY: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
- env_vars: { CTIMETESTS: 'no', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes', CPPFLAGS: '-DVERIFY' }
- env_vars: { BUILD: 'distcheck', WITH_VALGRIND: 'no', CTIMETESTS: 'no', BENCH: 'no' }
- env_vars: { CPPFLAGS: '-DDETERMINISTIC' }
- env_vars: { CFLAGS: '-O0', CTIMETESTS: 'no' }
- env_vars: { CFLAGS: '-O1', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
- env_vars: { CFLAGS: '-O1', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
- env_vars: { ECMULTGENKB: 2, ECMULTWINDOW: 2 }
- env_vars: { ECMULTGENKB: 86, ECMULTWINDOW: 4 }
cc:
Expand Down Expand Up @@ -132,6 +133,8 @@ jobs:
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
BATCH: 'yes'
EXPERIMENTAL: 'yes'
CC: ${{ matrix.cc }}

steps:
Expand Down Expand Up @@ -164,6 +167,8 @@ jobs:
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
BATCH: 'yes'
EXPERIMENTAL: 'yes'
CTIMETESTS: 'no'

steps:
Expand Down Expand Up @@ -204,6 +209,8 @@ jobs:
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
BATCH: 'yes'
EXPERIMENTAL: 'yes'
CTIMETESTS: 'no'

steps:
Expand Down Expand Up @@ -237,6 +244,8 @@ jobs:
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
BATCH: 'yes'
EXPERIMENTAL: 'yes'
CTIMETESTS: 'no'

strategy:
Expand Down Expand Up @@ -280,6 +289,8 @@ jobs:
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
BATCH: 'yes'
EXPERIMENTAL: 'yes'
CTIMETESTS: 'no'

steps:
Expand Down Expand Up @@ -321,6 +332,8 @@ jobs:
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
BATCH: 'yes'
EXPERIMENTAL: 'yes'
CTIMETESTS: 'no'
SECP256K1_TEST_ITERS: 2

Expand Down Expand Up @@ -360,6 +373,8 @@ jobs:
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
BATCH: 'yes'
EXPERIMENTAL: 'yes'
CTIMETESTS: 'no'
CFLAGS: '-fsanitize=undefined,address -g'
UBSAN_OPTIONS: 'print_stacktrace=1:halt_on_error=1'
Expand Down Expand Up @@ -413,6 +428,8 @@ jobs:
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
BATCH: 'yes'
EXPERIMENTAL: 'yes'
CC: 'clang'
SECP256K1_TEST_ITERS: 32
ASM: 'no'
Expand Down Expand Up @@ -449,6 +466,8 @@ jobs:
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
BATCH: 'yes'
EXPERIMENTAL: 'yes'
CTIMETESTS: 'no'

strategy:
Expand Down Expand Up @@ -492,15 +511,15 @@ jobs:
fail-fast: false
matrix:
env_vars:
- { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
- { WIDEMUL: 'int64', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
- { WIDEMUL: 'int128_struct', ECMULTGENKB: 2, ECMULTWINDOW: 4 }
- { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
- { WIDEMUL: 'int128', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
- { WIDEMUL: 'int128', RECOVERY: 'yes' }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes' }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc' }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', CC: 'gcc', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', CPPFLAGS: '-DVERIFY', CTIMETESTS: 'no' }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes' }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes', CC: 'gcc' }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes', CC: 'gcc', WRAPPER_CMD: 'valgrind --error-exitcode=42', SECP256K1_TEST_ITERS: 2 }
- { WIDEMUL: 'int128', RECOVERY: 'yes', ECDH: 'yes', EXTRAKEYS: 'yes', SCHNORRSIG: 'yes', MUSIG: 'yes', ELLSWIFT: 'yes', BATCH: 'yes', EXPERIMENTAL: 'yes', CPPFLAGS: '-DVERIFY', CTIMETESTS: 'no' }
- BUILD: 'distcheck'

steps:
Expand Down Expand Up @@ -669,6 +688,8 @@ jobs:
SCHNORRSIG: 'yes'
MUSIG: 'yes'
ELLSWIFT: 'yes'
BATCH: 'yes'
EXPERIMENTAL: 'yes'

steps:
- name: Checkout
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ ecdsa_example
schnorr_example
ellswift_example
musig_example
batch_example
*.exe
*.so
*.a
Expand Down
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ option(SECP256K1_ENABLE_MODULE_EXTRAKEYS "Enable extrakeys module." ON)
option(SECP256K1_ENABLE_MODULE_SCHNORRSIG "Enable schnorrsig module." ON)
option(SECP256K1_ENABLE_MODULE_MUSIG "Enable musig module." ON)
option(SECP256K1_ENABLE_MODULE_ELLSWIFT "Enable ElligatorSwift module." ON)
option(SECP256K1_ENABLE_MODULE_BATCH "Enable batch module (experimental)." OFF)

option(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS "Enable external default callback functions." OFF)
if(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS)
Expand Down Expand Up @@ -116,6 +117,9 @@ if(NOT SECP256K1_EXPERIMENTAL)
if(SECP256K1_ASM STREQUAL "arm32")
message(FATAL_ERROR "ARM32 assembly is experimental. Use -DSECP256K1_EXPERIMENTAL=ON to allow.")
endif()
if(SECP256K1_ENABLE_MODULE_BATCH)
message(FATAL_ERROR "The batch module is experimental. Use -DSECP256K1_EXPERIMENTAL=ON to allow.")
endif()
endif()

set(SECP256K1_VALGRIND "AUTO" CACHE STRING "Build with extra checks for running inside Valgrind. [default=AUTO]")
Expand Down Expand Up @@ -284,6 +288,7 @@ message(" extrakeys ........................... ${SECP256K1_ENABLE_MODULE_EXTRA
message(" schnorrsig .......................... ${SECP256K1_ENABLE_MODULE_SCHNORRSIG}")
message(" musig ............................... ${SECP256K1_ENABLE_MODULE_MUSIG}")
message(" ElligatorSwift ...................... ${SECP256K1_ENABLE_MODULE_ELLSWIFT}")
message(" batch (experimental) ................ ${SECP256K1_ENABLE_MODULE_BATCH}")
message("Parameters:")
message(" ecmult window size .................. ${SECP256K1_ECMULT_WINDOW_SIZE}")
message(" ecmult gen table size ............... ${SECP256K1_ECMULT_GEN_KB} KiB")
Expand Down
15 changes: 15 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,17 @@ if BUILD_WINDOWS
musig_example_LDFLAGS += -lbcrypt
endif
TESTS += musig_example
if ENABLE_MODULE_BATCH
noinst_PROGRAMS += batch_example
batch_example_SOURCES = examples/batch.c
batch_example_CPPFLAGS = -I$(top_srcdir)/include
batch_example_LDADD = libsecp256k1.la
batch_example_LDFLAGS = -static
if BUILD_WINDOWS
batch_example_LDFLAGS += -lbcrypt
endif
TESTS += batch_example
endif
endif
endif

Expand Down Expand Up @@ -311,3 +322,7 @@ endif
if ENABLE_MODULE_ELLSWIFT
include src/modules/ellswift/Makefile.am.include
endif

if ENABLE_MODULE_BATCH
include src/modules/batch/Makefile.am.include
endif
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Features:
* Optional module for Schnorr signatures according to [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki).
* Optional module for ElligatorSwift key exchange according to [BIP-324](https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki).
* Optional module for MuSig2 Schnorr multi-signatures according to [BIP-327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki).
* Optional module for Batch Verification (experimental).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could also mention "according to BIP340" here since batch verification is also specified there.


Implementation details
----------------------
Expand Down
3 changes: 2 additions & 1 deletion ci/ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ print_environment() {
# does not rely on bash.
for var in WERROR_CFLAGS MAKEFLAGS BUILD \
ECMULTWINDOW ECMULTGENKB ASM WIDEMUL WITH_VALGRIND EXTRAFLAGS \
EXPERIMENTAL ECDH RECOVERY EXTRAKEYS MUSIG SCHNORRSIG ELLSWIFT \
EXPERIMENTAL ECDH RECOVERY EXTRAKEYS MUSIG SCHNORRSIG ELLSWIFT BATCH \
SECP256K1_TEST_ITERS BENCH SECP256K1_BENCH_ITERS CTIMETESTS SYMBOL_CHECK \
EXAMPLES \
HOST WRAPPER_CMD \
Expand Down Expand Up @@ -80,6 +80,7 @@ esac
--enable-module-extrakeys="$EXTRAKEYS" \
--enable-module-schnorrsig="$SCHNORRSIG" \
--enable-module-musig="$MUSIG" \
--enable-module-batch="$BATCH"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing \ here?

--enable-examples="$EXAMPLES" \
--enable-ctime-tests="$CTIMETESTS" \
--with-valgrind="$WITH_VALGRIND" \
Expand Down
13 changes: 13 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ AC_ARG_ENABLE(module_ellswift,
AS_HELP_STRING([--enable-module-ellswift],[enable ElligatorSwift module [default=yes]]), [],
[SECP_SET_DEFAULT([enable_module_ellswift], [yes], [yes])])

AC_ARG_ENABLE(module_batch,
AS_HELP_STRING([--enable-module-batch],[enable batch verification module (experimental) [default=no]]), [],
[SECP_SET_DEFAULT([enable_module_batch], [no], [yes])])

AC_ARG_ENABLE(external_default_callbacks,
AS_HELP_STRING([--enable-external-default-callbacks],[enable external default callback functions [default=no]]), [],
[SECP_SET_DEFAULT([enable_external_default_callbacks], [no], [no])])
Expand Down Expand Up @@ -397,6 +401,10 @@ SECP_CFLAGS="$SECP_CFLAGS $WERROR_CFLAGS"

# Processing must be done in a reverse topological sorting of the dependency graph
# (dependent module first).
if test x"$enable_module_batch" = x"yes"; then
SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_BATCH=1"
fi

if test x"$enable_module_ellswift" = x"yes"; then
SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_ELLSWIFT=1"
fi
Expand Down Expand Up @@ -441,6 +449,9 @@ if test x"$enable_experimental" = x"no"; then
if test x"$set_asm" = x"arm32"; then
AC_MSG_ERROR([ARM32 assembly is experimental. Use --enable-experimental to allow.])
fi
if test x"$enable_module_batch" = x"yes"; then
AC_MSG_ERROR([batch verification module is experimental. Use --enable-experimental to allow.])
fi
fi

###
Expand All @@ -462,6 +473,7 @@ AM_CONDITIONAL([ENABLE_MODULE_EXTRAKEYS], [test x"$enable_module_extrakeys" = x"
AM_CONDITIONAL([ENABLE_MODULE_SCHNORRSIG], [test x"$enable_module_schnorrsig" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_MUSIG], [test x"$enable_module_musig" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_ELLSWIFT], [test x"$enable_module_ellswift" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_BATCH], [test x"$enable_module_batch" = x"yes"])
AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$enable_external_asm" = x"yes"])
AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm32"])
AM_CONDITIONAL([BUILD_WINDOWS], [test "$build_windows" = "yes"])
Expand All @@ -486,6 +498,7 @@ echo " module extrakeys = $enable_module_extrakeys"
echo " module schnorrsig = $enable_module_schnorrsig"
echo " module musig = $enable_module_musig"
echo " module ellswift = $enable_module_ellswift"
echo " module batch = $enable_module_batch"
echo
echo " asm = $set_asm"
echo " ecmult window size = $set_ecmult_window"
Expand Down
17 changes: 17 additions & 0 deletions doc/speedup-batch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Schnorrsig Batch Verification Speedup

![Speedup over single verification](speedup-batch/schnorrsig-speedup-batch.png)

# Tweak Pubkey Check Batch Verification Speedup

![Speedup over single verification](speedup-batch/tweakcheck-speedup-batch.png)

Build steps
-----------
To generate the above graphs on your local machine:

$ cd doc/speedup-batch
$ make
$ make speedup-batch.png

<!-- TODO: add additional notes on the API -->
1 change: 1 addition & 0 deletions doc/speedup-batch/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.dat
23 changes: 23 additions & 0 deletions doc/speedup-batch/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
schnorrsig_data = schnorrsig_batch.dat schnorrsig_single.dat
tweak_data = tweak_batch.dat tweak_single.dat

bench_output.txt: bench.sh
SECP256K1_BENCH_ITERS=500000 ./bench.sh bench_output.txt

schnorrsig_batch.dat: bench_output.txt
cat bench_output.txt | grep -v "batchverify_schnorrsigs_1 " | awk '{ gsub(/ /,""); print }' | gawk -F, 'match($$0, /batchverify_schnorrsigs_([0-9]+)/, arr) {print arr[1] " " $$3}' > schnorrsig_batch.dat

schnorrsig_single.dat: bench_output.txt
cat bench_output.txt | awk '{ gsub(/ /,""); print }' | awk -F, 'match($$0, /schnorrsig_verify/) {print $$3}' > schnorrsig_single.dat

tweak_batch.dat: bench_output.txt
cat bench_output.txt | grep -v "batchverify_tweak_checks_1 " | awk '{ gsub(/ /,""); print }' | gawk -F, 'match($$0, /batchverify_tweak_checks_([0-9]+)/, arr) {print arr[1] " " $$3}' > tweak_batch.dat

tweak_single.dat: bench_output.txt
cat bench_output.txt | awk '{ gsub(/ /,""); print }' | awk -F, 'match($$0, /tweak_add_check/) {print $$3}' > tweak_single.dat

speedup-batch.png: $(schnorrsig_data) $(tweak_data) plot.gp
gnuplot plot.gp

clean:
rm *.log *.txt *.dat *.png
13 changes: 13 additions & 0 deletions doc/speedup-batch/bench.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

output_file=$1
cur_dir=$(pwd)

cd ../../
echo "HEAD: $(git rev-parse --short HEAD)" > "$cur_dir/$output_file.log"
make clean
./autogen.sh
./configure --enable-experimental --enable-module-batch --enable-module-schnorrsig >> "$cur_dir/$output_file.log"
make
./bench schnorrsig > "$cur_dir/$output_file"
./bench extrakeys >> "$cur_dir/$output_file"
Loading
Loading