diff --git a/.gitignore b/.gitignore index e8642c1dc..964206e16 100644 --- a/.gitignore +++ b/.gitignore @@ -1,20 +1,15 @@ *.tar.gz *.deb *.exe -src/bitcoin src/bitcoinzd src/bitcoinz-cli src/bitcoinz-gtest src/bitcoinz-tx -src/zcashd -src/zcash-cli -src/zcash-gtest -src/zcash-tx -src/test/test_bitcoin +src/test/test_bitcoinz src/BitcoinZWallet.jar -*zcashTest.pk -*zcashTest.vk +*.pk +*.vk # autoreconf Makefile.in @@ -36,6 +31,7 @@ build-aux/test-driver config.log config.status configure +configure~ libtool src/config/bitcoin-config.h src/config/bitcoin-config.h.in @@ -57,7 +53,7 @@ src/univalue/gen *.pyc *.o *.o-* -.zcash +.bitcoinz *.a *.pb.cc *.pb.h @@ -94,10 +90,11 @@ build *.gcno *.gcda /*.info -test_bitcoin.coverage/ -zcash-gtest.coverage/ +test_bitcoinz.coverage/ +bitcoinz-gtest.coverage/ total.coverage/ coverage_percent.txt +afl-temp #build tests linux-coverage-build @@ -117,5 +114,11 @@ libzcashconsensus.pc contrib/debian/files contrib/debian/substvars +src/fuzzing/*/output +src/fuzz.cpp + .idea/ *.iml + +src/zcash/CreateJoinSplit +src/zcash/GenerateParams diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index ecb31ef0f..000000000 --- a/.travis.yml +++ /dev/null @@ -1,79 +0,0 @@ -# errata: -# - A travis bug causes caches to trample eachother when using the same -# compiler key (which we don't use anyway). This is worked around for now by -# replacing the "compilers" with a build name prefixed by the no-op ":" -# command. See: https://github.com/travis-ci/travis-ci/issues/4393 -# - sudo/dist/group are set so as to get Blue Box VMs, necessary for [loopback] -# IPv6 support - -sudo: required -dist: precise -group: legacy - -os: linux -language: cpp -compiler: gcc -env: - global: - - MAKEJOBS=-j3 - - RUN_TESTS=false - - BOOST_TEST_RANDOM=1$TRAVIS_BUILD_ID - - CCACHE_SIZE=100M - - CCACHE_TEMPDIR=/tmp/.ccache-temp - - CCACHE_COMPRESS=1 - - BASE_OUTDIR=$TRAVIS_BUILD_DIR/out - - SDK_URL=https://bitcoincore.org/depends-sources/sdks - - PYTHON_DEBUG=1 - - WINEDEBUG=fixme-all -cache: - apt: true - directories: - - depends/built - - depends/sdk-sources - - $HOME/.ccache -matrix: - fast_finish: true - include: - - compiler: ": ARM" - env: HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="" GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" - - compiler: ": Win32" - env: HOST=i686-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-i686 g++-mingw-w64-i686 binutils-mingw-w64-i686 mingw-w64-dev wine bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-reduce-exports" MAKEJOBS="-j2" - - compiler: ": 32-bit + dash" - env: HOST=i686-pc-linux-gnu PACKAGES="g++-multilib bc python-zmq" PPA="ppa:chris-lea/zeromq" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash" - - compiler: ": Win64" - env: HOST=x86_64-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64 mingw-w64-dev wine bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-reduce-exports" MAKEJOBS="-j2" - - compiler: ": bitcoind" - env: HOST=x86_64-unknown-linux-gnu PACKAGES="bc python-zmq" PPA="ppa:chris-lea/zeromq" DEP_OPTS="DEBUG=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER" - - compiler: ": No wallet" - env: HOST=x86_64-unknown-linux-gnu DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" - - compiler: ": Cross-Mac" - env: HOST=x86_64-apple-darwin11 PACKAGES="cmake libcap-dev libz-dev libbz2-dev" BITCOIN_CONFIG="--enable-reduce-exports" OSX_SDK=10.9 GOAL="deploy" - exclude: - - compiler: gcc -install: - - if [ -n "$PACKAGES" ]; then sudo rm -f /etc/apt/sources.list.d/travis_ci_zeromq3-source.list; fi - - if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get update; fi - - if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES; fi -before_script: - - unset CC; unset CXX - - mkdir -p depends/SDKs depends/sdk-sources - - if [ -n "$OSX_SDK" -a ! -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then curl --location --fail $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -o depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi - - if [ -n "$OSX_SDK" -a -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then tar -C depends/SDKs -xf depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi - - make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS -script: - - if [ -n "$USE_SHELL" ]; then export CONFIG_SHELL="$USE_SHELL"; fi - - OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST - - BITCOIN_CONFIG_ALL="--disable-dependency-tracking --prefix=$TRAVIS_BUILD_DIR/depends/$HOST --bindir=$OUTDIR/bin --libdir=$OUTDIR/lib" - - depends/$HOST/native/bin/ccache --max-size=$CCACHE_SIZE - - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then export CCACHE_READONLY=1; fi - - test -n "$USE_SHELL" && eval '"$USE_SHELL" -c "./autogen.sh"' || ./autogen.sh - - ./configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false) - - make distdir PACKAGE=bitcoin VERSION=$HOST - - cd bitcoin-$HOST - - ./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false) - - make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && make $GOAL V=1 ; false ) - - export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib - - if [ "$RUN_TESTS" = "true" ]; then make check; fi - - if [ "$RUN_TESTS" = "true" ]; then qa/pull-tester/rpc-tests.sh; fi -after_script: - - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then (echo "Upload goes here. Something like: scp -r $BASE_OUTDIR server" || echo "upload failed"); fi diff --git a/COPYING b/COPYING index 2dd806c6c..932ac8956 100644 --- a/COPYING +++ b/COPYING @@ -1,7 +1,7 @@ +Copyright (c) 2018-2024 The BitcoinZ Community Copyright (c) 2016-2019 The Zcash developers Copyright (c) 2009-2019 The Bitcoin Core developers Copyright (c) 2009-2019 Bitcoin Developers -Copyright (c) 2018-2020 The BitcoinZ Community Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,10 +22,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -The MIT software license (http://www.opensource.org/licenses/mit-license.php) -above applies to the code directly included in this source distribution. -Dependencies downloaded as part of the build process may be covered by other -open-source licenses. For further details see 'contrib/debian/copyright'. +The MIT software license (https://www.opensource.org/licenses/mit-license.php) +above applies to the code directly included in this source distribution, with +the exception of certain Autoconf macros. Dependencies downloaded as part of +the build process may be covered by other open-source licenses. The MIT-licensed +source code is not considered a derived work of these Autoconf macros or of the +dependencies. For further details see 'contrib/debian/copyright'. This product includes software developed by the OpenSSL Project for use in the @@ -33,7 +35,20 @@ OpenSSL Toolkit (https://www.openssl.org/). This product includes cryptographic software written by Eric Young (eay@cryptsoft.com). -Although almost all of the Zcash code is licensed under "permissive" open source +Although almost all of the BitcoinZ code is licensed under "permissive" open source licenses, users and distributors should note that when built using the default -build options, Zcash depends on Oracle Berkeley DB 6.2.x, which is licensed +build options, BitcoinZ depends on Oracle Berkeley DB 6.2.x, which is licensed under the GNU Affero General Public License. + + +Contributors should understand licensing implications before modifying the +following files in build-aux/m4 (see https://github.com/zcash/zcash/issues/2827): + + * ax_check_compile_flag.m4 + * ax_check_link_flag.m4 + * ax_check_preproc_flag.m4 + * ax_compiler_vendor.m4 + * ax_gcc_archflag.m4 + * ax_gcc_x86_cpuid.m4 + * ax_openmp.m4 + * ax_pthread.m4 diff --git a/Makefile.am b/Makefile.am index a5040733c..e163253bb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2020 The BitcoinZ community +# Copyright (c) 2017-2024 The BitcoinZ community # Copyright (c) 2016-2019 The Zcash developers # Copyright (c) 2013-2019 The Bitcoin Core developers # Copyright (c) 2013-2019 Bitcoin Developers @@ -28,10 +28,10 @@ BIN_CHECKS=$(top_srcdir)/contrib/devtools/symbol-check.py \ $(top_srcdir)/contrib/devtools/security-check.py COVERAGE_INFO = baseline_filtered_combined.info baseline.info \ - leveldb_baseline.info test_bitcoin_filtered.info total_coverage.info \ + leveldb_baseline.info test_bitcoinz_filtered.info total_coverage.info \ baseline_filtered.info \ - leveldb_baseline_filtered.info test_bitcoin_coverage.info test_bitcoin.info \ - zcash-gtest.info zcash-gtest_filtered.info zcash-gtest_coverage.info + leveldb_baseline_filtered.info test_bitcoinz_coverage.info test_bitcoinz.info \ + bitcoinz-gtest.info bitcoinz-gtest_filtered.info bitcoinz-gtest_coverage.info dist-hook: -$(MAKE) -C $(top_distdir)/src/leveldb clean @@ -90,13 +90,13 @@ leveldb_baseline_filtered.info: leveldb_baseline.info baseline_filtered_combined.info: leveldb_baseline_filtered.info baseline_filtered.info $(LCOV) -a leveldb_baseline_filtered.info -a baseline_filtered.info -o $@ -test_bitcoin.info: baseline_filtered_combined.info - $(MAKE) -C src/ bitcoin_test_check - $(LCOV) -c -d $(abs_builddir)/src -t test_bitcoin -o $@ +test_bitcoinz.info: baseline_filtered_combined.info + $(MAKE) -C src/ bitcoinz_test_check + $(LCOV) -c -d $(abs_builddir)/src -t test_bitcoinz -o $@ $(LCOV) -z -d $(abs_builddir)/src $(LCOV) -z -d $(abs_builddir)/src/leveldb -test_bitcoin_filtered.info: test_bitcoin.info +test_bitcoinz_filtered.info: test_bitcoinz.info $(LCOV) -r $< "/usr/include/*" \ "$(abs_builddir)/depends/x86_64-unknown-linux-gnu/include/*.h" \ "$(abs_builddir)/depends/x86_64-unknown-linux-gnu/include/boost/*" \ @@ -108,13 +108,13 @@ test_bitcoin_filtered.info: test_bitcoin.info "$(abs_builddir)/src/wallet/test/*" \ -o $@ -zcash-gtest.info: baseline_filtered_combined.info - $(MAKE) -C src/ zcash-gtest_check - $(LCOV) -c -d $(abs_builddir)/src -t zcash-gtest -o $@ +bitcoinz-gtest.info: baseline_filtered_combined.info + $(MAKE) -C src/ bitcoinz-gtest_check + $(LCOV) -c -d $(abs_builddir)/src -t bitcoinz-gtest -o $@ $(LCOV) -z -d $(abs_builddir)/src $(LCOV) -z -d $(abs_builddir)/src/leveldb -zcash-gtest_filtered.info: zcash-gtest.info +bitcoinz-gtest_filtered.info: bitcoinz-gtest.info $(LCOV) -r $< "/usr/include/*" \ "$(abs_builddir)/depends/x86_64-unknown-linux-gnu/include/*.h" \ "$(abs_builddir)/depends/x86_64-unknown-linux-gnu/include/boost/*" \ @@ -126,30 +126,30 @@ zcash-gtest_filtered.info: zcash-gtest.info "$(abs_builddir)/src/wallet/test/*" \ -o $@ -test_bitcoin_coverage.info: baseline_filtered_combined.info test_bitcoin_filtered.info - $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a test_bitcoin_filtered.info -o $@ +test_bitcoinz_coverage.info: baseline_filtered_combined.info test_bitcoinz_filtered.info + $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a test_bitcoinz_filtered.info -o $@ -zcash-gtest_coverage.info: baseline_filtered_combined.info zcash-gtest_filtered.info - $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a zcash-gtest_filtered.info -o $@ +bitcoinz-gtest_coverage.info: baseline_filtered_combined.info bitcoinz-gtest_filtered.info + $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a bitcoinz-gtest_filtered.info -o $@ -total_coverage.info: baseline_filtered_combined.info test_bitcoin_filtered.info zcash-gtest_filtered.info - $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a test_bitcoin_filtered.info -a zcash-gtest_filtered.info -o $@ | $(GREP) "\%" | $(AWK) '{ print substr($$3,2,50) "/" $$5 }' > coverage_percent.txt +total_coverage.info: baseline_filtered_combined.info test_bitcoinz_filtered.info bitcoinz-gtest_filtered.info + $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a test_bitcoinz_filtered.info -a bitcoinz-gtest_filtered.info -o $@ | $(GREP) "\%" | $(AWK) '{ print substr($$3,2,50) "/" $$5 }' > coverage_percent.txt -test_bitcoin.coverage/.dirstamp: test_bitcoin_coverage.info +test_bitcoinz.coverage/.dirstamp: test_bitcoinz_coverage.info $(GENHTML) -s $< -o $(@D) @touch $@ -zcash-gtest.coverage/.dirstamp: zcash-gtest_coverage.info +bitcoinz-gtest.coverage/.dirstamp: bitcoinz-gtest_coverage.info $(GENHTML) -s $< -o $(@D) @touch $@ -cov-zcash: zcash-gtest.coverage/.dirstamp +cov-bitcoinz: bitcoinz-gtest.coverage/.dirstamp total.coverage/.dirstamp: total_coverage.info $(GENHTML) -s $< -o $(@D) @touch $@ -cov: test_bitcoin.coverage/.dirstamp cov-zcash total.coverage/.dirstamp +cov: test_bitcoinz.coverage/.dirstamp cov-bitcoinz total.coverage/.dirstamp endif @@ -159,11 +159,12 @@ dist_noinst_SCRIPTS = autogen.sh zcutil/build-debian-package.sh zcutil/build.sh EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.sh qa/pull-tester/run-bitcoin-cli qa/rpc-tests qa/bitcoinz $(DIST_DOCS) $(BIN_CHECKS) install-exec-hook: - mv $(DESTDIR)$(bindir)/fetch-params.sh $(DESTDIR)$(bindir)/zcash-fetch-params + mv $(DESTDIR)$(bindir)/fetch-params.sh $(DESTDIR)$(bindir)/bitcoinz-fetch-params .INTERMEDIATE: $(COVERAGE_INFO) DISTCHECK_CONFIGURE_FLAGS = --enable-man clean-local: - rm -rf test_bitcoin.coverage/ zcash-gtest.coverage/ total.coverage/ + rm -rf test_bitcoinz.coverage/ bitcoinz-gtest.coverage/ total.coverage/ + rm -rf afl-temp diff --git a/README.md b/README.md index 30d55fb62..2dfa2e62d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# BitcoinZ 2.0.8 +# BitcoinZ 2.0.9-rc2 **Keep running wallet to strengthen the BitcoinZ network. Backup your wallet in many locations & keep your coins wallet offline.** ### Ports: @@ -15,7 +15,7 @@ Install required dependencies: ```{r, engine='bash'} sudo apt-get install \ build-essential pkg-config libc6-dev m4 g++-multilib \ - autoconf libtool ncurses-dev unzip git python \ + autoconf libtool libncurses-dev unzip git python3 python-is-python3 \ zlib1g-dev wget bsdmainutils automake ``` @@ -60,7 +60,7 @@ Install required dependencies: apt-get update \ && apt-get install -y \ curl build-essential pkg-config libc6-dev m4 g++-multilib autoconf \ - libtool ncurses-dev unzip git python zlib1g-dev wget bsdmainutils \ + libtool libncurses-dev unzip git python3 python-is-python3 zlib1g-dev wget bsdmainutils \ automake p7zip-full pwgen mingw-w64 cmake ``` diff --git a/autogen.sh b/autogen.sh index 77dac7475..cb526759f 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Copyright (c) 2017-2020 The BitcoinZ community +# Copyright (c) 2017-2024 The BitcoinZ community # Copyright (c) 2016-2019 The Zcash developers # Copyright (c) 2013-2019 The Bitcoin Core developers # Copyright (c) 2013-2019 Bitcoin Developers diff --git a/build-aux/m4/ax_boost_base.m4 b/build-aux/m4/ax_boost_base.m4 index 45d948933..296e05558 100644 --- a/build-aux/m4/ax_boost_base.m4 +++ b/build-aux/m4/ax_boost_base.m4 @@ -10,7 +10,7 @@ # # Test for the Boost C++ libraries of a particular version (or newer) # -# If no path to the installed boost library is given the macro searchs +# If no path to the installed boost library is given the macro searches # under /usr, /usr/local, /opt and /opt/local and evaluates the # $BOOST_ROOT environment variable. Further documentation is available at # . @@ -119,7 +119,7 @@ if test "x$want_boost" = "xyes"; then libsubdirs="lib/`$CXX -dumpmachine 2>/dev/null` $libsubdirs" dnl first we check the system location for boost libraries - dnl this location ist chosen if boost libraries are installed with the --layout=system option + dnl this location is chosen if boost libraries are installed with the --layout=system option dnl or if you install boost with RPM if test "$ac_boost_path" != ""; then BOOST_CPPFLAGS="-I$ac_boost_path/include" diff --git a/build-aux/m4/ax_compiler_vendor.m4 b/build-aux/m4/ax_compiler_vendor.m4 deleted file mode 100644 index f06e86540..000000000 --- a/build-aux/m4/ax_compiler_vendor.m4 +++ /dev/null @@ -1,117 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_COMPILER_VENDOR -# -# DESCRIPTION -# -# Determine the vendor of the C, C++ or Fortran compiler. The vendor is -# returned in the cache variable $ax_cv_c_compiler_vendor for C, -# $ax_cv_cxx_compiler_vendor for C++ or $ax_cv_fc_compiler_vendor for -# (modern) Fortran. The value is one of "intel", "ibm", "pathscale", -# "clang" (LLVM), "cray", "fujitsu", "sdcc", "sx", "portland" (PGI), "gnu" -# (GCC), "sun" (Oracle Developer Studio), "hp", "dec", "borland", -# "comeau", "kai", "lcc", "sgi", "microsoft", "metrowerks", "watcom", -# "tcc" (Tiny CC) or "unknown" (if the compiler cannot be determined). -# -# To check for a Fortran compiler, you must first call AC_FC_PP_SRCEXT -# with an appropriate preprocessor-enabled extension. For example: -# -# AC_LANG_PUSH([Fortran]) -# AC_PROG_FC -# AC_FC_PP_SRCEXT([F]) -# AX_COMPILER_VENDOR -# AC_LANG_POP([Fortran]) -# -# LICENSE -# -# Copyright (c) 2008 Steven G. Johnson -# Copyright (c) 2008 Matteo Frigo -# Copyright (c) 2018-19 John Zaitseff -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 30 - -AC_DEFUN([AX_COMPILER_VENDOR], [dnl - AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, [dnl - dnl If you modify this list of vendors, please add similar support - dnl to ax_compiler_version.m4 if at all possible. - dnl - dnl Note: Do NOT check for GCC first since some other compilers - dnl define __GNUC__ to remain compatible with it. Compilers that - dnl are very slow to start (such as Intel) are listed first. - - vendors=" - intel: __ICC,__ECC,__INTEL_COMPILER - ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__,__ibmxl__ - pathscale: __PATHCC__,__PATHSCALE__ - clang: __clang__ - cray: _CRAYC - fujitsu: __FUJITSU - sdcc: SDCC,__SDCC - sx: _SX - portland: __PGI - gnu: __GNUC__ - sun: __SUNPRO_C,__SUNPRO_CC,__SUNPRO_F90,__SUNPRO_F95 - hp: __HP_cc,__HP_aCC - dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER - borland: __BORLANDC__,__CODEGEARC__,__TURBOC__ - comeau: __COMO__ - kai: __KCC - lcc: __LCC__ - sgi: __sgi,sgi - microsoft: _MSC_VER - metrowerks: __MWERKS__ - watcom: __WATCOMC__ - tcc: __TINYC__ - unknown: UNKNOWN - " - for ventest in $vendors; do - case $ventest in - *:) - vendor=$ventest - continue - ;; - *) - vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" - ;; - esac - - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[ -#if !($vencpp) - thisisanerror; -#endif - ]])], [break]) - done - - ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1` - ]) -])dnl diff --git a/build-aux/m4/ax_cxx_compile_stdcxx.m4 b/build-aux/m4/ax_cxx_compile_stdcxx.m4 index f147cee3b..43087b2e6 100644 --- a/build-aux/m4/ax_cxx_compile_stdcxx.m4 +++ b/build-aux/m4/ax_cxx_compile_stdcxx.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html # =========================================================================== # # SYNOPSIS @@ -33,21 +33,23 @@ # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov # Copyright (c) 2015 Paul Norman # Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016, 2018 Krzesimir Nowak +# Copyright (c) 2019 Enji Cooper # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 4 +#serial 11 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro dnl (serial version number 13). AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl - m4_if([$1], [11], [], - [$1], [14], [], - [$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])], + m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], + [$1], [14], [ax_cxx_compile_alternatives="14 1y"], + [$1], [17], [ax_cxx_compile_alternatives="17 1z"], [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$2], [], [], [$2], [ext], [], @@ -57,26 +59,13 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], [$3], [optional], [ax_cxx_compile_cxx$1_required=false], [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) - m4_if([$4], [], [ax_cxx_compile_cxx$1_try_default=true], - [$4], [default], [ax_cxx_compile_cxx$1_try_default=true], - [$4], [nodefault], [ax_cxx_compile_cxx$1_try_default=false], - [m4_fatal([invalid fourth argument `$4' to AX_CXX_COMPILE_STDCXX])]) AC_LANG_PUSH([C++])dnl ac_success=no - m4_if([$4], [nodefault], [], [dnl - AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, - ax_cv_cxx_compile_cxx$1, - [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], - [ax_cv_cxx_compile_cxx$1=yes], - [ax_cv_cxx_compile_cxx$1=no])]) - if test x$ax_cv_cxx_compile_cxx$1 = xyes; then - ac_success=yes - fi]) - m4_if([$2], [noext], [], [dnl if test x$ac_success = xno; then - for switch in -std=gnu++$1 -std=gnu++0x; do + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, @@ -102,22 +91,27 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl dnl HP's aCC needs +std=c++11 according to: dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf dnl Cray's crayCC needs "-h std=c++11" - for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, - $cachevar, - [ac_save_CXX="$CXX" - CXX="$CXX $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXX="$ac_save_CXX"]) - if eval test x\$$cachevar = xyes; then - CXX="$CXX $switch" - if test -n "$CXXCPP" ; then - CXXCPP="$CXXCPP $switch" + for alternative in ${ax_cxx_compile_alternatives}; do + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break fi - ac_success=yes + done + if test x$ac_success = xyes; then break fi done @@ -154,6 +148,11 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 ) +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 +) dnl Tests for new features in C++11 @@ -191,11 +190,13 @@ namespace cxx11 struct Base { + virtual ~Base() {} virtual void f() {} }; struct Derived : public Base { + virtual ~Derived() override {} virtual void f() override {} }; @@ -524,7 +525,7 @@ namespace cxx14 } - namespace test_digit_seperators + namespace test_digit_separators { constexpr auto ten_million = 100'000'000; @@ -566,3 +567,385 @@ namespace cxx14 #endif // __cplusplus >= 201402L ]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201703L + +#error "This is not a C++17 compiler" + +#else + +#include +#include +#include + +namespace cxx17 +{ + + namespace test_constexpr_lambdas + { + + constexpr int foo = [](){return 42;}(); + + } + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template + int multiply(Args... args) + { + return (args * ... * 1); + } + + template + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_auto_brace_init_list + { + + auto foo = {5}; + auto bar {5}; + + static_assert(std::is_same, decltype(foo)>::value); + static_assert(std::is_same::value); + } + + namespace test_typename_in_template_template_parameter + { + + template typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + + namespace test_template_argument_deduction_for_class_templates + { + + template + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } + + namespace test_non_type_auto_template_parameters + { + + template + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + + namespace test_structured_bindings + { + + int arr[2] = { 1, 2 }; + std::pair pr = { 1, 2 }; + + auto f1() -> int(&)[2] + { + return arr; + } + + auto f2() -> std::pair& + { + return pr; + } + + struct S + { + int x1 : 2; + volatile double y1; + }; + + S f3() + { + return {}; + } + + auto [ x1, y1 ] = f1(); + auto& [ xr1, yr1 ] = f1(); + auto [ x2, y2 ] = f2(); + auto& [ xr2, yr2 ] = f2(); + const auto [ x3, y3 ] = f3(); + + } + + namespace test_exception_spec_type_system + { + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template + Bad + f(T*, T*); + + template + Good + f(T1*, T2*); + + static_assert (std::is_same_v); + + } + + namespace test_inline_variables + { + + template void f(T) + {} + + template inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // __cplusplus < 201703L + +]]) diff --git a/build-aux/m4/ax_gcc_archflag.m4 b/build-aux/m4/ax_gcc_archflag.m4 deleted file mode 100644 index c52b9b296..000000000 --- a/build-aux/m4/ax_gcc_archflag.m4 +++ /dev/null @@ -1,267 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_gcc_archflag.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_GCC_ARCHFLAG([PORTABLE?], [ACTION-SUCCESS], [ACTION-FAILURE]) -# -# DESCRIPTION -# -# This macro tries to guess the "native" arch corresponding to the target -# architecture for use with gcc's -march=arch or -mtune=arch flags. If -# found, the cache variable $ax_cv_gcc_archflag is set to this flag and -# ACTION-SUCCESS is executed; otherwise $ax_cv_gcc_archflag is set to -# "unknown" and ACTION-FAILURE is executed. The default ACTION-SUCCESS is -# to add $ax_cv_gcc_archflag to the end of $CFLAGS. -# -# PORTABLE? should be either [yes] (default) or [no]. In the former case, -# the flag is set to -mtune (or equivalent) so that the architecture is -# only used for tuning, but the instruction set used is still portable. In -# the latter case, the flag is set to -march (or equivalent) so that -# architecture-specific instructions are enabled. -# -# The user can specify --with-gcc-arch= in order to override the -# macro's choice of architecture, or --without-gcc-arch to disable this. -# -# When cross-compiling, or if $CC is not gcc, then ACTION-FAILURE is -# called unless the user specified --with-gcc-arch manually. -# -# Requires macros: AX_CHECK_COMPILE_FLAG, AX_GCC_X86_CPUID -# -# (The main emphasis here is on recent CPUs, on the principle that doing -# high-performance computing on old hardware is uncommon.) -# -# LICENSE -# -# Copyright (c) 2008 Steven G. Johnson -# Copyright (c) 2008 Matteo Frigo -# Copyright (c) 2014 Tsukasa Oi -# Copyright (c) 2017-2018 Alexey Kopytov -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 22 - -AC_DEFUN([AX_GCC_ARCHFLAG], -[AC_REQUIRE([AC_PROG_CC]) -AC_REQUIRE([AC_CANONICAL_HOST]) -AC_REQUIRE([AC_PROG_SED]) -AC_REQUIRE([AX_COMPILER_VENDOR]) - -AC_ARG_WITH(gcc-arch, [AS_HELP_STRING([--with-gcc-arch=], [use architecture for gcc -march/-mtune, instead of guessing])], - ax_gcc_arch=$withval, ax_gcc_arch=yes) - -AC_MSG_CHECKING([for gcc architecture flag]) -AC_MSG_RESULT([]) -AC_CACHE_VAL(ax_cv_gcc_archflag, -[ -ax_cv_gcc_archflag="unknown" - -if test "$GCC" = yes; then - -if test "x$ax_gcc_arch" = xyes; then -ax_gcc_arch="" -if test "$cross_compiling" = no; then -case $host_cpu in - i[[3456]]86*|x86_64*|amd64*) # use cpuid codes - AX_GCC_X86_CPUID(0) - AX_GCC_X86_CPUID(1) - case $ax_cv_gcc_x86_cpuid_0 in - *:756e6547:6c65746e:49656e69) # Intel - case $ax_cv_gcc_x86_cpuid_1 in - *5[[4578]]?:*:*:*) ax_gcc_arch="pentium-mmx pentium" ;; - *5[[123]]?:*:*:*) ax_gcc_arch=pentium ;; - *0?61?:*:*:*|?61?:*:*:*|61?:*:*:*) ax_gcc_arch=pentiumpro ;; - *0?6[[356]]?:*:*:*|?6[[356]]?:*:*:*|6[[356]]?:*:*:*) ax_gcc_arch="pentium2 pentiumpro" ;; - *0?6[[78ab]]?:*:*:*|?6[[78ab]]?:*:*:*|6[[78ab]]?:*:*:*) ax_gcc_arch="pentium3 pentiumpro" ;; - *0?6[[9d]]?:*:*:*|?6[[9d]]?:*:*:*|6[[9d]]?:*:*:*|*1?65?:*:*:*) ax_gcc_arch="pentium-m pentium3 pentiumpro" ;; - *0?6e?:*:*:*|?6e?:*:*:*|6e?:*:*:*) ax_gcc_arch="yonah pentium-m pentium3 pentiumpro" ;; - *0?6f?:*:*:*|?6f?:*:*:*|6f?:*:*:*|*1?66?:*:*:*) ax_gcc_arch="core2 pentium-m pentium3 pentiumpro" ;; - *1?6[[7d]]?:*:*:*) ax_gcc_arch="penryn core2 pentium-m pentium3 pentiumpro" ;; - *1?6[[aef]]?:*:*:*|*2?6e?:*:*:*) ax_gcc_arch="nehalem corei7 core2 pentium-m pentium3 pentiumpro" ;; - *2?6[[5cf]]?:*:*:*) ax_gcc_arch="westmere corei7 core2 pentium-m pentium3 pentiumpro" ;; - *2?6[[ad]]?:*:*:*) ax_gcc_arch="sandybridge corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; - *3?6[[ae]]?:*:*:*) ax_gcc_arch="ivybridge core-avx-i corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; - *3?6[[cf]]?:*:*:*|*4?6[[56]]?:*:*:*) ax_gcc_arch="haswell core-avx2 core-avx-i corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; - *3?6d?:*:*:*|*4?6[[7f]]?:*:*:*|*5?66?:*:*:*) ax_gcc_arch="broadwell core-avx2 core-avx-i corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; - *1?6c?:*:*:*|*2?6[[67]]?:*:*:*|*3?6[[56]]?:*:*:*) ax_gcc_arch="bonnell atom core2 pentium-m pentium3 pentiumpro" ;; - *3?67?:*:*:*|*[[45]]?6[[ad]]?:*:*:*) ax_gcc_arch="silvermont atom core2 pentium-m pentium3 pentiumpro" ;; - *000?f[[012]]?:*:*:*|?f[[012]]?:*:*:*|f[[012]]?:*:*:*) ax_gcc_arch="pentium4 pentiumpro" ;; - *000?f[[346]]?:*:*:*|?f[[346]]?:*:*:*|f[[346]]?:*:*:*) ax_gcc_arch="nocona prescott pentium4 pentiumpro" ;; - # fallback - *5??:*:*:*) ax_gcc_arch=pentium ;; - *??6??:*:*:*) ax_gcc_arch="core2 pentiumpro" ;; - *6??:*:*:*) ax_gcc_arch=pentiumpro ;; - *00??f??:*:*:*|??f??:*:*:*|?f??:*:*:*|f??:*:*:*) ax_gcc_arch="pentium4 pentiumpro" ;; - esac ;; - *:68747541:444d4163:69746e65) # AMD - case $ax_cv_gcc_x86_cpuid_1 in - *5[[67]]?:*:*:*) ax_gcc_arch=k6 ;; - *5[[8]]?:*:*:*) ax_gcc_arch="k6-2 k6" ;; - *5[[9d]]?:*:*:*) ax_gcc_arch="k6-3 k6" ;; - *6[[12]]?:*:*:*) ax_gcc_arch="athlon k7" ;; - *6[[34]]?:*:*:*) ax_gcc_arch="athlon-tbird k7" ;; - *6[[678a]]?:*:*:*) ax_gcc_arch="athlon-xp athlon-4 athlon k7" ;; - *000?f[[4578bcef]]?:*:*:*|?f[[4578bcef]]?:*:*:*|f[[4578bcef]]?:*:*:*|*001?f[[4578bcf]]?:*:*:*|1?f[[4578bcf]]?:*:*:*) ax_gcc_arch="athlon64 k8" ;; - *002?f[[13457bcf]]?:*:*:*|2?f[[13457bcf]]?:*:*:*|*004?f[[138bcf]]?:*:*:*|4?f[[138bcf]]?:*:*:*|*005?f[[df]]?:*:*:*|5?f[[df]]?:*:*:*|*006?f[[8bcf]]?:*:*:*|6?f[[8bcf]]?:*:*:*|*007?f[[cf]]?:*:*:*|7?f[[cf]]?:*:*:*|*00c?f1?:*:*:*|c?f1?:*:*:*|*020?f3?:*:*:*|20?f3?:*:*:*) ax_gcc_arch="athlon64-sse3 k8-sse3 athlon64 k8" ;; - *010?f[[245689a]]?:*:*:*|10?f[[245689a]]?:*:*:*|*030?f1?:*:*:*|30?f1?:*:*:*) ax_gcc_arch="barcelona amdfam10 k8" ;; - *050?f[[12]]?:*:*:*|50?f[[12]]?:*:*:*) ax_gcc_arch="btver1 amdfam10 k8" ;; - *060?f1?:*:*:*|60?f1?:*:*:*) ax_gcc_arch="bdver1 amdfam10 k8" ;; - *060?f2?:*:*:*|60?f2?:*:*:*|*061?f[[03]]?:*:*:*|61?f[[03]]?:*:*:*) ax_gcc_arch="bdver2 bdver1 amdfam10 k8" ;; - *063?f0?:*:*:*|63?f0?:*:*:*) ax_gcc_arch="bdver3 bdver2 bdver1 amdfam10 k8" ;; - *07[[03]]?f0?:*:*:*|7[[03]]?f0?:*:*:*) ax_gcc_arch="btver2 btver1 amdfam10 k8" ;; - # fallback - *0[[13]]??f??:*:*:*|[[13]]??f??:*:*:*) ax_gcc_arch="barcelona amdfam10 k8" ;; - *020?f??:*:*:*|20?f??:*:*:*) ax_gcc_arch="athlon64-sse3 k8-sse3 athlon64 k8" ;; - *05??f??:*:*:*|5??f??:*:*:*) ax_gcc_arch="btver1 amdfam10 k8" ;; - *060?f??:*:*:*|60?f??:*:*:*) ax_gcc_arch="bdver1 amdfam10 k8" ;; - *061?f??:*:*:*|61?f??:*:*:*) ax_gcc_arch="bdver2 bdver1 amdfam10 k8" ;; - *06??f??:*:*:*|6??f??:*:*:*) ax_gcc_arch="bdver3 bdver2 bdver1 amdfam10 k8" ;; - *070?f??:*:*:*|70?f??:*:*:*) ax_gcc_arch="btver2 btver1 amdfam10 k8" ;; - *???f??:*:*:*) ax_gcc_arch="amdfam10 k8" ;; - esac ;; - *:746e6543:736c7561:48727561) # IDT / VIA (Centaur) - case $ax_cv_gcc_x86_cpuid_1 in - *54?:*:*:*) ax_gcc_arch=winchip-c6 ;; - *5[[89]]?:*:*:*) ax_gcc_arch=winchip2 ;; - *66?:*:*:*) ax_gcc_arch=winchip2 ;; - *6[[78]]?:*:*:*) ax_gcc_arch=c3 ;; - *6[[9adf]]?:*:*:*) ax_gcc_arch="c3-2 c3" ;; - esac ;; - esac - if test x"$ax_gcc_arch" = x; then # fallback - case $host_cpu in - i586*) ax_gcc_arch=pentium ;; - i686*) ax_gcc_arch=pentiumpro ;; - esac - fi - ;; - - sparc*) - AC_PATH_PROG([PRTDIAG], [prtdiag], [prtdiag], [$PATH:/usr/platform/`uname -i`/sbin/:/usr/platform/`uname -m`/sbin/]) - cputype=`(((grep cpu /proc/cpuinfo | cut -d: -f2) ; ($PRTDIAG -v |grep -i sparc) ; grep -i cpu /var/run/dmesg.boot ) | head -n 1) 2> /dev/null` - cputype=`echo "$cputype" | tr -d ' -' | $SED 's/SPARCIIi/SPARCII/' |tr $as_cr_LETTERS $as_cr_letters` - case $cputype in - *ultrasparciv*) ax_gcc_arch="ultrasparc4 ultrasparc3 ultrasparc v9" ;; - *ultrasparciii*) ax_gcc_arch="ultrasparc3 ultrasparc v9" ;; - *ultrasparc*) ax_gcc_arch="ultrasparc v9" ;; - *supersparc*|*tms390z5[[05]]*) ax_gcc_arch="supersparc v8" ;; - *hypersparc*|*rt62[[056]]*) ax_gcc_arch="hypersparc v8" ;; - *cypress*) ax_gcc_arch=cypress ;; - esac ;; - - alphaev5) ax_gcc_arch=ev5 ;; - alphaev56) ax_gcc_arch=ev56 ;; - alphapca56) ax_gcc_arch="pca56 ev56" ;; - alphapca57) ax_gcc_arch="pca57 pca56 ev56" ;; - alphaev6) ax_gcc_arch=ev6 ;; - alphaev67) ax_gcc_arch=ev67 ;; - alphaev68) ax_gcc_arch="ev68 ev67" ;; - alphaev69) ax_gcc_arch="ev69 ev68 ev67" ;; - alphaev7) ax_gcc_arch="ev7 ev69 ev68 ev67" ;; - alphaev79) ax_gcc_arch="ev79 ev7 ev69 ev68 ev67" ;; - - powerpc*) - cputype=`((grep cpu /proc/cpuinfo | head -n 1 | cut -d: -f2 | cut -d, -f1 | $SED 's/ //g') ; /usr/bin/machine ; /bin/machine; grep CPU /var/run/dmesg.boot | head -n 1 | cut -d" " -f2) 2> /dev/null` - cputype=`echo $cputype | $SED -e 's/ppc//g;s/ *//g'` - case $cputype in - *750*) ax_gcc_arch="750 G3" ;; - *740[[0-9]]*) ax_gcc_arch="$cputype 7400 G4" ;; - *74[[4-5]][[0-9]]*) ax_gcc_arch="$cputype 7450 G4" ;; - *74[[0-9]][[0-9]]*) ax_gcc_arch="$cputype G4" ;; - *970*) ax_gcc_arch="970 G5 power4";; - *POWER4*|*power4*|*gq*) ax_gcc_arch="power4 970";; - *POWER5*|*power5*|*gr*|*gs*) ax_gcc_arch="power5 power4 970";; - 603ev|8240) ax_gcc_arch="$cputype 603e 603";; - *POWER7*) ax_gcc_arch="power7";; - *POWER8*) ax_gcc_arch="power8";; - *POWER9*) ax_gcc_arch="power9";; - *POWER10*) ax_gcc_arch="power10";; - *) ax_gcc_arch=$cputype ;; - esac - ax_gcc_arch="$ax_gcc_arch powerpc" - ;; - aarch64) - cpuimpl=`grep 'CPU implementer' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1` - cpuarch=`grep 'CPU architecture' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1` - cpuvar=`grep 'CPU variant' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1` - case $cpuimpl in - 0x42) case $cpuarch in - 8) case $cpuvar in - 0x0) ax_gcc_arch="thunderx2t99 vulcan armv8.1-a armv8-a+lse armv8-a native" ;; - esac - ;; - esac - ;; - 0x43) case $cpuarch in - 8) case $cpuvar in - 0x0) ax_gcc_arch="thunderx armv8-a native" ;; - 0x1) ax_gcc_arch="thunderx+lse armv8.1-a armv8-a+lse armv8-a native" ;; - esac - ;; - esac - ;; - esac - ;; -esac -fi # not cross-compiling -fi # guess arch - -if test "x$ax_gcc_arch" != x -a "x$ax_gcc_arch" != xno; then -if test "x[]m4_default([$1],yes)" = xyes; then # if we require portable code - flag_prefixes="-mtune=" - if test "x$ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor" = xclang; then flag_prefixes="-march="; fi - # -mcpu=$arch and m$arch generate nonportable code on every arch except - # x86. And some other arches (e.g. Alpha) don't accept -mtune. Grrr. - case $host_cpu in i*86|x86_64*|amd64*) flag_prefixes="$flag_prefixes -mcpu= -m";; esac -else - flag_prefixes="-march= -mcpu= -m" -fi -for flag_prefix in $flag_prefixes; do - for arch in $ax_gcc_arch; do - flag="$flag_prefix$arch" - AX_CHECK_COMPILE_FLAG($flag, [if test "x$ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor" = xclang; then - if test "x[]m4_default([$1],yes)" = xyes; then - if test "x$flag" = "x-march=$arch"; then flag=-mtune=$arch; fi - fi - fi; ax_cv_gcc_archflag=$flag; break]) - done - test "x$ax_cv_gcc_archflag" = xunknown || break -done -fi - -fi # $GCC=yes -]) -AC_MSG_CHECKING([for gcc architecture flag]) -AC_MSG_RESULT($ax_cv_gcc_archflag) -if test "x$ax_cv_gcc_archflag" = xunknown; then - m4_default([$3],:) -else - m4_default([$2], [CFLAGS="$CFLAGS $ax_cv_gcc_archflag"]) -fi -]) diff --git a/build-aux/m4/ax_gcc_func_attribute.m4 b/build-aux/m4/ax_gcc_func_attribute.m4 index c788ca9bd..02b597357 100644 --- a/build-aux/m4/ax_gcc_func_attribute.m4 +++ b/build-aux/m4/ax_gcc_func_attribute.m4 @@ -61,7 +61,7 @@ # weak # weakref # -# Unsuppored function attributes will be tested with a prototype returning +# Unsupported function attributes will be tested with a prototype returning # an int and not accepting any arguments and the result of the check might # be wrong or meaningless so use with care. # diff --git a/build-aux/m4/ax_gcc_x86_cpuid.m4 b/build-aux/m4/ax_gcc_x86_cpuid.m4 deleted file mode 100644 index df954658e..000000000 --- a/build-aux/m4/ax_gcc_x86_cpuid.m4 +++ /dev/null @@ -1,89 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_gcc_x86_cpuid.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_GCC_X86_CPUID(OP) -# AX_GCC_X86_CPUID_COUNT(OP, COUNT) -# -# DESCRIPTION -# -# On Pentium and later x86 processors, with gcc or a compiler that has a -# compatible syntax for inline assembly instructions, run a small program -# that executes the cpuid instruction with input OP. This can be used to -# detect the CPU type. AX_GCC_X86_CPUID_COUNT takes an additional COUNT -# parameter that gets passed into register ECX before calling cpuid. -# -# On output, the values of the eax, ebx, ecx, and edx registers are stored -# as hexadecimal strings as "eax:ebx:ecx:edx" in the cache variable -# ax_cv_gcc_x86_cpuid_OP. -# -# If the cpuid instruction fails (because you are running a -# cross-compiler, or because you are not using gcc, or because you are on -# a processor that doesn't have this instruction), ax_cv_gcc_x86_cpuid_OP -# is set to the string "unknown". -# -# This macro mainly exists to be used in AX_GCC_ARCHFLAG. -# -# LICENSE -# -# Copyright (c) 2008 Steven G. Johnson -# Copyright (c) 2008 Matteo Frigo -# Copyright (c) 2015 Michael Petch -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 10 - -AC_DEFUN([AX_GCC_X86_CPUID], -[AX_GCC_X86_CPUID_COUNT($1, 0) -]) - -AC_DEFUN([AX_GCC_X86_CPUID_COUNT], -[AC_REQUIRE([AC_PROG_CC]) -AC_LANG_PUSH([C]) -AC_CACHE_CHECK(for x86 cpuid $1 output, ax_cv_gcc_x86_cpuid_$1, - [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [ - int op = $1, level = $2, eax, ebx, ecx, edx; - FILE *f; - __asm__ __volatile__ ("xchg %%ebx, %1\n" - "cpuid\n" - "xchg %%ebx, %1\n" - : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) - : "a" (op), "2" (level)); - - f = fopen("conftest_cpuid", "w"); if (!f) return 1; - fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); - fclose(f); - return 0; -])], - [ax_cv_gcc_x86_cpuid_$1=`cat conftest_cpuid`; rm -f conftest_cpuid], - [ax_cv_gcc_x86_cpuid_$1=unknown; rm -f conftest_cpuid], - [ax_cv_gcc_x86_cpuid_$1=unknown])]) -AC_LANG_POP([C]) -]) diff --git a/build-aux/m4/ax_openmp.m4 b/build-aux/m4/ax_openmp.m4 deleted file mode 100644 index 866e1d664..000000000 --- a/build-aux/m4/ax_openmp.m4 +++ /dev/null @@ -1,123 +0,0 @@ -# =========================================================================== -# https://www.gnu.org/software/autoconf-archive/ax_openmp.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_OPENMP([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) -# -# DESCRIPTION -# -# This macro tries to find out how to compile programs that use OpenMP a -# standard API and set of compiler directives for parallel programming -# (see http://www-unix.mcs/) -# -# On success, it sets the OPENMP_CFLAGS/OPENMP_CXXFLAGS/OPENMP_F77FLAGS -# output variable to the flag (e.g. -omp) used both to compile *and* link -# OpenMP programs in the current language. -# -# NOTE: You are assumed to not only compile your program with these flags, -# but also link it with them as well. -# -# If you want to compile everything with OpenMP, you should set: -# -# CFLAGS="$CFLAGS $OPENMP_CFLAGS" -# #OR# CXXFLAGS="$CXXFLAGS $OPENMP_CXXFLAGS" -# #OR# FFLAGS="$FFLAGS $OPENMP_FFLAGS" -# -# (depending on the selected language). -# -# The user can override the default choice by setting the corresponding -# environment variable (e.g. OPENMP_CFLAGS). -# -# ACTION-IF-FOUND is a list of shell commands to run if an OpenMP flag is -# found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it is -# not found. If ACTION-IF-FOUND is not specified, the default action will -# define HAVE_OPENMP. -# -# LICENSE -# -# Copyright (c) 2008 Steven G. Johnson -# Copyright (c) 2015 John W. Peterson -# Copyright (c) 2016 Nick R. Papior -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 13 - -AC_DEFUN([AX_OPENMP], [ -AC_PREREQ([2.69]) dnl for _AC_LANG_PREFIX - -AC_CACHE_CHECK([for OpenMP flag of _AC_LANG compiler], ax_cv_[]_AC_LANG_ABBREV[]_openmp, [save[]_AC_LANG_PREFIX[]FLAGS=$[]_AC_LANG_PREFIX[]FLAGS -ax_cv_[]_AC_LANG_ABBREV[]_openmp=unknown -# Flags to try: -fopenmp (gcc), -mp (SGI & PGI), -# -qopenmp (icc>=15), -openmp (icc), -# -xopenmp (Sun), -omp (Tru64), -# -qsmp=omp (AIX), -# none -ax_openmp_flags="-fopenmp -openmp -qopenmp -mp -xopenmp -omp -qsmp=omp none" -if test "x$OPENMP_[]_AC_LANG_PREFIX[]FLAGS" != x; then - ax_openmp_flags="$OPENMP_[]_AC_LANG_PREFIX[]FLAGS $ax_openmp_flags" -fi -for ax_openmp_flag in $ax_openmp_flags; do - case $ax_openmp_flag in - none) []_AC_LANG_PREFIX[]FLAGS=$save[]_AC_LANG_PREFIX[] ;; - *) []_AC_LANG_PREFIX[]FLAGS="$save[]_AC_LANG_PREFIX[]FLAGS $ax_openmp_flag" ;; - esac - AC_LINK_IFELSE([AC_LANG_SOURCE([[ -@%:@include - -static void -parallel_fill(int * data, int n) -{ - int i; -@%:@pragma omp parallel for - for (i = 0; i < n; ++i) - data[i] = i; -} - -int -main() -{ - int arr[100000]; - omp_set_num_threads(2); - parallel_fill(arr, 100000); - return 0; -} -]])],[ax_cv_[]_AC_LANG_ABBREV[]_openmp=$ax_openmp_flag; break],[]) -done -[]_AC_LANG_PREFIX[]FLAGS=$save[]_AC_LANG_PREFIX[]FLAGS -]) -if test "x$ax_cv_[]_AC_LANG_ABBREV[]_openmp" = "xunknown"; then - m4_default([$2],:) -else - if test "x$ax_cv_[]_AC_LANG_ABBREV[]_openmp" != "xnone"; then - OPENMP_[]_AC_LANG_PREFIX[]FLAGS=$ax_cv_[]_AC_LANG_ABBREV[]_openmp - fi - m4_default([$1], [AC_DEFINE(HAVE_OPENMP,1,[Define if OpenMP is enabled])]) -fi -])dnl AX_OPENMP diff --git a/build-aux/m4/bitcoin_find_bdb.m4 b/build-aux/m4/bitcoin_find_bdb.m4 index bd5c2af45..e6c365271 100644 --- a/build-aux/m4/bitcoin_find_bdb.m4 +++ b/build-aux/m4/bitcoin_find_bdb.m4 @@ -1,3 +1,9 @@ +dnl Copyright (c) 2016-2019 The Zcash developers +dnl Copyright (c) 2013-2019 The Bitcoin Core developers +dnl Copyright (c) 2013-2019 Bitcoin Developers +dnl Distributed under the MIT software license, see the accompanying +dnl file COPYING or https://www.opensource.org/licenses/mit-license.php . + AC_DEFUN([BITCOIN_FIND_BDB62],[ AC_MSG_CHECKING([for Berkeley DB C++ headers]) BDB_CPPFLAGS= diff --git a/build-aux/m4/bitcoin_subdir_to_include.m4 b/build-aux/m4/bitcoin_subdir_to_include.m4 index 66f106c7d..52da5ef9f 100644 --- a/build-aux/m4/bitcoin_subdir_to_include.m4 +++ b/build-aux/m4/bitcoin_subdir_to_include.m4 @@ -1,3 +1,9 @@ +dnl Copyright (c) 2016-2019 The Zcash developers +dnl Copyright (c) 2013-2019 The Bitcoin Core developers +dnl Copyright (c) 2013-2019 Bitcoin Developers +dnl Distributed under the MIT software license, see the accompanying +dnl file COPYING or https://www.opensource.org/licenses/mit-license.php . + dnl BITCOIN_SUBDIR_TO_INCLUDE([CPPFLAGS-VARIABLE-NAME],[SUBDIRECTORY-NAME],[HEADER-FILE]) dnl SUBDIRECTORY-NAME must end with a path separator AC_DEFUN([BITCOIN_SUBDIR_TO_INCLUDE],[ diff --git a/build-aux/m4/l_atomic.m4 b/build-aux/m4/l_atomic.m4 index e7a3d2fc4..75c43f9a9 100644 --- a/build-aux/m4/l_atomic.m4 +++ b/build-aux/m4/l_atomic.m4 @@ -2,7 +2,7 @@ dnl Copyright (c) 2015 Tim Kosse dnl Copying and distribution of this file, with or without modification, are dnl permitted in any medium without royalty provided the copyright notice dnl and this notice are preserved. This file is offered as-is, without any -dnl warranty +dnl warranty. # Some versions of gcc/libstdc++ require linking with -latomic if # using the C++ atomic library. diff --git a/configure.ac b/configure.ac index 7f0df9106..d666ca000 100644 --- a/configure.ac +++ b/configure.ac @@ -2,12 +2,12 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 2) define(_CLIENT_VERSION_MINOR, 0) -define(_CLIENT_VERSION_REVISION, 8) -define(_CLIENT_VERSION_BUILD, 50) +define(_CLIENT_VERSION_REVISION, 9) +define(_CLIENT_VERSION_BUILD, 26) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) -define(_COPYRIGHT_YEAR, 2022) +define(_COPYRIGHT_YEAR, 2024) AC_INIT([BitcoinZ],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_SUFFIX(_ZC_BUILD_VAL)],[https://github.com/btcz/bitcoinz/issues],[BitcoinZ]) AC_CONFIG_SRCDIR([src/main.cpp]) AC_CONFIG_HEADERS([src/config/bitcoin-config.h]) @@ -61,8 +61,8 @@ case $host in lt_cv_deplibs_check_method="pass_all" ;; esac -dnl Require C++11 compiler (no GNU extensions) -AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory], [nodefault]) +dnl Require C++17 compiler (no GNU extensions) +AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory]) dnl Check if -latomic is required for CHECK_ATOMIC @@ -85,8 +85,8 @@ AC_PATH_TOOL(CPPFILT,c++filt) # Enable wallet AC_ARG_ENABLE([wallet], - [AS_HELP_STRING([--enable-wallet], - [enable wallet (default is yes)])], + [AS_HELP_STRING([--disable-wallet], + [disable wallet (enabled by default)])], [enable_wallet=$enableval], [enable_wallet=yes]) @@ -97,33 +97,32 @@ AC_ARG_ENABLE([mining], [enable_mining=yes]) AC_ARG_ENABLE([proton], - [AS_HELP_STRING([--disable-proton], - [disable Proton (AMQP messaging)])], + [AS_HELP_STRING([--enable-proton], + [enable Proton (AMQP messaging) (default is no)])], [use_proton=$enableval], - [use_proton=yes]) + [use_proton=no]) AC_ARG_ENABLE(tests, - AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]), + AS_HELP_STRING([--disable-tests],[do not compile tests (default is to compile)]), [use_tests=$enableval], [use_tests=yes]) -AC_ARG_ENABLE([asan], - [AS_HELP_STRING([--enable-asan], - [instrument the executables with asan (default is no)])], - [use_asan=$enableval], - [use_asan=no]) +AC_ARG_ENABLE(bench, + AS_HELP_STRING([--enable-bench],[compile benchmarks (default is yes)]), + [use_bench=$enableval], + [use_bench=yes]) -AC_ARG_ENABLE([tsan], - [AS_HELP_STRING([--enable-tsan], - [instrument the executables with tsan (default is no)])], - [use_tsan=$enableval], - [use_tsan=no]) +AC_ARG_ENABLE([fuzz-main], + [AS_HELP_STRING([--enable-fuzz-main], + [Replace main() with a stub for fuzzing (default is no)])], + [use_fuzz_main=$enableval], + [use_fuzz_main=no]) AC_ARG_ENABLE([hardening], - [AS_HELP_STRING([--enable-hardening], - [attempt to harden the resulting executables (default is yes)])], + [AS_HELP_STRING([--disable-hardening], + [do not attempt to harden the resulting executables (default is to harden when possible)])], [use_hardening=$enableval], - [use_hardening=yes]) + [use_hardening=auto]) AC_ARG_ENABLE([reduce-exports], [AS_HELP_STRING([--enable-reduce-exports], @@ -132,8 +131,8 @@ AC_ARG_ENABLE([reduce-exports], [use_reduce_exports=no]) AC_ARG_ENABLE([ccache], - [AS_HELP_STRING([--enable-ccache], - [use ccache for building (default is yes if ccache is found)])], + [AS_HELP_STRING([--disable-ccache], + [do not use ccache for building (default is to use if found)])], [use_ccache=$enableval], [use_ccache=auto]) @@ -166,10 +165,23 @@ AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no) # Enable debug AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug], - [use debug compiler flags and macros (default is no)])], + [use compiler flags and macros suited for debugging (default is no)])], [enable_debug=$enableval], [enable_debug=no]) +# Enable different -fsanitize options +AC_ARG_WITH([sanitizers], + [AS_HELP_STRING([--with-sanitizers], + [comma separated list of extra sanitizers to build with (default is none enabled)])], + [use_sanitizers=$withval]) + +# Enable gprof profiling +AC_ARG_ENABLE([gprof], + [AS_HELP_STRING([--enable-gprof], + [use gprof profiling compiler flags (default is no)])], + [enable_gprof=$enableval], + [enable_gprof=no]) + # Turn warnings into errors AC_ARG_ENABLE([werror], [AS_HELP_STRING([--enable-werror], @@ -181,14 +193,78 @@ AC_LANG_PUSH([C++]) AX_CHECK_COMPILE_FLAG([-Werror],[CXXFLAG_WERROR="-Werror"],[CXXFLAG_WERROR=""]) if test "x$enable_debug" = xyes; then - CPPFLAGS="$CPPFLAGS -DDEBUG -DDEBUG_LOCKORDER" - if test "x$GCC" = xyes; then - CFLAGS="$CFLAGS -g3 -O0" - fi + # Clear default -g -O2 flags + if test "x$CXXFLAGS_overridden" = xno; then + CXXFLAGS="" + fi - if test "x$GXX" = xyes; then - CXXFLAGS="$CXXFLAGS -g3 -O0" - fi + # Disable all optimizations + AX_CHECK_COMPILE_FLAG([-O0], [[DEBUG_CXXFLAGS="$DEBUG_CXXFLAGS -O0"]],,[[$CXXFLAG_WERROR]]) + + # Prefer -g3, fall back to -g if that is unavailable. + AX_CHECK_COMPILE_FLAG( + [-g3], + [[DEBUG_CXXFLAGS="$DEBUG_CXXFLAGS -g3"]], + [AX_CHECK_COMPILE_FLAG([-g],[[DEBUG_CXXFLAGS="$DEBUG_CXXFLAGS -g"]],,[[$CXXFLAG_WERROR]])], + [[$CXXFLAG_WERROR]]) + + AX_CHECK_PREPROC_FLAG([-DDEBUG],[[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DDEBUG"]],,[[$CXXFLAG_WERROR]]) + AX_CHECK_PREPROC_FLAG([-DDEBUG_LOCKORDER],[[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DDEBUG_LOCKORDER"]],,[[$CXXFLAG_WERROR]]) + AX_CHECK_COMPILE_FLAG([-ftrapv],[DEBUG_CXXFLAGS="$DEBUG_CXXFLAGS -ftrapv"],,[[$CXXFLAG_WERROR]]) +else + # Even with enable_debug=no we build with standard debug symbols + AX_CHECK_COMPILE_FLAG([-g],[[DEBUG_CXXFLAGS="$DEBUG_CXXFLAGS -g"]],,[[$CXXFLAG_WERROR]]) + + # -ftrapv and -fwrapv conflict, so we only set this if enable_debug=no + AX_CHECK_COMPILE_FLAG([-fwrapv],[CXXFLAGS="$CXXFLAGS -fwrapv"],,[[$CXXFLAG_WERROR]]) +fi + +if test x$use_sanitizers != x; then + # First check if the compiler accepts flags. If an incompatible pair like + # -fsanitize=address,thread is used here, this check will fail. This will also + # fail if a bad argument is passed, e.g. -fsanitize=undfeined + AX_CHECK_COMPILE_FLAG( + [[-fsanitize=$use_sanitizers]], + [[SANITIZER_CXXFLAGS=-fsanitize=$use_sanitizers]], + [AC_MSG_ERROR([compiler did not accept requested flags])]) + + # Some compilers (e.g. GCC) require additional libraries like libasan, + # libtsan, libubsan, etc. Make sure linking still works with the sanitize + # flag. This is a separate check so we can give a better error message when + # the sanitize flags are supported by the compiler but the actual sanitizer + # libs are missing. + AX_CHECK_LINK_FLAG( + [[-fsanitize=$use_sanitizers]], + [[SANITIZER_LDFLAGS=-fsanitize=$use_sanitizers]], + [AC_MSG_ERROR([linker did not accept requested flags, you are missing required libraries])]) + + AX_CHECK_COMPILE_FLAG( + [-fno-omit-frame-pointer], + [SANITIZER_CXXFLAGS="$SANITIZER_CXXFLAGS -fno-omit-frame-pointer"], + [AC_MSG_ERROR(Cannot enable -fno-omit-frame-pointer)]) + + # libc/libstdc++ static linking is not supported for TSan + case $use_sanitizers in + *thread*) + ;; + *) + AX_CHECK_LINK_FLAG( + [-static-libstdc++], + [SANITIZER_LDFLAGS="$SANITIZER_LDFLAGS -static-libstdc++"], + [AC_MSG_ERROR(Cannot statically link -static-libstdc++)]) + ;; + esac + + case $use_sanitizers in + *address*) + AX_CHECK_LINK_FLAG( + [-static-libasan], + [SANITIZER_LDFLAGS="$SANITIZER_LDFLAGS -static-libasan"], + [AC_MSG_ERROR(Cannot statically link -static-libasan)]) + ;; + *) + ;; + esac fi ERROR_CXXFLAGS= @@ -321,12 +397,7 @@ case $host in dnl It's safe to add these paths even if the functionality is disabled by dnl the user (--without-wallet for example). - openssl_prefix=`$BREW --prefix openssl 2>/dev/null` bdb_prefix=`$BREW --prefix berkeley-db4 2>/dev/null` - if test x$openssl_prefix != x; then - PKG_CONFIG_PATH="$openssl_prefix/lib/pkgconfig:$PKG_CONFIG_PATH" - export PKG_CONFIG_PATH - fi if test x$bdb_prefix != x; then CPPFLAGS="$CPPFLAGS -I$bdb_prefix/include" LIBS="$LIBS -L$bdb_prefix/lib" @@ -442,35 +513,35 @@ else AC_SEARCH_LIBS([clock_gettime],[rt]) fi -if test x$TARGET_OS != xwindows; then - # All windows code is PIC, forcing it on just adds useless compile warnings - AX_CHECK_COMPILE_FLAG([-fPIC],[PIC_FLAGS="-fPIC"]) -fi +if test "x$enable_gprof" = xyes; then + dnl -pg is incompatible with -pie. Since hardening and profiling together doesn't make sense, + dnl we simply make them mutually exclusive here. Additionally, hardened toolchains may force + dnl -pie by default, in which case it needs to be turned off with -no-pie. -#asan and tsan cannot be used together -if test x$use_asan$use_tsan == xyesyes; then - AC_MSG_ERROR(asan and tsan cannot be simultaneously enabled) + if test x$use_hardening = xyes; then + AC_MSG_ERROR(gprof profiling is not compatible with hardening. Reconfigure with --disable-hardening or --disable-gprof) + fi + use_hardening=no + AX_CHECK_COMPILE_FLAG([-pg],[GPROF_CXXFLAGS="-pg"], + [AC_MSG_ERROR(gprof profiling requested but not available)], [[$CXXFLAG_WERROR]]) + + AX_CHECK_LINK_FLAG([[-no-pie]], [GPROF_LDFLAGS="-no-pie"]) + AX_CHECK_LINK_FLAG([[-pg]],[GPROF_LDFLAGS="$GPROF_LDFLAGS -pg"], + [AC_MSG_ERROR(gprof profiling requested but not available)], [[$GPROF_LDFLAGS]]) fi -# using asan flag to enable address sanitizer and undefined behavior sanitizer -if test x$use_asan == xyes; then - AX_CHECK_LINK_FLAG([-static-libstdc++],[SAN_LDFLAGS="$SAN_LDFLAGS -static-libstdc++"],[AC_MSG_ERROR(Cannot statically link -static-libstdc++)]) - AX_CHECK_LINK_FLAG([-static-libasan],[SAN_LDFLAGS="$SAN_LDFLAGS -static-libasan"],[AC_MSG_ERROR(Cannot statically link -static-libasan)]) - AX_CHECK_COMPILE_FLAG([-fsanitize=address],[SAN_CXXFLAGS="$SAN_CXXFLAGS -fsanitize=address"],[AC_MSG_ERROR(Cannot enable -fsanitize=address)]) - AX_CHECK_COMPILE_FLAG([-fsanitize=undefined],[SAN_CXXFLAGS="$SAN_CXXFLAGS -fsanitize=undefined"],[AC_MSG_ERROR(Cannot enable -fsanitize=undefined)]) - AX_CHECK_COMPILE_FLAG([-fno-omit-frame-pointer],[SAN_CXXFLAGS="$SAN_CXXFLAGS -fno-omit-frame-pointer"],[AC_MSG_ERROR(Cannot enable -fno-omit-frame-pointer)]) +if test x$TARGET_OS != xwindows; then + # All windows code is PIC, forcing it on just adds useless compile warnings + AX_CHECK_COMPILE_FLAG([-fPIC],[PIC_FLAGS="-fPIC"]) fi -# using tsan flag to enable address thread sanitizer -# TSAN is supported on Linux x84_64 and tested on Ubuntu 12.04 -# Non-position-independent executables are not supported. Use with -fPIE and -pie flags -# libc/libstdc++ static linking is not supported -if test x$use_tsan == xyes; then - AX_CHECK_COMPILE_FLAG([-fsanitize=thread],[SAN_CXXFLAGS="$SAN_CXXFLAGS -fsanitize=thread"],[AC_MSG_ERROR(Cannot enable -fsanitize=thread)]) - AX_CHECK_COMPILE_FLAG([-fno-omit-frame-pointer],[SAN_CXXFLAGS="$SAN_CXXFLAGS -fno-omit-frame-pointer"],[AC_MSG_ERROR(Cannot enable -fno-omit-frame-pointer)]) +if test x$use_fuzz_main == xyes; then + CFLAGS="$CFLAGS -DZCASH_FUZZ=1" + CXXFLAGS="$CXXFLAGS -DZCASH_FUZZ=1" fi if test x$use_hardening != xno; then + use_hardening=yes AX_CHECK_COMPILE_FLAG([-Wformat],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -Wformat"],[AC_MSG_ERROR(Cannot enable -Wformat)]) AX_CHECK_COMPILE_FLAG([-Wformat-security],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -Wformat-security"],[AC_MSG_ERROR(Cannot enable -Wformat-security)],[-Wformat]) AX_CHECK_COMPILE_FLAG([-Wstack-protector],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -Wstack-protector"],[AC_MSG_ERROR(Cannot enable -Wstack-protector)]) @@ -483,7 +554,7 @@ if test x$use_hardening != xno; then HARDENED_CPPFLAGS="$HARDENED_CPPFLAGS -D_FORTIFY_SOURCE=2" ],[AC_MSG_ERROR(Cannot enable -D_FORTIFY_SOURCE=2)]) - if test x$BUILD_OS = xdarwin || test x$TARGET_OS = xwindows; then + if test x$TARGET_OS = xdarwin || test x$TARGET_OS = xwindows; then # Xcode's ld (at least ld64-302.3) doesn't support -z # mingw-w64's ld (at least mingw-w64 4.0.4-2) also appears to not support -z AX_CHECK_LINK_FLAG([[-Wl,-z,relro]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,relro"],[AC_MSG_WARN(Cannot enable RELRO)]) @@ -581,6 +652,20 @@ if test x$enable_wallet != xno; then BITCOIN_FIND_BDB62 fi +dnl Check to find the libsodium headers/libraries +AC_CHECK_LIB(sodium, sodium_init,[], +[AC_MSG_ERROR([The Sodium crypto library libraries not found.])]) + +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ +#include +], [ +#if SODIUM_LIBRARY_VERSION_MAJOR < 9 || SODIUM_LIBRARY_VERSION_MAJOR == 9 && SODIUM_LIBRARY_VERSION_MINOR < 1 +# error +#endif +])], +[AC_MSG_RESULT([checking for version of libsodium... yes])], +[AC_MSG_ERROR([Wrong libsodium: version >= 1.0.8 required])]) + dnl Check Qpid Proton headers and library exist if test x$use_proton = xyes; then AC_CHECK_HEADERS([proton/connection.hpp], @@ -671,8 +756,6 @@ if test x$use_pkgconfig = xyes; then m4_ifdef( [PKG_CHECK_MODULES], [ - PKG_CHECK_MODULES([SSL], [libssl],, [AC_MSG_ERROR(openssl not found.)]) - PKG_CHECK_MODULES([CRYPTO], [libcrypto],,[AC_MSG_ERROR(libcrypto not found.)]) if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests != xnononono; then PKG_CHECK_MODULES([EVENT], [libevent],, [AC_MSG_ERROR(libevent not found.)]) if test x$TARGET_OS != xwindows; then @@ -692,14 +775,6 @@ if test x$use_pkgconfig = xyes; then ] ) else - # BUG: Fix this: - echo 'BUG: configure does not yet check for the following dependencies if pkg-config is not on the system: libcrypto++, libgmp' - - AC_CHECK_HEADER([openssl/crypto.h],,AC_MSG_ERROR(libcrypto headers missing)) - AC_CHECK_LIB([crypto], [main],CRYPTO_LIBS=-lcrypto, AC_MSG_ERROR(libcrypto missing)) - - AC_CHECK_HEADER([openssl/ssl.h],, AC_MSG_ERROR(libssl headers missing),) - AC_CHECK_LIB([ssl], [main],SSL_LIBS=-lssl, AC_MSG_ERROR(libssl missing)) if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests != xnononono; then AC_CHECK_HEADER([event2/event.h],, AC_MSG_ERROR(libevent headers missing),) @@ -733,14 +808,6 @@ else fi fi -# These packages don't provide pkgconfig config files across all -# platforms, so we use older autoconf detection mechanisms: -AC_CHECK_HEADER([gmp.h],,AC_MSG_ERROR(libgmp headers missing)) -AC_CHECK_LIB([gmp],[[__gmpn_sub_n]],GMP_LIBS=-lgmp, [AC_MSG_ERROR(libgmp missing)]) - -AC_CHECK_HEADER([gmpxx.h],,AC_MSG_ERROR(libgmpxx headers missing)) -AC_CHECK_LIB([gmpxx],[main],GMPXX_LIBS=-lgmpxx, [AC_MSG_ERROR(libgmpxx missing)]) - RUST_LIBS="-lrustzcash" case $host in *mingw*) @@ -750,33 +817,11 @@ case $host in ;; esac -dnl Check for OpenMP support -AX_OPENMP( - [AC_DEFINE(HAVE_OPENMP, 1, [Define if OpenMP is enabled]) - AM_CONDITIONAL([HAVE_OPENMP], [true]) - CPPFLAGS="$CPPFLAGS -DMULTICORE" - CXXFLAGS="$CXXFLAGS $OPENMP_CXXFLAGS"], - [AC_MSG_WARN([OpenMP not supported, disabling multithreading]) - AC_DEFINE(HAVE_OPENMP, 0, [Define if OpenMP is enabled]) - AM_CONDITIONAL([HAVE_OPENMP], [false])]) - -# Gitian uses a config.site that sets depends_prefix, and then sets --prefix=/ -# build.sh just uses --prefix -if test x$depends_prefix != x; then - LIBSNARK_DEPINST="$depends_prefix" -else - LIBSNARK_DEPINST="$prefix" -fi - -# Set optimization flags for libsnark -AX_GCC_ARCHFLAG([no], [LIBSNARK_OPTFLAGS="-O2 $ax_cv_gcc_archflag"], [LIBSNARK_OPTFLAGS="-O2"]) - # Additional BitcoinZ flags -AX_CHECK_COMPILE_FLAG([-fwrapv],[CXXFLAGS="$CXXFLAGS -fwrapv"]) AX_CHECK_COMPILE_FLAG([-fno-strict-aliasing],[CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"]) AX_CHECK_COMPILE_FLAG([-Wno-builtin-declaration-mismatch],[CXXFLAGS="$CXXFLAGS -Wno-builtin-declaration-mismatch"],,[[$CXXFLAG_WERROR]]) -LIBZCASH_LIBS="-lgmp -lgmpxx $BOOST_SYSTEM_LIB -lcrypto -lsodium $RUST_LIBS" +LIBZCASH_LIBS="$BOOST_SYSTEM_LIB -lsodium $RUST_LIBS" AC_MSG_CHECKING([whether to build bitcoind]) AM_CONDITIONAL([BUILD_BITCOIND], [test x$build_bitcoind = xyes]) @@ -840,7 +885,7 @@ AM_CONDITIONAL([ENABLE_ZMQ], [test "x$use_zmq" = "xyes"]) AM_CONDITIONAL([ENABLE_PROTON], [test "x$use_proton" = "xyes"]) -AC_MSG_CHECKING([whether to build test_bitcoin]) +AC_MSG_CHECKING([whether to build test_bitcoinz]) if test x$use_tests = xyes; then AC_MSG_RESULT([yes]) BUILD_TEST="yes" @@ -866,11 +911,10 @@ AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows]) AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes]) AM_CONDITIONAL([ENABLE_MINING],[test x$enable_mining = xyes]) AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes]) +AM_CONDITIONAL([ENABLE_BENCH],[test x$use_bench = xyes]) AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes]) AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes]) AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes]) -AM_CONDITIONAL([ASAN],[test x$use_asan = xyes]) -AM_CONDITIONAL([TSAN],[test x$use_tsan = xyes]) AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version]) AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version]) @@ -889,27 +933,25 @@ AC_SUBST(BITCOIN_CLI_NAME) AC_SUBST(BITCOIN_TX_NAME) AC_SUBST(RELDFLAGS) +AC_SUBST(DEBUG_CPPFLAGS) +AC_SUBST(DEBUG_CXXFLAGS) AC_SUBST(ERROR_CXXFLAGS) -AC_SUBST(SAN_CXXFLAGS) -AC_SUBST(SAN_LDFLAGS) +AC_SUBST(GPROF_CXXFLAGS) +AC_SUBST(GPROF_LDFLAGS) AC_SUBST(HARDENED_CXXFLAGS) AC_SUBST(HARDENED_CPPFLAGS) AC_SUBST(HARDENED_LDFLAGS) AC_SUBST(PIC_FLAGS) AC_SUBST(PIE_FLAGS) +AC_SUBST(SANITIZER_CXXFLAGS) +AC_SUBST(SANITIZER_LDFLAGS) AC_SUBST(LIBTOOL_APP_LDFLAGS) AC_SUBST(BOOST_LIBS) AC_SUBST(TESTDEFS) AC_SUBST(LEVELDB_TARGET_FLAGS) -AC_SUBST(CRYPTO_LIBS) -AC_SUBST(SSL_LIBS) AC_SUBST(EVENT_LIBS) AC_SUBST(EVENT_PTHREADS_LIBS) AC_SUBST(ZMQ_LIBS) -AC_SUBST(GMP_LIBS) -AC_SUBST(GMPXX_LIBS) -AC_SUBST(LIBSNARK_DEPINST) -AC_SUBST(LIBSNARK_OPTFLAGS) AC_SUBST(LIBZCASH_LIBS) AC_SUBST(PROTON_LIBS) AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile src/test/buildenv.py]) @@ -940,7 +982,7 @@ unset PKG_CONFIG_LIBDIR PKG_CONFIG_LIBDIR="$PKGCONFIG_LIBDIR_TEMP" ac_configure_args="${ac_configure_args} --disable-shared --with-pic --with-bignum=no --enable-module-recovery" -AC_CONFIG_SUBDIRS([src/secp256k1 src/snark src/univalue]) +AC_CONFIG_SUBDIRS([src/secp256k1 src/univalue]) AC_OUTPUT @@ -961,7 +1003,9 @@ echo " with wallet = $enable_wallet" echo " with proton = $use_proton" echo " with zmq = $use_zmq" echo " with test = $use_tests" +echo " sanitizers = $use_sanitizers" echo " debug enabled = $enable_debug" +echo " gprof enabled = $enable_gprof" echo " werror = $enable_werror" echo echo " target os = $TARGET_OS" @@ -969,9 +1013,9 @@ echo " build os = $BUILD_OS" echo echo " CC = $CC" echo " CFLAGS = $CFLAGS" -echo " CPPFLAGS = $CPPFLAGS" +echo " CPPFLAGS = $DEBUG_CPPFLAGS $HARDENED_CPPFLAGS $CPPFLAGS" echo " CXX = $CXX" -echo " CXXFLAGS = $CXXFLAGS" -echo " LDFLAGS = $LDFLAGS" +echo " CXXFLAGS = $DEBUG_CXXFLAGS $HARDENED_CXXFLAGS $ERROR_CXXFLAGS $GPROF_CXXFLAGS $CXXFLAGS" +echo " LDFLAGS = $PTHREAD_CFLAGS $HARDENED_LDFLAGS $GPROF_LDFLAGS $LDFLAGS" echo " ARFLAGS = $ARFLAGS" echo diff --git a/contrib/amqp/amqp_sub.py b/contrib/amqp/amqp_sub.py index 8218b0aba..de21dbb25 100644 --- a/contrib/amqp/amqp_sub.py +++ b/contrib/amqp/amqp_sub.py @@ -1,8 +1,8 @@ #!/usr/bin/env python2 # Copyright (c) 2017-2020 The BitcoinZ Community # Copyright (c) 2017-2019 The Zcash developers -# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying -# file COPYING or https://www.opensource.org/licenses/mit-license.php . # file COPYING or https://www.opensource.org/licenses/mit-license.php . +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # Requirements: # pip install python-qpid-proton diff --git a/contrib/bitcoinz-cli.bash-completion b/contrib/bitcoinz-cli.bash-completion index f1ce244ad..c9353bebe 100644 --- a/contrib/bitcoinz-cli.bash-completion +++ b/contrib/bitcoinz-cli.bash-completion @@ -1,5 +1,5 @@ # bash programmable completion for bitcoinz-cli(1) -# Copyright (c) 2017-2020 The BitcoinZ community +# Copyright (c) 2017-2024 The BitcoinZ community # Copyright (c) 2016-2019 The Zcash developers # Copyright (c) 2012-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying diff --git a/contrib/bitcoinz-tx.bash-completion b/contrib/bitcoinz-tx.bash-completion index 20160be62..d0687f3be 100644 --- a/contrib/bitcoinz-tx.bash-completion +++ b/contrib/bitcoinz-tx.bash-completion @@ -1,5 +1,5 @@ # bash programmable completion for bitcoinz-tx(1) -# Copyright (c) 2017-2018 The BitcoinZ Community +# Copyright (c) 2017-2024 The BitcoinZ Community # Copyright (c) 2016-2019 The Zcash developers # Copyright (c) 2012-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying diff --git a/contrib/bitcoinzd.bash-completion b/contrib/bitcoinzd.bash-completion index 229b9059e..2fa5fb1e3 100644 --- a/contrib/bitcoinzd.bash-completion +++ b/contrib/bitcoinzd.bash-completion @@ -1,5 +1,5 @@ # bash programmable completion for bitcoinzd(1) -# Copyright (c) 2017-2020 The BitcoinZ community +# Copyright (c) 2017-2024 The BitcoinZ community # Copyright (c) 2016-2019 The Zcash developers # Copyright (c) 2012-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 3547e241c..62e45bcff 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,15 @@ +bitcoinz (2.0.9-rc2) stable; urgency=medium + + * 2.0.9-rc2 release. + + -- The BitcoinZ Community Jul 2024 + +bitcoinz (2.0.9-rc1) stable; urgency=medium + + * 2.0.9-rc1 release. + + -- The BitcoinZ Community Jul 2024 + bitcoinz (2.0.8) stable; urgency=low * 2.0.8 release. diff --git a/contrib/debian/control b/contrib/debian/control index 30ae24bf1..5f3db9bd1 100644 --- a/contrib/debian/control +++ b/contrib/debian/control @@ -8,10 +8,15 @@ Build-Depends: autoconf, automake, bsdmainutils, build-essential, m4, ncurses-dev, pkg-config, python, unzip, wget, zlib1g-dev Vcs-Git: https://github.com/btcz/bitcoinz.git -Vcs-Browser: https://github.com/btcz +Vcs-Browser: https://github.com/btcz/bitcoinz Package: bitcoinz -Version: 1.4.0 +Architecture: amd64 Depends: ${shlibs:Depends} -Architecture: all -Description: BitcoinZ is a decentralized community project based on the Bitcoin and Zcash codebase. +Description: BitcoinZ libraries and tools + Based on Bitcoin's code, it intends to offer a far higher standard + of privacy and anonymity through a sophisticiated zero-knowledge + proving scheme which preserves confidentiality of transaction metadata. + Think of it as HTTPS for money. + This package provides the daemon, bitcoinzd, and the CLI tool, + bitcoinz-cli, to interact with the daemon. diff --git a/contrib/debian/copyright b/contrib/debian/copyright index c918e8889..32a2cafb1 100644 --- a/contrib/debian/copyright +++ b/contrib/debian/copyright @@ -4,27 +4,87 @@ Upstream-Contact: The BitcoinZ Community Source: https://github.com/btcz/bitcoinz Files: * -Copyright: 2017-2019 The BitcoinZ Community - 2016-2018, The Zcash developers - 2016-2018, The Zcash developers - 2009-2018, Bitcoin Core developers +Copyright: 2017-2024 The BitcoinZ Community + 2016-2019, The Zcash developers + 2009-2019, Bitcoin Core developers + 2009-2019, Bitcoin Developers License: Expat -Comment: The Bitcoin Core developers encompasses the current developers listed on bitcoin.org, - as well as the numerous contributors to the project. - The Zcash developers are listed at https://z.cash/team.html. +Comment: The Bitcoin Core developers encompasses the current developers listed on + bitcoin.org, as well as the numerous contributors to the project. + The Zcash developers are listed at https://z.cash/team.html and in doc/authors.md. + This copyright entry excludes files explicitly listed below. + +Files: build-aux/m4/ax_boost_base.m4 +Copyright: 2008, Thomas Porschberg + 2009, Peter Adolphs +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_boost_chrono.m4 +Copyright: 2012, Xiyue Deng +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_boost_filesystem.m4 +Copyright: 2009, Thomas Porschberg + 2009, Michael Tindal + 2009, Roman Rybalko +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_boost_program_options.m4 +Copyright: 2009, Thomas Porschberg +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_boost_system.m4 +Copyright: 2008, Thomas Porschberg + 2008, Michael Tindal + 2008, Daniel Casimiro +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_boost_thread.m4 +Copyright: 2009, Thomas Porschberg + 2009, Michael Tindal +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_boost_unit_test_framework.m4 +Copyright: 2008, Thomas Porschberg +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_cxx_compile_stdcxx.m4 +Copyright: 2008, Benjamin Kosnik + 2012, Zack Weinberg + 2013, Roy Stogner + 2014-2015, Google Inc.; contributed by Alexey Sokolov + 2015, Paul Norman + 2015, Moritz Klammler +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_gcc_func_attribute.m4 +Copyright: 2013, Gabriele Svelto +License: GNU-All-permissive-License + +Files: build-aux/m4/l_atomic.m4 +Copyright: 2015, Tim Kosse +License: GNU-All-permissive-License + +Files: build-aux/m4/ax_check_compile_flag.m4 + build-aux/m4/ax_check_link_flag.m4 + build-aux/m4/ax_check_preproc_flag.m4 +Copyright: 2008, Guido U. Draheim + 2011, Maarten Bosmans +License: GPLv3-or-later-with-Autoconf-exception + +Files: build-aux/m4/ax_pthread.m4 +Copyright: 2008, Steven G. Johnson + 2011, Daniel Richard G. +License: GPLv3-or-later-with-Autoconf-exception + +Files: qa/bitcoinz/checksec.sh +Copyright: 2009-2011, Tobias Klein +License: BSD-3clause-Tobias-Klein Files: depends/sources/libsodium-*.tar.gz Copyright: 2013-2016 Frank Denis License: ISC -Files: depends/sources/libsnark-*.tar.gz -Copyright: 2012-2016 SCIPR Lab and contributors; 2016 The Zcash developers -License: Expat - -Files: depends/sources/gmp-*.tar.bz2 -Copyright: 1991, 1996, 1999, 2000, 2007 Free Software Foundation, Inc. -License: LGPL - Files: depends/sources/boost_*.tar.gz Copyright: 2008 Beman Dawes License: Boost-Software-License-1.0 @@ -36,10 +96,6 @@ Copyright: 1990, 2016 Oracle and/or its affiliates; 2000-2005 INRIA, France Telecom License: BDB -Files: depends/sources/openssl-*.tar.gz -Copyright: 1998-2016 The OpenSSL Project and 1995-1998 Eric Young -License: OpenSSL+SSLeay - Files: depends/sources/zeromq-*.tar.gz Copyright: 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. @@ -65,6 +121,15 @@ Files: depends/sources/utfcpp-*.tar.gz Copyright: 2006 Nemanja Trifunovic License: Boost-Software-License-1.0 +Files: src/crypto/ctaes/* +Copyright: Copyright (c) 2016 Pieter Wuille +License: Expat + +Files: src/secp256k1/* +Copyright: Copyright (c) 2013 Pieter Wuille +License: Expat +Comment: This copyright entry excludes files explicitly listed below. + Files: src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 Copyright: 2008 Don Anderson License: GNU-All-permissive-License @@ -73,6 +138,11 @@ Files: src/secp256k1/build-aux/m4/ax_prog_cc_for_build.m4 Copyright: 2008 Paolo Bonzini License: GNU-All-permissive-License +Files src/leveldb/* +Copyright: 2011, The LevelDB Authors +License: BSD-3clause-Google +Comment: The LevelDB Authors are listed in src/leveldb/AUTHORS. + License: Boost-Software-License-1.0 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by @@ -855,128 +925,6 @@ License: BDB * THE POSSIBILITY OF SUCH DAMAGE. */ -License: OpenSSL+SSLeay - The OpenSSL toolkit stays under a dual license, i.e. both the conditions of - the OpenSSL License and the original SSLeay license apply to the toolkit. - See below for the actual license texts. - . - OpenSSL License - --------------- - . - /* ==================================================================== - * Copyright (c) 1998-2016 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ - . - Original SSLeay License - ----------------------- - . - /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - License: BSD-3clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -1048,6 +996,31 @@ License: BSD-3clause-Google (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +License: BSD-3clause-Tobias-Klein + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + . + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Tobias Klein nor the name of trapkit.de may be used + to endorse or promote products derived from this software without specific + prior written permission. + . + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + License: ISC Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -1327,3 +1300,33 @@ License: GNU-All-permissive-License permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty. + +License: GPLv3-or-later-with-Autoconf-exception + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + . + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + Public License for more details. + . + You should have received a copy of the GNU General Public License along + with this program. If not, see . + . + As a special exception, the respective Autoconf Macro's copyright owner + gives unlimited permission to copy, distribute and modify the configure + scripts that are the output of Autoconf when processing the Macro. You + need not follow the terms of the GNU General Public License when using + or distributing such scripts, even though portions of the text of the + Macro appear in them. The GNU General Public License (GPL) does govern + all other use of the material that constitutes the Autoconf Macro. + . + This special exception to the GPL applies to versions of the Autoconf + Macro released by the Autoconf Archive. When you make and distribute a + modified version of the Autoconf Macro, you may extend this special + exception to the GPL to apply to your modified version as well. +Comment: + The "special exception" is extended to the versions of files covered by + this license that are distributed with this software. diff --git a/contrib/gitian-descriptors/README.md b/contrib/gitian-descriptors/README.md index 07c2ba98b..614970659 100644 --- a/contrib/gitian-descriptors/README.md +++ b/contrib/gitian-descriptors/README.md @@ -1,8 +1,7 @@ -### Gavin's notes on getting gitian builds up and running using KVM:### +### Gavin's notes on getting gitian builds up and running using KVM -These instructions distilled from: -[ https://help.ubuntu.com/community/KVM/Installation]( https://help.ubuntu.com/community/KVM/Installation) -... see there for complete details. +These instructions distilled from +[https://help.ubuntu.com/community/KVM/Installation](https://help.ubuntu.com/community/KVM/Installation). You need the right hardware: you need a 64-bit-capable CPU with hardware virtualization support (Intel VT-x or AMD-V). Not all modern CPUs support hardware virtualization. @@ -33,14 +32,14 @@ Once you've got the right hardware and software: # Get inputs (see doc/release-process.md for exact inputs needed and where to get them) ... - # For further build instructions see doc/release-notes.md + # For further build instructions see doc/release-process.md ... --------------------- `gitian-builder` now also supports building using LXC. See -[ https://help.ubuntu.com/12.04/serverguide/lxc.html]( https://help.ubuntu.com/12.04/serverguide/lxc.html) -... for how to get LXC up and running under Ubuntu. +[help.ubuntu.com](https://help.ubuntu.com/14.04/serverguide/lxc.html) +for how to get LXC up and running under Ubuntu. If your main machine is a 64-bit Mac or PC with a few gigabytes of memory and at least 10 gigabytes of free disk space, you can `gitian-build` using diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 7df13dec6..31b2c74f2 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "bitcoinz-2.0.8" +name: "bitcoinz-2.0.9-rc2" enable_cache: true distro: "debian" suites: diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 794a82af8..65533d060 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -24,10 +24,10 @@ remotes: - "url": "https://github.com/bitcoin/bitcoin.git" "dir": "bitcoin" files: -- "MacOSX10.9.sdk.tar.gz" +- "Xcode-11.3.1-11C505-extracted-SDK-with-libcxx-headers.tar.gz" script: | WRAP_DIR=$HOME/wrapped - HOSTS="x86_64-apple-darwin11" + HOSTS="x86_64-apple-darwin18" CONFIGFLAGS="--enable-reduce-exports --disable-bench GENISOIMAGE=$WRAP_DIR/genisoimage" FAKETIME_HOST_PROGS="" FAKETIME_PROGS="ar ranlib date dmg genisoimage" @@ -48,7 +48,7 @@ script: | function create_global_faketime_wrappers { for prog in ${FAKETIME_PROGS}; do - echo '#!/bin/bash' > ${WRAP_DIR}/${prog} + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${prog} echo "REAL=\`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1\`" >> ${WRAP_DIR}/${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${prog} echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${prog} @@ -60,7 +60,7 @@ script: | function create_per-host_faketime_wrappers { for i in $HOSTS; do for prog in ${FAKETIME_HOST_PROGS}; do - echo '#!/bin/bash' > ${WRAP_DIR}/${i}-${prog} + echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog} echo "REAL=\`which -a ${i}-${prog} | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} echo 'export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1' >> ${WRAP_DIR}/${i}-${prog} echo "export FAKETIME=\"$1\"" >> ${WRAP_DIR}/${i}-${prog} @@ -80,7 +80,7 @@ script: | BASEPREFIX=`pwd`/depends mkdir -p ${BASEPREFIX}/SDKs - tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/MacOSX10.9.sdk.tar.gz + tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/Xcode-11.3.1-11C505-extracted-SDK-with-libcxx-headers.tar.gz # Build dependencies for each host for i in $HOSTS; do diff --git a/contrib/simulations/worstcase.py b/contrib/simulations/worstcase.py new file mode 100755 index 000000000..8b583dc11 --- /dev/null +++ b/contrib/simulations/worstcase.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python3 +import csv +import os +import subprocess + +# +# Constants +# + +MAX_BLOCK_SIZE = 2000000 + +# +# Verification times +# + +def collect_times(): + # Find bench_bitcoinz binary + script_dir = os.path.dirname(os.path.realpath(__file__)) + base_dir = os.path.dirname(os.path.dirname(script_dir)) + bench_bitcoinz = os.path.join(base_dir, 'src', 'bench', 'bench_bitcoinz') + + # Run bench_bitcoinz binary + try: + result = subprocess.run([bench_bitcoinz], stdout=subprocess.PIPE, universal_newlines=True) + result.check_returncode() + result = result.stdout + except AttributeError: + # Use the older API + result = subprocess.check_output([bench_bitcoinz], universal_newlines=True) + + # Collect benchmarks + benchmarks = {} + for row in result.strip().split('\n')[1:]: # Skip the headings + parts = row.split(',') + benchmarks[parts[0]] = int(parts[2]) + + return { + 'proof': benchmarks['SaplingOutput'], + 'ecdsa': benchmarks['ECDSA'], + 'redjubjub': benchmarks['SaplingSpend'] - benchmarks['SaplingOutput'], + 'ed25519': benchmarks['JoinSplitSig'], + } + +# +# Size calculations +# + +def compact_size_size(nSize): + if nSize < 253: + return 1 + elif nSize <= 0xFFFF: + return 3 + elif nSize <= 0xFFFFFFFF: + return 5 + else: + return 9 + +def script_size(script): + return ( + compact_size_size(len(script)) + + len(script) + ) + +def tx_in_size(scriptSig): + return ( + 32 + # prevout.hash + 4 + # prevout.n + script_size(scriptSig) + + 4 # nSequence + ) + +def tx_out_size(scriptPubKey): + return ( + 8 + # nValue + script_size(scriptPubKey) + ) + +def v4_tx_size(vin, vout, nShieldedSpend, nShieldedOutput, nJoinSplit): + return ( + 4 + # header + 4 + # nVersionGroupId + compact_size_size(len(vin)) + + sum([tx_in_size(scriptSig) for scriptSig in vin]) + + compact_size_size(len(vout)) + + sum([tx_out_size(scriptPubKey) for scriptPubKey in vout]) + + 4 + # lock_time + 4 + # nExpiryHeight + 4 + # valueBalance + compact_size_size(nShieldedSpend) + + (384 * nShieldedSpend) + + compact_size_size(nShieldedOutput) + + (948 * nShieldedOutput) + + compact_size_size(nJoinSplit) + + (1698 * nJoinSplit) + + ((32 + 64) if nJoinSplit > 0 else 0) + # joinSplitPubKey + joinSplitSig + (64 if (nShieldedSpend + nShieldedOutput) > 0 else 0) # bindingSig + ) + +def block_size(vtx): + return ( + 4 + # nVersion + 32 + # hashPrevBlock + 32 + # hashMerkleRoot + 32 + # hashFinalSaplingRoot + 4 + # nTime + 4 + # nBits + 32 + # nNonce + compact_size_size(1344) + # solutionSize + 1344 + # solution + compact_size_size(len(vtx)) + + sum([v4_tx_size(**tx) for tx in vtx]) + ) + +# +# Runners +# + +def worst_case_many_identical_txs(tx): + vtx = [] + while True: + vtx.append(tx) + if block_size(vtx) > MAX_BLOCK_SIZE: + # Keep under the size limit + vtx.pop() + break + return vtx + +def worst_case_one_tx_containing(item): + vtx = [{ + 'vin': [], + 'vout': [], + 'nShieldedSpend': 0, + 'nShieldedOutput': 0, + 'nJoinSplit': 0, + }] + while True: + vtx[0][item] += 1 + if block_size(vtx) > MAX_BLOCK_SIZE: + # Keep under the size limit + vtx[0][item] -= 1 + break + return vtx + +def print_makeup(vtx, times): + # One proof per Sapling spend, Sapling output, and JoinSplit + proofs = sum([tx['nShieldedSpend'] + tx['nShieldedOutput'] + tx['nJoinSplit'] for tx in vtx]) + + # One ECDSA signature per transparent input + ecdsa_sigs = sum([len(tx['vin']) for tx in vtx]) + + # One RedJubjub signature per Sapling spend (spendAuthSig) and per transaction (bindingSig) + redjubjub_sigs = sum([tx['nShieldedSpend'] + ( + 1 if tx['nShieldedSpend'] + tx['nShieldedOutput'] > 0 else 0) for tx in vtx]) + + # One Ed25519 signature per transaction that contains JoinSplits + ed25519_sigs = sum([1 if tx['nJoinSplit'] > 0 else 0 for tx in vtx]) + + print('- Block size: ', block_size(vtx), 'bytes') + print('- Transactions: ', len(vtx)) + print('- Proofs: ', proofs) + print('- ECDSA signatures: ', ecdsa_sigs) + print('- RedJubjub signatures:', redjubjub_sigs) + print('- Ed25519 signatures: ', ed25519_sigs) + print('- Verification time: %0.2f seconds' % (float( + (times['proof'] * proofs) + + (times['ecdsa'] * ecdsa_sigs) + + (times['redjubjub'] * redjubjub_sigs) + + (times['ed25519'] * ed25519_sigs) + ) / 10**9)) + +# +# Worst-case scenarios +# + +def worst_case_one_sapling_spend_per_tx(times): + vtx = worst_case_many_identical_txs({ + 'vin': [], + 'vout': [], + 'nShieldedSpend': 1, + 'nShieldedOutput': 0, + 'nJoinSplit': 0, + }) + print('One Sapling spend per transaction:') + print_makeup(vtx, times) + print() + +def worst_case_one_tx_containing_sapling_spends(times): + vtx = worst_case_one_tx_containing('nShieldedSpend') + print('One transaction containing Sapling spends:') + print_makeup(vtx, times) + print() + +def worst_case_one_sapling_output_per_tx(times): + vtx = worst_case_many_identical_txs({ + 'vin': [], + 'vout': [], + 'nShieldedSpend': 0, + 'nShieldedOutput': 1, + 'nJoinSplit': 0, + }) + print('One Sapling output per transaction:') + print_makeup(vtx, times) + print() + +def worst_case_one_tx_containing_sapling_outputs(times): + vtx = worst_case_one_tx_containing('nShieldedOutput') + print('One transaction containing Sapling outputs:') + print_makeup(vtx, times) + print() + +def worst_case_one_joinsplit_per_tx(times): + vtx = worst_case_many_identical_txs({ + 'vin': [], + 'vout': [], + 'nShieldedSpend': 0, + 'nShieldedOutput': 0, + 'nJoinSplit': 1, + }) + print('One JoinSplit per transaction:') + print_makeup(vtx, times) + print() + +def worst_case_one_tx_containing_joinsplits(times): + vtx = worst_case_one_tx_containing('nJoinSplit') + print('One transaction containing JoinSplits:') + print_makeup(vtx, times) + print() + + +def run(): + print('Collecting benchmarks...') + times = collect_times() + # times = hard_coded_times() + print('Times (ns):', times) + print() + + print('Running worst-case simulations...') + worst_case_one_sapling_spend_per_tx(times) + worst_case_one_tx_containing_sapling_spends(times) + worst_case_one_sapling_output_per_tx(times) + worst_case_one_tx_containing_sapling_outputs(times) + worst_case_one_joinsplit_per_tx(times) + worst_case_one_tx_containing_joinsplits(times) + +if __name__ == '__main__': + run() diff --git a/contrib/testgen/gen_base58_test_vectors.py b/contrib/testgen/gen_base58_test_vectors.py index 181343695..17b85667a 100755 --- a/contrib/testgen/gen_base58_test_vectors.py +++ b/contrib/testgen/gen_base58_test_vectors.py @@ -15,10 +15,10 @@ from binascii import b2a_hex # key types -PUBKEY_ADDRESS = 0 -SCRIPT_ADDRESS = 5 -PUBKEY_ADDRESS_TEST = 111 -SCRIPT_ADDRESS_TEST = 196 +PUBKEY_ADDRESS = (0x1C, 0xB8) +SCRIPT_ADDRESS = (0x1C, 0xBD) +PUBKEY_ADDRESS_TEST = (0x1D, 0x25) +SCRIPT_ADDRESS_TEST = (0x1C, 0xBA) PRIVKEY = 128 PRIVKEY_TEST = 239 @@ -27,10 +27,10 @@ templates = [ # prefix, payload_size, suffix, metadata # None = N/A - ((PUBKEY_ADDRESS,), 20, (), (False, False, 'pubkey', None)), - ((SCRIPT_ADDRESS,), 20, (), (False, False, 'script', None)), - ((PUBKEY_ADDRESS_TEST,), 20, (), (False, True, 'pubkey', None)), - ((SCRIPT_ADDRESS_TEST,), 20, (), (False, True, 'script', None)), + (PUBKEY_ADDRESS, 20, (), (False, False, 'pubkey', None)), + (SCRIPT_ADDRESS, 20, (), (False, False, 'script', None)), + (PUBKEY_ADDRESS_TEST, 20, (), (False, True, 'pubkey', None)), + (SCRIPT_ADDRESS_TEST, 20, (), (False, True, 'script', None)), ((PRIVKEY,), 32, (), (True, False, None, False)), ((PRIVKEY,), 32, (1,), (True, False, None, True)), ((PRIVKEY_TEST,), 32, (), (True, True, None, False)), diff --git a/contrib/verifysfbinaries/README.md b/contrib/verifysfbinaries/README.md index 8c038865b..1db3fe52f 100644 --- a/contrib/verifysfbinaries/README.md +++ b/contrib/verifysfbinaries/README.md @@ -1,6 +1,6 @@ -### Verify SF Binaries ### +### Verify Binaries ### This script attempts to download the signature file `SHA256SUMS.asc` from https://bitcoin.org. It first checks if the signature passes, and then downloads the files specified in the file, and checks if the hashes of these files match those that are specified in the signature file. -The script returns 0 if everything passes the checks. It returns 1 if either the signature check or the hash check doesn't pass. If an error occurs the return value is 2. \ No newline at end of file +The script returns 0 if everything passes the checks. It returns 1 if either the signature check or the hash check doesn't pass. If an error occurs the return value is 2. diff --git a/depends/Makefile b/depends/Makefile index aa07755f0..8c81804e2 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -15,6 +15,8 @@ DOWNLOAD_CONNECT_TIMEOUT:=10 DOWNLOAD_RETRIES:=3 CRATE_REGISTRY:=vendored-sources +LIBRUSTZCASH_OVERRIDE ?= + host:=$(BUILD) ifneq ($(HOST),) host:=$(HOST) @@ -38,6 +40,7 @@ build_vendor=$(word 2,$(subst -, ,$(build))) full_build_os:=$(subst $(build_arch)-$(build_vendor)-,,$(build)) build_os:=$(findstring linux,$(full_build_os)) build_os+=$(findstring darwin,$(full_build_os)) +build_os+=$(findstring freebsd,$(full_build_os)) build_os:=$(strip $(build_os)) ifeq ($(build_os),) build_os=$(full_build_os) @@ -48,6 +51,7 @@ host_vendor=$(word 2,$(subst -, ,$(canonical_host))) full_host_os:=$(subst $(host_arch)-$(host_vendor)-,,$(canonical_host)) host_os:=$(findstring linux,$(full_host_os)) host_os+=$(findstring darwin,$(full_host_os)) +host_os+=$(findstring freebsd,$(full_host_os)) host_os+=$(findstring mingw32,$(full_host_os)) host_os:=$(strip $(host_os)) ifeq ($(host_os),) @@ -73,7 +77,9 @@ include builders/default.mk include packages/packages.mk wallet_packages_$(NO_WALLET) = $(wallet_packages) -proton_packages_$(NO_PROTON) = $(proton_packages) + +NO_PROTON_$(WITH_PROTON) = 1 +proton_packages_$(NO_PROTON_) = $(proton_packages) packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(rust_packages) $(proton_packages_) $(wallet_packages_) native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages) @@ -146,7 +152,7 @@ install: check-packages $(host_prefix)/share/config.site download-one: check-sources $(all_sources) download-osx: - @$(MAKE) -s HOST=x86_64-apple-darwin11 download-one + @$(MAKE) -s HOST=x86_64-apple-darwin18 download-one download-linux: @$(MAKE) -s HOST=x86_64-unknown-linux-gnu download-one download-win: diff --git a/depends/README.md b/depends/README.md index 41898de1a..96634863b 100644 --- a/depends/README.md +++ b/depends/README.md @@ -22,7 +22,7 @@ Common `host-platform-triplets` for cross compilation are: - `i686-w64-mingw32` for Win32 - `x86_64-w64-mingw32` for Win64 -- `x86_64-apple-darwin11` for MacOSX +- `x86_64-apple-darwin18` for MacOSX - `arm-linux-gnueabihf` for Linux ARM No other options are needed, the paths are automatically configured. @@ -36,6 +36,7 @@ The following can be set when running make: make FOO=bar PRIORITY_DOWNLOAD_PATH: Try fetching source files from here before using their own URLs NO_WALLET: Don't download/build/cache libs needed to enable the wallet DEBUG: disable some optimizations and enable more runtime checking + LIBRUSTZCASH_OVERRIDE: Path to a local librustzcash repository If some packages are not built, for example `make NO_WALLET=1`, the appropriate options will be passed to bitcoin's configure. In this case, `--disable-wallet`. diff --git a/depends/builders/darwin.mk b/depends/builders/darwin.mk index 27f550ab0..f8ff4e23a 100644 --- a/depends/builders/darwin.mk +++ b/depends/builders/darwin.mk @@ -10,8 +10,8 @@ build_darwin_SHA256SUM = shasum -a 256 build_darwin_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o #darwin host on darwin builder. overrides darwin host preferences. -darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION) -darwin_CXX:=$(shell xcrun -f clang++) -mmacosx-version-min=$(OSX_MIN_VERSION) -stdlib=libc++ +darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION) -fvisibility=hidden -fvisibility-inlines-hidden --sysroot $(shell xcrun --show-sdk-path) +darwin_CXX:=$(shell xcrun -f clang++) -mmacosx-version-min=$(OSX_MIN_VERSION) -fvisibility=hidden -fvisibility-inlines-hidden -stdlib=libc++ --sysroot $(shell xcrun --show-sdk-path) darwin_AR:=$(shell xcrun -f ar) darwin_RANLIB:=$(shell xcrun -f ranlib) darwin_STRIP:=$(shell xcrun -f strip) diff --git a/depends/builders/freebsd.mk b/depends/builders/freebsd.mk new file mode 100644 index 000000000..fb2fefe2a --- /dev/null +++ b/depends/builders/freebsd.mk @@ -0,0 +1,2 @@ +build_freebsd_SHA256SUM = shasum -a 256 +build_freebsd_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o diff --git a/depends/funcs.mk b/depends/funcs.mk index f17b246a4..35ca5abcf 100644 --- a/depends/funcs.mk +++ b/depends/funcs.mk @@ -40,7 +40,7 @@ endef define vendor_crate_source mkdir -p $($(1)_staging_prefix_dir)/$(CRATE_REGISTRY) && \ -cp -r $($(1)_extract_dir) $($(1)_staging_prefix_dir)/$(CRATE_REGISTRY)/$($(1)_crate_name) && \ +cp -r $($(1)_extract_dir) $($(1)_staging_prefix_dir)/$(CRATE_REGISTRY)/$($(1)_crate_versioned_name) && \ cd $($(1)_staging_prefix_dir)/$(CRATE_REGISTRY)/$($(1)_crate_versioned_name) && \ rm -r `basename $($(1)_patch_dir)` .stamp_* .$($(1)_file_name).hash endef @@ -91,8 +91,9 @@ $(1)_download_path_fixed=$(subst :,\:,$$($(1)_download_path)) #default commands +# The default behavior for tar will try to set ownership when running as uid 0 and may not succeed, --no-same-owner disables this behavior $(1)_fetch_cmds ?= $(call fetch_file,$(1),$(subst \:,:,$$($(1)_download_path_fixed)),$$($(1)_download_file),$($(1)_file_name),$($(1)_sha256_hash)) -$(1)_extract_cmds ?= mkdir -p $$($(1)_extract_dir) && echo "$$($(1)_sha256_hash) $$($(1)_source)" > $$($(1)_extract_dir)/.$$($(1)_file_name).hash && $(build_SHA256SUM) -c $$($(1)_extract_dir)/.$$($(1)_file_name).hash && tar --strip-components=1 -xf $$($(1)_source) +$(1)_extract_cmds ?= mkdir -p $$($(1)_extract_dir) && echo "$$($(1)_sha256_hash) $$($(1)_source)" > $$($(1)_extract_dir)/.$$($(1)_file_name).hash && $(build_SHA256SUM) -c $$($(1)_extract_dir)/.$$($(1)_file_name).hash && tar --no-same-owner --strip-components=1 -xf $$($(1)_source) $(1)_preprocess_cmds ?= $(1)_build_cmds ?= $(1)_config_cmds ?= @@ -193,7 +194,7 @@ $($(1)_preprocessed): | $($(1)_dependencies) $($(1)_extracted) $(AT)touch $$@ $($(1)_configured): | $($(1)_preprocessed) $(AT)echo Configuring $(1)... - $(AT)rm -rf $(host_prefix); mkdir -p $(host_prefix)/lib; cd $(host_prefix); $(foreach package,$($(1)_all_dependencies), tar xf $($(package)_cached); ) + $(AT)rm -rf $(host_prefix); mkdir -p $(host_prefix)/lib; cd $(host_prefix); $(foreach package,$($(1)_all_dependencies), tar --no-same-owner -xf $($(package)_cached); ) $(AT)mkdir -p $$(@D) $(AT)+cd $$(@D); $($(1)_config_env) $(call $(1)_config_cmds, $(1)) $(AT)touch $$@ diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk index 939988197..259ff2864 100644 --- a/depends/hosts/darwin.mk +++ b/depends/hosts/darwin.mk @@ -1,17 +1,43 @@ -OSX_MIN_VERSION=10.8 -OSX_SDK_VERSION=10.11 -OSX_SDK=$(SDK_PATH)/MacOSX$(OSX_SDK_VERSION).sdk -LD64_VERSION=253.9 -darwin_CC=clang -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -darwin_CXX=clang++ -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -stdlib=libc++ +OSX_MIN_VERSION=10.14 +XCODE_VERSION=11.3.1 +XCODE_BUILD_ID=11C505 +LD64_VERSION=530 + +OSX_SDK=$(SDK_PATH)/Xcode-$(XCODE_VERSION)-$(XCODE_BUILD_ID)-extracted-SDK-with-libcxx-headers + +# Flag explanations: +# +# -mlinker-version +# +# Ensures that modern linker features are enabled. See here for more +# details: https://github.com/bitcoin/bitcoin/pull/19407. +# +# -B$(build_prefix)/bin +# +# Explicitly point to our binaries (e.g. cctools) so that they are +# ensured to be found and preferred over other possibilities. +# +# -nostdinc++ -isystem $(OSX_SDK)/usr/include/c++/v1 +# +# Forces clang to use the libc++ headers from our SDK and completely +# forget about the libc++ headers from the standard directories +# +# TODO: Once we start requiring a clang version that has the +# -stdlib++-isystem flag first introduced here: +# https://reviews.llvm.org/D64089, we should use that instead. Read the +# differential summary there for more details. +# +darwin_CC=clang -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -B$(build_prefix)/bin +darwin_CXX=clang++ -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -stdlib=libc++ -mlinker-version=$(LD64_VERSION) -B$(build_prefix)/bin -nostdinc++ -isystem $(OSX_SDK)/usr/include/c++/v1 darwin_CFLAGS=-pipe darwin_CXXFLAGS=$(darwin_CFLAGS) -darwin_release_CFLAGS=-O1 +darwin_release_CFLAGS=-O2 darwin_release_CXXFLAGS=$(darwin_release_CFLAGS) darwin_debug_CFLAGS=-O1 darwin_debug_CXXFLAGS=$(darwin_debug_CFLAGS) +darwin_native_binutils=native_cctools darwin_native_toolchain=native_cctools diff --git a/depends/hosts/freebsd.mk b/depends/hosts/freebsd.mk new file mode 100644 index 000000000..07436aef8 --- /dev/null +++ b/depends/hosts/freebsd.mk @@ -0,0 +1,31 @@ +freebsd_CFLAGS=-pipe +freebsd_CXXFLAGS=$(freebsd_CFLAGS) + +freebsd_release_CFLAGS=-O1 +freebsd_release_CXXFLAGS=$(freebsd_release_CFLAGS) + +freebsd_debug_CFLAGS=-O1 +freebsd_debug_CXXFLAGS=$(freebsd_debug_CFLAGS) + +freebsd_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC + +ifeq (86,$(findstring 86,$(build_arch))) +i686_freebsd_CC=gcc -m32 +i686_freebsd_CXX=g++ -m32 +i686_freebsd_AR=ar +i686_freebsd_RANLIB=ranlib +i686_freebsd_NM=nm +i686_freebsd_STRIP=strip + +x86_64_freebsd_CC=gcc -m64 +x86_64_freebsd_CXX=g++ -m64 +x86_64_freebsd_AR=ar +x86_64_freebsd_RANLIB=ranlib +x86_64_freebsd_NM=nm +x86_64_freebsd_STRIP=strip +else +i686_freebsd_CC=$(default_host_CC) -m32 +i686_freebsd_CXX=$(default_host_CXX) -m32 +x86_64_freebsd_CC=$(default_host_CC) -m64 +x86_64_freebsd_CXX=$(default_host_CXX) -m64 +endif diff --git a/depends/hosts/mingw32.mk b/depends/hosts/mingw32.mk index 2248973a1..4f5f80503 100644 --- a/depends/hosts/mingw32.mk +++ b/depends/hosts/mingw32.mk @@ -1,6 +1,9 @@ mingw32_CFLAGS=-pipe mingw32_CXXFLAGS=$(mingw32_CFLAGS) +mingw32_LDFLAGS?=-fuse-ld=lld +mingw32_LDFLAGS+=-L/usr/lib/gcc/x86_64-w64-mingw32/$(shell x86_64-w64-mingw32-g++-posix -dumpversion) + mingw32_release_CFLAGS=-O1 mingw32_release_CXXFLAGS=$(mingw32_release_CFLAGS) diff --git a/depends/packages.md b/depends/packages.md index 7c8036250..7d2bd4670 100644 --- a/depends/packages.md +++ b/depends/packages.md @@ -14,8 +14,9 @@ Each package is required to define at least these variables: placeholder such as 1.0 can be used. $(package)_download_path: - Location of the upstream source, without the file-name. Usually http or - ftp. + Location of the upstream source, without the file-name. Usually http, https + or ftp. Secure transmission options like https should be preferred if + available. $(package)_file_name: The upstream source filename available at the download path. diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk index 21019aeb7..fae0783cf 100644 --- a/depends/packages/bdb.mk +++ b/depends/packages/bdb.mk @@ -9,8 +9,12 @@ define $(package)_set_vars $(package)_config_opts=--disable-shared --enable-cxx --disable-replication $(package)_config_opts_mingw32=--enable-mingw $(package)_config_opts_linux=--with-pic +$(package)_config_opts_freebsd=--with-pic +ifneq ($(build_os),darwin) +$(package)_config_opts_darwin=--disable-atomicsupport +endif $(package)_config_opts_aarch64=--disable-atomicsupport -$(package)_cxxflags=-std=c++11 +$(package)_cxxflags=-std=c++17 endef define $(package)_preprocess_cmds diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index a5c90cece..ead894626 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -1,13 +1,14 @@ package=boost -$(package)_version=1_70_0 -$(package)_download_path=https://dl.bintray.com/boostorg/release/1.70.0/source +$(package)_version=1_74_0 +$(package)_download_path=https://dl.bintray.com/boostorg/release/1.74.0/source $(package)_file_name=$(package)_$($(package)_version).tar.bz2 -$(package)_sha256_hash=430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778 +$(package)_sha256_hash=83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1 +$(package)_patches=signals2-noise.patch define $(package)_set_vars $(package)_config_opts_release=variant=release $(package)_config_opts_debug=variant=debug -$(package)_config_opts=--layout=system --user-config=user-config.jam +$(package)_config_opts=--layout=system $(package)_config_opts+=threading=multi link=static -sNO_BZIP2=1 -sNO_ZLIB=1 $(package)_config_opts_linux=threadapi=pthread runtime-link=shared $(package)_config_opts_darwin=--toolset=darwin-4.2.1 runtime-link=shared @@ -20,16 +21,18 @@ $(package)_archiver_$(host_os)=$($(package)_ar) $(package)_toolset_darwin=darwin $(package)_archiver_darwin=$($(package)_libtool) $(package)_config_libraries=chrono,filesystem,program_options,system,thread,test -$(package)_cxxflags=-std=c++11 -fvisibility=hidden +$(package)_cxxflags=-std=c++17 -fvisibility=hidden $(package)_cxxflags_linux=-fPIC +$(package)_cxxflags_freebsd=-fPIC endef define $(package)_preprocess_cmds - echo "using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : \"$($(package)_cxxflags) $($(package)_cppflags)\" \"$($(package)_ldflags)\" \"$(boost_archiver_$(host_os))\" \"$(host_STRIP)\" \"$(host_RANLIB)\" \"$(host_WINDRES)\" : ;" > user-config.jam + patch -p2 < $($(package)_patch_dir)/signals2-noise.patch endef define $(package)_config_cmds - ./bootstrap.sh --without-icu --with-libraries=$(boost_config_libraries) + ./bootstrap.sh --without-icu --with-libraries=$($(package)_config_libraries) && \ + sed -i -e "s|using gcc ;|using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : \"$($(package)_cxxflags) $($(package)_cppflags)\" \"$($(package)_ldflags)\" \"$(boost_archiver_$(host_os))\" \"$(host_STRIP)\" \"$(host_RANLIB)\" \"$(host_WINDRES)\" : ;|" project-config.jam endef define $(package)_build_cmds diff --git a/depends/packages/googletest.mk b/depends/packages/googletest.mk index ad42d5b9c..98ef97842 100644 --- a/depends/packages/googletest.mk +++ b/depends/packages/googletest.mk @@ -6,13 +6,14 @@ $(package)_download_file=release-$($(package)_version).tar.gz $(package)_sha256_hash=58a6f4277ca2bc8565222b3bbd58a177609e9c488e8a72649359ba51450db7d8 define $(package)_set_vars -$(package)_cxxflags+=-std=c++11 +$(package)_cxxflags+=-std=c++17 $(package)_cxxflags_linux=-fPIC +$(package)_cxxflags_freebsd=-fPIC endef define $(package)_build_cmds $(MAKE) -C googlemock/make CC="$($(package)_cc)" CXX="$($(package)_cxx)" AR="$($(package)_ar)" CXXFLAGS="$($(package)_cxxflags)" gmock.a && \ - $(MAKE) -C googletest/make CC="$($(package)_cc)" CXX="$($(package)_cxx)" AR="$($(package)_ar)" CXXFLAGS="$($(package)_cxxflags)" gtest.a + $($(package)_build_env) $(MAKE) -C googletest/make CC="$($(package)_cc)" CXX="$($(package)_cxx)" AR="$($(package)_ar)" CXXFLAGS="$($(package)_cxxflags)" gtest.a endef define $(package)_stage_cmds diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk index 2a1125fda..7119176f2 100644 --- a/depends/packages/libevent.mk +++ b/depends/packages/libevent.mk @@ -4,8 +4,11 @@ $(package)_download_path=https://github.com/libevent/libevent/archive/ $(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_download_file=release-$($(package)_version)-stable.tar.gz $(package)_sha256_hash=316ddb401745ac5d222d7c529ef1eada12f58f6376a66c1118eee803cb70f83d +$(package)_patches=detect-arch4random_addrandom.patch detect-arch4random_addrandom-fix.patch define $(package)_preprocess_cmds + patch -p1 <$($(package)_patch_dir)/detect-arch4random_addrandom.patch && \ + patch -p1 <$($(package)_patch_dir)/detect-arch4random_addrandom-fix.patch && \ ./autogen.sh endef @@ -13,6 +16,7 @@ define $(package)_set_vars $(package)_config_opts=--disable-shared --disable-openssl --disable-libevent-regress $(package)_config_opts_release=--disable-debug-mode $(package)_config_opts_linux=--with-pic + $(package)_config_opts_freebsd=--with-pic endef define $(package)_config_cmds diff --git a/depends/packages/libgmp.mk b/depends/packages/libgmp.mk deleted file mode 100644 index c43b99bd7..000000000 --- a/depends/packages/libgmp.mk +++ /dev/null @@ -1,20 +0,0 @@ -package=libgmp -$(package)_download_path=https://github.com/z-classic/$(package)/archive/ -$(package)_file_name=$(package)-$($(package)_git_commit).tar.gz -$(package)_download_file=$($(package)_git_commit).tar.gz -$(package)_sha256_hash=59b2c2b5d58fdf5943bfde1fa709e9eb53e7e072c9699d28dc1c2cbb3c8cc32c -$(package)_git_commit=aece03c7b6967f91f3efdac8c673f55adff53ab1 -$(package)_dependencies= -$(package)_config_opts=--enable-cxx --disable-shared - -define $(package)_config_cmds - $($(package)_autoconf) --host=$(host) --build=$(build) -endef - -define $(package)_build_cmds - $(MAKE) CPPFLAGS='-fPIC' -endef - -define $(package)_stage_cmds - $(MAKE) DESTDIR=$($(package)_staging_dir) install ; echo '=== staging find for $(package):' ; find $($(package)_staging_dir) -endef diff --git a/depends/packages/librustzcash.mk b/depends/packages/librustzcash.mk index 9bc8ee543..8dee7b9a6 100644 --- a/depends/packages/librustzcash.mk +++ b/depends/packages/librustzcash.mk @@ -5,8 +5,11 @@ $(package)_file_name=$(package)-$($(package)_git_commit).tar.gz $(package)_download_file=$($(package)_git_commit).tar.gz $(package)_sha256_hash=9909ec59fa7a411c2071d6237b3363a0bc6e5e42358505cf64b7da0f58a7ff5a $(package)_git_commit=06da3b9ac8f278e5d4ae13088cf0a4c03d2c13f5 -$(package)_dependencies=rust $(rust_crates) +$(package)_dependencies=rust +ifeq ($(LIBRUSTZCASH_OVERRIDE),) +$(package)_dependencies+=$(rust_crates) $(package)_patches=cargo.config 0001-Start-using-cargo-clippy-for-CI.patch remove-dev-dependencies.diff +endif $(package)_rust_target=$(if $(rust_rust_target_$(canonical_host)),$(rust_rust_target_$(canonical_host)),$(canonical_host)) @@ -19,12 +22,37 @@ $(package)_library_file=target/release/librustzcash.a endif define $(package)_set_vars -$(package)_build_opts=--frozen --release +$(package)_build_opts=--release +ifeq ($(LIBRUSTZCASH_OVERRIDE),) +$(package)_build_opts+=--frozen +endif ifneq ($(canonical_host),$(build)) $(package)_build_opts+=--target=$($(package)_rust_target) endif endef +ifneq ($(LIBRUSTZCASH_OVERRIDE),) + +define $(package)_fetch_cmds +endef + +define $(package)_extract_cmds +endef + +define $(package)_build_cmds + cd $(LIBRUSTZCASH_OVERRIDE) && \ + $(host_prefix)/native/bin/cargo build --package librustzcash $($(package)_build_opts) +endef + +define $(package)_stage_cmds + mkdir $($(package)_staging_dir)$(host_prefix)/lib/ && \ + mkdir $($(package)_staging_dir)$(host_prefix)/include/ && \ + cp $(LIBRUSTZCASH_OVERRIDE)/$($(package)_library_file) $($(package)_staging_dir)$(host_prefix)/lib/ && \ + cp $(LIBRUSTZCASH_OVERRIDE)/librustzcash/include/librustzcash.h $($(package)_staging_dir)$(host_prefix)/include/ +endef + +else + define $(package)_preprocess_cmds patch -p1 -d pairing < $($(package)_patch_dir)/0001-Start-using-cargo-clippy-for-CI.patch && \ patch -p1 < $($(package)_patch_dir)/remove-dev-dependencies.diff && \ @@ -42,3 +70,5 @@ define $(package)_stage_cmds cp $($(package)_library_file) $($(package)_staging_dir)$(host_prefix)/lib/ && \ cp librustzcash/include/librustzcash.h $($(package)_staging_dir)$(host_prefix)/include/ endef + +endif diff --git a/depends/packages/libsodium.mk b/depends/packages/libsodium.mk index a494f125a..7b5da8b11 100644 --- a/depends/packages/libsodium.mk +++ b/depends/packages/libsodium.mk @@ -1,12 +1,15 @@ package=libsodium -$(package)_version=1.0.15 -$(package)_download_path=https://download.libsodium.org/libsodium/releases/old/ +$(package)_version=1.0.18 +$(package)_download_path=https://download.libsodium.org/libsodium/releases/ $(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=fb6a9e879a2f674592e4328c5d9f79f082405ee4bb05cb6e679b90afe9e178f4 +$(package)_sha256_hash=6f504490b342a4f8a4c4a02fc9b866cbef8622d5df4e5452b46be121e46636c1 $(package)_dependencies= +$(package)_patches=1.0.15-pubkey-validation.diff 1.0.15-signature-validation.diff $(package)_config_opts= define $(package)_preprocess_cmds + patch -p1 < $($(package)_patch_dir)/1.0.15-pubkey-validation.diff && \ + patch -p1 < $($(package)_patch_dir)/1.0.15-signature-validation.diff && \ cd $($(package)_build_subdir); ./autogen.sh endef diff --git a/depends/packages/native_ccache.mk b/depends/packages/native_ccache.mk index b63c18b90..4c5dde76d 100644 --- a/depends/packages/native_ccache.mk +++ b/depends/packages/native_ccache.mk @@ -1,8 +1,8 @@ package=native_ccache -$(package)_version=3.3.1 -$(package)_download_path=https://www.samba.org/ftp/ccache -$(package)_file_name=ccache-$($(package)_version).tar.bz2 -$(package)_sha256_hash=cb6e4bafbb19ba0a2ec43386b123a5f92a20e1e3384c071d5d13e0cb3c84bf73 +$(package)_version=3.7.12 +$(package)_download_path=https://github.com/ccache/ccache/releases/download/v$($(package)_version) +$(package)_file_name=ccache-$($(package)_version).tar.gz +$(package)_sha256_hash=d2abe88d4c283ce960e233583061127b156ffb027c6da3cf10770fc0c7244194 define $(package)_set_vars $(package)_config_opts= diff --git a/depends/packages/native_cctools.mk b/depends/packages/native_cctools.mk new file mode 100644 index 000000000..a065256c1 --- /dev/null +++ b/depends/packages/native_cctools.mk @@ -0,0 +1,65 @@ +package=native_cctools +$(package)_version=807d6fd1be5d2224872e381870c0a75387fe05e6 +$(package)_download_path=https://github.com/theuni/cctools-port/archive +$(package)_file_name=$($(package)_version).tar.gz +$(package)_sha256_hash=a09c9ba4684670a0375e42d9d67e7f12c1f62581a27f28f7c825d6d7032ccc6a +$(package)_build_subdir=cctools +$(package)_clang_version=3.7.1 +$(package)_clang_download_path=https://llvm.org/releases/$($(package)_clang_version) +$(package)_clang_download_file=clang+llvm-$($(package)_clang_version)-x86_64-linux-gnu-ubuntu-14.04.tar.xz +$(package)_clang_file_name=clang-llvm-$($(package)_clang_version)-x86_64-linux-gnu-ubuntu-14.04.tar.xz +$(package)_clang_sha256_hash=99b28a6b48e793705228a390471991386daa33a9717cd9ca007fcdde69608fd9 +$(package)_extra_sources=$($(package)_clang_file_name) + +define $(package)_fetch_cmds +$(call fetch_file,$(package),$($(package)_download_path),$($(package)_download_file),$($(package)_file_name),$($(package)_sha256_hash)) && \ +$(call fetch_file,$(package),$($(package)_clang_download_path),$($(package)_clang_download_file),$($(package)_clang_file_name),$($(package)_clang_sha256_hash)) +endef + +define $(package)_extract_cmds + mkdir -p $($(package)_extract_dir) && \ + echo "$($(package)_sha256_hash) $($(package)_source)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \ + echo "$($(package)_clang_sha256_hash) $($(package)_source_dir)/$($(package)_clang_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \ + $(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \ + mkdir -p toolchain/bin toolchain/lib/clang/3.5/include && \ + tar --no-same-owner --strip-components=1 -C toolchain -xf $($(package)_source_dir)/$($(package)_clang_file_name) && \ + rm -f toolchain/lib/libc++abi.so* && \ + echo "#!/bin/sh" > toolchain/bin/$(host)-dsymutil && \ + echo "exit 0" >> toolchain/bin/$(host)-dsymutil && \ + chmod +x toolchain/bin/$(host)-dsymutil && \ + tar --no-same-owner --strip-components=1 -xf $($(package)_source) +endef + +define $(package)_set_vars +$(package)_config_opts=--target=$(host) --disable-lto-support +$(package)_ldflags+=-Wl,-rpath=\\$$$$$$$$\$$$$$$$$ORIGIN/../lib +$(package)_cc=$($(package)_extract_dir)/toolchain/bin/clang +$(package)_cxx=$($(package)_extract_dir)/toolchain/bin/clang++ +endef + +define $(package)_preprocess_cmds + cd $($(package)_build_subdir); ./autogen.sh && \ + sed -i.old "/define HAVE_PTHREADS/d" ld64/src/ld/InputFiles.h +endef + +define $(package)_config_cmds + $($(package)_autoconf) +endef + +define $(package)_build_cmds + $(MAKE) +endef + +define $(package)_stage_cmds + $(MAKE) DESTDIR=$($(package)_staging_dir) install && \ + cd $($(package)_extract_dir)/toolchain && \ + mkdir -p $($(package)_staging_prefix_dir)/lib/clang/$($(package)_clang_version)/include && \ + mkdir -p $($(package)_staging_prefix_dir)/bin $($(package)_staging_prefix_dir)/include && \ + cp bin/clang $($(package)_staging_prefix_dir)/bin/ &&\ + cp -P bin/clang++ $($(package)_staging_prefix_dir)/bin/ &&\ + cp lib/libLTO.so $($(package)_staging_prefix_dir)/lib/ && \ + cp -rf lib/clang/$($(package)_clang_version)/include/* $($(package)_staging_prefix_dir)/lib/clang/$($(package)_clang_version)/include/ && \ + cp bin/llvm-dsymutil $($(package)_staging_prefix_dir)/bin/$(host)-dsymutil && \ + if `test -d include/c++/`; then cp -rf include/c++/ $($(package)_staging_prefix_dir)/include/; fi && \ + if `test -d lib/c++/`; then cp -rf lib/c++/ $($(package)_staging_prefix_dir)/lib/; fi +endef diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk deleted file mode 100644 index a1d5439aa..000000000 --- a/depends/packages/openssl.mk +++ /dev/null @@ -1,113 +0,0 @@ -package=openssl -$(package)_version=1.1.1a -$(package)_download_path=https://www.openssl.org/source -$(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=fc20130f8b7cbd2fb918b2f14e2f429e109c31ddd0fb38fc5d71d9ffed3f9f41 - -define $(package)_set_vars -$(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)" -$(package)_config_opts=--prefix=$(host_prefix) --openssldir=$(host_prefix)/etc/openssl -$(package)_config_opts+=no-afalgeng -$(package)_config_opts+=no-asm -$(package)_config_opts+=no-async -$(package)_config_opts+=no-bf -$(package)_config_opts+=no-blake2 -$(package)_config_opts+=no-camellia -$(package)_config_opts+=no-capieng -$(package)_config_opts+=no-cast -$(package)_config_opts+=no-chacha -$(package)_config_opts+=no-cmac -$(package)_config_opts+=no-cms -$(package)_config_opts+=no-comp -$(package)_config_opts+=no-crypto-mdebug -$(package)_config_opts+=no-crypto-mdebug-backtrace -$(package)_config_opts+=no-ct -$(package)_config_opts+=no-des -$(package)_config_opts+=no-dgram -$(package)_config_opts+=no-dsa -$(package)_config_opts+=no-dso -$(package)_config_opts+=no-dtls -$(package)_config_opts+=no-dtls1 -$(package)_config_opts+=no-dtls1-method -$(package)_config_opts+=no-dynamic-engine -$(package)_config_opts+=no-ec2m -$(package)_config_opts+=no-ec_nistp_64_gcc_128 -$(package)_config_opts+=no-egd -$(package)_config_opts+=no-engine -$(package)_config_opts+=no-err -$(package)_config_opts+=no-gost -$(package)_config_opts+=no-heartbeats -$(package)_config_opts+=no-idea -$(package)_config_opts+=no-md2 -$(package)_config_opts+=no-md4 -$(package)_config_opts+=no-mdc2 -$(package)_config_opts+=no-multiblock -$(package)_config_opts+=no-nextprotoneg -$(package)_config_opts+=no-ocb -$(package)_config_opts+=no-ocsp -$(package)_config_opts+=no-poly1305 -$(package)_config_opts+=no-posix-io -$(package)_config_opts+=no-psk -$(package)_config_opts+=no-rc2 -$(package)_config_opts+=no-rc4 -$(package)_config_opts+=no-rc5 -$(package)_config_opts+=no-rdrand -$(package)_config_opts+=no-rfc3779 -$(package)_config_opts+=no-rmd160 -$(package)_config_opts+=no-scrypt -$(package)_config_opts+=no-sctp -$(package)_config_opts+=no-seed -$(package)_config_opts+=no-shared -$(package)_config_opts+=no-sock -$(package)_config_opts+=no-srp -$(package)_config_opts+=no-srtp -$(package)_config_opts+=no-ssl -$(package)_config_opts+=no-ssl3 -$(package)_config_opts+=no-ssl3-method -$(package)_config_opts+=no-ssl-trace -$(package)_config_opts+=no-stdio -$(package)_config_opts+=no-tls -$(package)_config_opts+=no-tls1 -$(package)_config_opts+=no-tls1-method -$(package)_config_opts+=no-ts -$(package)_config_opts+=no-ui -$(package)_config_opts+=no-unit-test -$(package)_config_opts+=no-weak-ssl-ciphers -$(package)_config_opts+=no-whirlpool -$(package)_config_opts+=no-zlib -$(package)_config_opts+=no-zlib-dynamic -$(package)_config_opts+=$($(package)_cflags) $($(package)_cppflags) -$(package)_config_opts+=-DPURIFY -$(package)_config_opts_linux=-fPIC -Wa,--noexecstack -$(package)_config_opts_x86_64_linux=linux-x86_64 -$(package)_config_opts_i686_linux=linux-generic32 -$(package)_config_opts_arm_linux=linux-generic32 -$(package)_config_opts_aarch64_linux=linux-generic64 -$(package)_config_opts_mipsel_linux=linux-generic32 -$(package)_config_opts_mips_linux=linux-generic32 -$(package)_config_opts_powerpc_linux=linux-generic32 -$(package)_config_opts_x86_64_darwin=darwin64-x86_64-cc -$(package)_config_opts_x86_64_mingw32=mingw64 -$(package)_config_opts_i686_mingw32=mingw -endef - -define $(package)_preprocess_cmds - sed -i.old 's/built on: $$$$date/built on: date not available/' util/mkbuildinf.pl && \ - sed -i.old "s|\"engines\", \"apps\", \"test\"|\"engines\"|" Configure -endef - -define $(package)_config_cmds - ./Configure $($(package)_config_opts) -endef - -define $(package)_build_cmds - $(MAKE) -j1 build_libs libcrypto.pc libssl.pc openssl.pc -endef - -define $(package)_stage_cmds - $(MAKE) DESTDIR=$($(package)_staging_dir) -j1 install_sw -endef - -define $(package)_postprocess_cmds - rm -rf share bin etc -endef diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 91f7b9934..fac5f4938 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -34,8 +34,12 @@ rust_crates := \ crate_winapi_x86_64_pc_windows_gnu rust_packages := rust $(rust_crates) librustzcash proton_packages := proton -zcash_packages := libgmp libsodium utfcpp -packages := boost openssl libevent zeromq $(zcash_packages) googletest +zcash_packages := libsodium utfcpp +packages := boost libevent zeromq $(zcash_packages) googletest native_packages := native_ccache wallet_packages=bdb + +ifneq ($(build_os),darwin) +darwin_native_packages=native_cctools +endif diff --git a/depends/packages/proton.mk b/depends/packages/proton.mk index 3440f184e..d974fa5fa 100644 --- a/depends/packages/proton.mk +++ b/depends/packages/proton.mk @@ -1,8 +1,8 @@ package=proton -$(package)_version=0.26.0 +$(package)_version=0.30.0 $(package)_download_path=https://archive.apache.org/dist/qpid/proton/$($(package)_version) $(package)_file_name=qpid-proton-$($(package)_version).tar.gz -$(package)_sha256_hash=0eddac870f0085b9aeb0c9da333bd3f53fedb7c872164171a7cc06761ddbbd75 +$(package)_sha256_hash=e37fd8fb13391c3996f927839969a8f66edf35612392d0611eeac6e39e48dd33 $(package)_patches=minimal-build.patch define $(package)_preprocess_cmds diff --git a/depends/packages/rust.mk b/depends/packages/rust.mk index b892d8b72..0eb51eef7 100644 --- a/depends/packages/rust.mk +++ b/depends/packages/rust.mk @@ -5,13 +5,17 @@ $(package)_file_name_linux=rust-$($(package)_version)-x86_64-unknown-linux-gnu.t $(package)_sha256_hash_linux=e024698320d76b74daf0e6e71be3681a1e7923122e3ebd03673fcac3ecc23810 $(package)_file_name_darwin=rust-$($(package)_version)-x86_64-apple-darwin.tar.gz $(package)_sha256_hash_darwin=f0dfba507192f9b5c330b5984ba71d57d434475f3d62bd44a39201e36fa76304 +$(package)_file_name_freebsd=rust-$($(package)_version)-x86_64-unknown-freebsd.tar.gz +$(package)_sha256_hash_freebsd=20d062493d01f1816014fe9dbe883bda06f1828a6ddbfb7ee5e4f1df20eb1c3a # Mapping from GCC canonical hosts to Rust targets # If a mapping is not present, we assume they are identical +$(package)_rust_target_x86_64-apple-darwin11=x86_64-apple-darwin $(package)_rust_target_x86_64-w64-mingw32=x86_64-pc-windows-gnu # Mapping from Rust targets to SHA-256 hashes $(package)_rust_std_sha256_hash_aarch64-unknown-linux-gnu=346efe3aef2aff7b71a611bf7661bcec5f9bc4025a599c2866ec5fd330247cb9 +$(package)_rust_std_sha256_hash_x86_64-apple-darwin=7c6806809e010e5fba1780007ecff5c31f0ad2fcac1b414b98ca3baa0fb41b36 $(package)_rust_std_sha256_hash_x86_64-pc-windows-gnu=cad5f1454d591c13eeb3657f1c9dbfeb30e648f59680bd0765b94c63e7afc49e ifneq ($(canonical_host),$(build)) @@ -38,12 +42,12 @@ define $(package)_extract_cmds endef define $(package)_stage_cmds - ./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig && \ + bash ./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig && \ ../$(canonical_host)/install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig endef else define $(package)_stage_cmds - ./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig + bash ./install.sh --destdir=$($(package)_staging_dir) --prefix=$(host_prefix)/native --disable-ldconfig endef endif diff --git a/depends/packages/vendorcrate.mk b/depends/packages/vendorcrate.mk new file mode 100644 index 000000000..728eb71b5 --- /dev/null +++ b/depends/packages/vendorcrate.mk @@ -0,0 +1,15 @@ +package=crate_CRATEFILE +$(package)_crate_name=CRATENAME +$(package)_version=CRATEVER +$(package)_download_path=https://static.crates.io/crates/$($(package)_crate_name) +$(package)_file_name=$($(package)_crate_name)-$($(package)_version).crate +$(package)_sha256_hash=CRATEHASH +$(package)_crate_versioned_name=$($(package)_crate_name) + +define $(package)_preprocess_cmds + $(call generate_crate_checksum,$(package)) +endef + +define $(package)_stage_cmds + $(call vendor_crate_source,$(package)) +endef diff --git a/depends/packages/vendorcrate.sh b/depends/packages/vendorcrate.sh new file mode 100644 index 000000000..b76521ae4 --- /dev/null +++ b/depends/packages/vendorcrate.sh @@ -0,0 +1,12 @@ +pkgdir=$(dirname $0) + +cratefile=$(echo "$1" | tr '-' '_') +cratename=$1 +cratever=$2 +cratehash=$(curl "https://static.crates.io/crates/$cratename/$cratename-$cratever.crate" | sha256sum | awk '{print $1}') + +cat "$pkgdir/vendorcrate.mk" | +sed "s/CRATEFILE/$cratefile/g" | +sed "s/CRATENAME/$cratename/g" | +sed "s/CRATEVER/$cratever/g" | +sed "s/CRATEHASH/$cratehash/g" > "$pkgdir/crate_$cratefile.mk" diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk index 79373f09a..af4243162 100644 --- a/depends/packages/zeromq.mk +++ b/depends/packages/zeromq.mk @@ -7,7 +7,8 @@ $(package)_sha256_hash=bcbabe1e2c7d0eec4ed612e10b94b112dd5f06fcefa994a0c79a45d83 define $(package)_set_vars $(package)_config_opts=--without-documentation --disable-shared --disable-curve $(package)_config_opts_linux=--with-pic - $(package)_cxxflags=-std=c++11 + $(package)_config_opts_freebsd=--with-pic + $(package)_cxxflags=-std=c++17 endef define $(package)_config_cmds diff --git a/depends/patches/boost/signals2-noise.patch b/depends/patches/boost/signals2-noise.patch new file mode 100644 index 000000000..51d71516e --- /dev/null +++ b/depends/patches/boost/signals2-noise.patch @@ -0,0 +1,23 @@ +From fd27423fea5537bc857c1fa14bb0c25b994f77b3 Mon Sep 17 00:00:00 2001 +From: Frank Mori Hess +Date: Mon, 20 Jul 2020 14:17:05 -0400 +Subject: [PATCH] Fix warning about deprecated + boost/function_output_iterator.hpp + +--- + include/boost/signals2/detail/null_output_iterator.hpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/boost/signals2/detail/null_output_iterator.hpp b/include/boost/signals2/detail/null_output_iterator.hpp +index 9e986959..dee4373c 100644 +--- a/include/boost/signals2/detail/null_output_iterator.hpp ++++ b/include/boost/signals2/detail/null_output_iterator.hpp +@@ -11,7 +11,7 @@ + #ifndef BOOST_SIGNALS2_NULL_OUTPUT_ITERATOR_HPP + #define BOOST_SIGNALS2_NULL_OUTPUT_ITERATOR_HPP + +-#include ++#include + + namespace boost + { diff --git a/depends/patches/libevent/detect-arch4random_addrandom-fix.patch b/depends/patches/libevent/detect-arch4random_addrandom-fix.patch new file mode 100644 index 000000000..14ce2edb8 --- /dev/null +++ b/depends/patches/libevent/detect-arch4random_addrandom-fix.patch @@ -0,0 +1,43 @@ +From 266f43af7798befa3d27bfabaa9ae699259c3924 Mon Sep 17 00:00:00 2001 +From: Azat Khuzhin +Date: Mon, 27 Mar 2017 15:50:23 +0300 +Subject: [PATCH] Fix arc4random_addrandom() detecting and fallback + (regression) + +But this is kind of hot-fix, we definitelly need more sane arc4random +compat layer. + +Fixes: #488 +Introduced-in: 6541168 ("Detect arch4random_addrandom() existence") +--- + event-config.h.cmake | 3 +++ + include/event2/util.h | 2 +- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/event-config.h.cmake b/event-config.h.cmake +index b7f0be57c..5c233a3d9 100644 +--- a/event-config.h.cmake ++++ b/event-config.h.cmake +@@ -53,6 +53,9 @@ + /* Define to 1 if you have the `arc4random_buf' function. */ + #cmakedefine EVENT__HAVE_ARC4RANDOM_BUF 1 + ++/* Define to 1 if you have the `arc4random_addrandom' function. */ ++#cmakedefine EVENT__HAVE_ARC4RANDOM_ADDRANDOM 1 ++ + /* Define if clock_gettime is available in libc */ + #cmakedefine EVENT__DNS_USE_CPU_CLOCK_FOR_ID 1 + +diff --git a/include/event2/util.h b/include/event2/util.h +index c4af2bd60..ca4048944 100644 +--- a/include/event2/util.h ++++ b/include/event2/util.h +@@ -842,7 +842,7 @@ int evutil_secure_rng_init(void); + EVENT2_EXPORT_SYMBOL + int evutil_secure_rng_set_urandom_device_file(char *fname); + +-#ifdef EVENT__HAVE_ARC4RANDOM_ADDRANDOM ++#if !defined(EVENT__HAVE_ARC4RANDOM) || defined(EVENT__HAVE_ARC4RANDOM_ADDRANDOM) + /** Seed the random number generator with extra random bytes. + + You should almost never need to call this function; it should be diff --git a/depends/patches/libevent/detect-arch4random_addrandom.patch b/depends/patches/libevent/detect-arch4random_addrandom.patch new file mode 100644 index 000000000..1f480715f --- /dev/null +++ b/depends/patches/libevent/detect-arch4random_addrandom.patch @@ -0,0 +1,77 @@ +From 6541168d7037457b8e5c51cc354f11bd94e618b6 Mon Sep 17 00:00:00 2001 +From: Marek Sebera +Date: Mon, 6 Mar 2017 00:55:16 +0300 +Subject: [PATCH] Detect arch4random_addrandom() existence + +Refs: #370 +Refs: #475 +--- + CMakeLists.txt | 1 + + configure.ac | 1 + + evutil_rand.c | 2 ++ + include/event2/util.h | 2 ++ + 4 files changed, 6 insertions(+) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index a861e7d96..f609d02d0 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -338,6 +338,7 @@ CHECK_FUNCTION_EXISTS_EX(sysctl EVENT__HAVE_SYSCTL) + CHECK_FUNCTION_EXISTS_EX(accept4 EVENT__HAVE_ACCEPT4) + CHECK_FUNCTION_EXISTS_EX(arc4random EVENT__HAVE_ARC4RANDOM) + CHECK_FUNCTION_EXISTS_EX(arc4random_buf EVENT__HAVE_ARC4RANDOM_BUF) ++CHECK_FUNCTION_EXISTS_EX(arc4random_addrandom EVENT__HAVE_ARC4RANDOM_ADDRANDOM) + CHECK_FUNCTION_EXISTS_EX(epoll_create1 EVENT__HAVE_EPOLL_CREATE1) + CHECK_FUNCTION_EXISTS_EX(getegid EVENT__HAVE_GETEGID) + CHECK_FUNCTION_EXISTS_EX(geteuid EVENT__HAVE_GETEUID) +diff --git a/configure.ac b/configure.ac +index a127bbc91..e73c29b14 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -342,6 +342,7 @@ AC_CHECK_FUNCS([ \ + accept4 \ + arc4random \ + arc4random_buf \ ++ arc4random_addrandom \ + eventfd \ + epoll_create1 \ + fcntl \ +diff --git a/evutil_rand.c b/evutil_rand.c +index 046a14b07..4be0b1c5e 100644 +--- a/evutil_rand.c ++++ b/evutil_rand.c +@@ -192,12 +192,14 @@ evutil_secure_rng_get_bytes(void *buf, size_t n) + ev_arc4random_buf(buf, n); + } + ++#if !defined(EVENT__HAVE_ARC4RANDOM) || defined(EVENT__HAVE_ARC4RANDOM_ADDRANDOM) + void + evutil_secure_rng_add_bytes(const char *buf, size_t n) + { + arc4random_addrandom((unsigned char*)buf, + n>(size_t)INT_MAX ? INT_MAX : (int)n); + } ++#endif + + void + evutil_free_secure_rng_globals_(void) +diff --git a/include/event2/util.h b/include/event2/util.h +index dd4bbb69d..c4af2bd60 100644 +--- a/include/event2/util.h ++++ b/include/event2/util.h +@@ -842,6 +842,7 @@ int evutil_secure_rng_init(void); + EVENT2_EXPORT_SYMBOL + int evutil_secure_rng_set_urandom_device_file(char *fname); + ++#ifdef EVENT__HAVE_ARC4RANDOM_ADDRANDOM + /** Seed the random number generator with extra random bytes. + + You should almost never need to call this function; it should be +@@ -858,6 +859,7 @@ int evutil_secure_rng_set_urandom_device_file(char *fname); + */ + EVENT2_EXPORT_SYMBOL + void evutil_secure_rng_add_bytes(const char *dat, size_t datlen); ++#endif + + #ifdef __cplusplus + } diff --git a/depends/patches/libsodium/1.0.15-pubkey-validation.diff b/depends/patches/libsodium/1.0.15-pubkey-validation.diff new file mode 100644 index 000000000..3a9b7ea86 --- /dev/null +++ b/depends/patches/libsodium/1.0.15-pubkey-validation.diff @@ -0,0 +1,17 @@ +diff -ur libsodium-1.0.18-orig/src/libsodium/crypto_sign/ed25519/ref10/open.c libsodium-1.0.18/src/libsodium/crypto_sign/ed25519/ref10/open.c +--- libsodium-1.0.18-orig/src/libsodium/crypto_sign/ed25519/ref10/open.c 2019-05-18 16:32:11.000000000 -0400 ++++ libsodium-1.0.18/src/libsodium/crypto_sign/ed25519/ref10/open.c 2020-01-21 18:55:22.474233831 -0500 +@@ -32,8 +32,11 @@ + ge25519_has_small_order(sig) != 0) { + return -1; + } +- if (ge25519_is_canonical(pk) == 0 || +- ge25519_has_small_order(pk) != 0) { ++ unsigned char d = 0; ++ for (int i = 0; i < 32; ++i) { ++ d |= pk[i]; ++ } ++ if (d == 0) { + return -1; + } + #endif diff --git a/depends/patches/libsodium/1.0.15-signature-validation.diff b/depends/patches/libsodium/1.0.15-signature-validation.diff new file mode 100644 index 000000000..482eb3686 --- /dev/null +++ b/depends/patches/libsodium/1.0.15-signature-validation.diff @@ -0,0 +1,78 @@ +diff -ur libsodium-1.0.18-orig/src/libsodium/crypto_sign/ed25519/ref10/open.c libsodium-1.0.18/src/libsodium/crypto_sign/ed25519/ref10/open.c +--- libsodium-1.0.18-orig/src/libsodium/crypto_sign/ed25519/ref10/open.c 2019-05-18 21:32:11.000000000 +0100 ++++ libsodium-1.0.18/src/libsodium/crypto_sign/ed25519/ref10/open.c 2020-02-18 00:00:08.544107613 +0000 +@@ -10,6 +10,65 @@ + #include "private/ed25519_ref10.h" + #include "utils.h" + ++#ifndef ED25519_COMPAT ++int ++_crypto_sign_ed25519_small_order(const unsigned char p[32]) ++{ ++ CRYPTO_ALIGN(16) ++ static const unsigned char blacklist[][32] = { ++ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, ++ { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, ++ { 0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, ++ 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, ++ 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05 }, ++ { 0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, ++ 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, ++ 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a }, ++ { 0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, ++ 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, ++ 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85 }, ++ { 0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, ++ 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, ++ 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa }, ++ { 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, ++ { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, ++ { 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, ++ { 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, ++ { 0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, ++ { 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } ++ }; ++ size_t i, j; ++ unsigned char c; ++ ++ for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) { ++ c = 0; ++ for (j = 0; j < 32; j++) { ++ c |= p[j] ^ blacklist[i][j]; ++ } ++ if (c == 0) { ++ return 1; ++ } ++ } ++ return 0; ++} ++#endif ++ + int + _crypto_sign_ed25519_verify_detached(const unsigned char *sig, + const unsigned char *m, +@@ -29,7 +88,7 @@ + } + #else + if (sc25519_is_canonical(sig + 32) == 0 || +- ge25519_has_small_order(sig) != 0) { ++ _crypto_sign_ed25519_small_order(sig) != 0) { + return -1; + } + if (ge25519_is_canonical(pk) == 0 || diff --git a/depends/patches/proton/minimal-build.patch b/depends/patches/proton/minimal-build.patch index a9b47ff35..1c0c972b6 100644 --- a/depends/patches/proton/minimal-build.patch +++ b/depends/patches/proton/minimal-build.patch @@ -1,12 +1,15 @@ -diff -ur qpid-proton-0.26.0/c/CMakeLists.txt qpid-proton-patched/c/CMakeLists.txt ---- qpid-proton-0.26.0/c/CMakeLists.txt 2018-10-04 04:09:02.000000000 -0600 -+++ qpid-proton-patched/c/CMakeLists.txt 2019-03-25 17:32:41.521213312 -0600 -@@ -443,15 +443,15 @@ - ${qpid-proton-include-generated} - ) - --add_library (qpid-proton-core SHARED ${qpid-proton-core-src}) --add_dependencies (qpid-proton-core generated_c_files) +diff -ur a/c/CMakeLists.txt b/c/CMakeLists.txt +--- a/c/CMakeLists.txt 2019-12-09 07:17:00.000000000 -0700 ++++ b/c/CMakeLists.txt 2020-01-08 16:15:26.837987469 -0700 +@@ -428,18 +428,18 @@ + # Can't use target_link_libraries() because cmake 2.8.12 doesn't allow object libraries as the first param + # otherwise for cmake 3.9 and on this would be: + # target_link_libraries (qpid-proton-core-objects ${SSL_LIB} ${SASL_LIB} ${TIME_LIB} ${PLATFORM_LIBS}) +-target_compile_definitions(qpid-proton-core-objects PRIVATE $) +-target_compile_options (qpid-proton-core-objects PRIVATE $) +-target_include_directories(qpid-proton-core-objects PRIVATE $) +- +-add_library (qpid-proton-core SHARED $) -target_link_libraries (qpid-proton-core ${SSL_LIB} ${SASL_LIB} ${TIME_LIB} ${PLATFORM_LIBS}) -set_target_properties (qpid-proton-core - PROPERTIES @@ -14,8 +17,11 @@ diff -ur qpid-proton-0.26.0/c/CMakeLists.txt qpid-proton-patched/c/CMakeLists.tx - SOVERSION "${PN_LIB_CORE_MAJOR_VERSION}" - LINK_FLAGS "${CATCH_UNDEFINED} ${LTO}" -) -+#add_library (qpid-proton-core SHARED ${qpid-proton-core-src}) -+#add_dependencies (qpid-proton-core generated_c_files) ++#target_compile_definitions(qpid-proton-core-objects PRIVATE $) ++#target_compile_options (qpid-proton-core-objects PRIVATE $) ++#target_include_directories(qpid-proton-core-objects PRIVATE $) ++ ++#add_library (qpid-proton-core SHARED $) +#target_link_libraries (qpid-proton-core ${SSL_LIB} ${SASL_LIB} ${TIME_LIB} ${PLATFORM_LIBS}) +#set_target_properties (qpid-proton-core +# PROPERTIES @@ -23,14 +29,14 @@ diff -ur qpid-proton-0.26.0/c/CMakeLists.txt qpid-proton-patched/c/CMakeLists.tx +# SOVERSION "${PN_LIB_CORE_MAJOR_VERSION}" +# LINK_FLAGS "${CATCH_UNDEFINED} ${LTO}" +#) - + if (BUILD_STATIC_LIBS) add_library (qpid-proton-core-static STATIC ${qpid-proton-core-src}) -@@ -472,14 +472,14 @@ +@@ -454,14 +454,14 @@ ${qpid-proton-include-extra} ) - --add_library (qpid-proton SHARED ${qpid-proton-src}) + +-add_library (qpid-proton SHARED $ ${qpid-proton-noncore-src}) -target_link_libraries (qpid-proton LINK_PRIVATE ${SSL_LIB} ${SASL_LIB} ${TIME_LIB} ${PLATFORM_LIBS} ${PROACTOR_LIBS}) -set_target_properties (qpid-proton - PROPERTIES @@ -38,19 +44,19 @@ diff -ur qpid-proton-0.26.0/c/CMakeLists.txt qpid-proton-patched/c/CMakeLists.tx - SOVERSION "${PN_LIB_LEGACY_MAJOR_VERSION}" - LINK_FLAGS "${CATCH_UNDEFINED} ${LTO}" -) -+#add_library (qpid-proton SHARED ${qpid-proton-src}) -+#target_link_libraries (qpid-proton LINK_PRIVATE ${SSL_LIB} ${SASL_LIB} ${TIME_LIB} ${PLATFORM_LIBS} ${PROACTOR_LIBS}) -+#set_target_properties (qpid-proton -+# PROPERTIES -+# VERSION "${PN_LIB_LEGACY_VERSION}" -+# SOVERSION "${PN_LIB_LEGACY_MAJOR_VERSION}" -+# LINK_FLAGS "${CATCH_UNDEFINED} ${LTO}" -+#) - ++# add_library (qpid-proton SHARED $ ${qpid-proton-noncore-src}) ++# target_link_libraries (qpid-proton LINK_PRIVATE ${SSL_LIB} ${SASL_LIB} ${TIME_LIB} ${PLATFORM_LIBS} ${PROACTOR_LIBS}) ++# set_target_properties (qpid-proton ++# PROPERTIES ++# VERSION "${PN_LIB_LEGACY_VERSION}" ++# SOVERSION "${PN_LIB_LEGACY_MAJOR_VERSION}" ++# LINK_FLAGS "${CATCH_UNDEFINED} ${LTO}" ++# ) + if (BUILD_STATIC_LIBS) - add_library(qpid-proton-static STATIC ${qpid-proton-src}) -@@ -500,15 +500,15 @@ - + add_library(qpid-proton-static STATIC ${qpid-proton-core-src} ${qpid-proton-noncore-src}) +@@ -482,15 +482,15 @@ + if (qpid-proton-proactor) set(HAS_PROACTOR True) - add_library (qpid-proton-proactor SHARED ${qpid-proton-proactor}) @@ -62,28 +68,36 @@ diff -ur qpid-proton-0.26.0/c/CMakeLists.txt qpid-proton-patched/c/CMakeLists.tx - SOVERSION "${PN_LIB_PROACTOR_MAJOR_VERSION}" - LINK_FLAGS "${CATCH_UNDEFINED} ${LTO}" - ) -+ #add_library (qpid-proton-proactor SHARED ${qpid-proton-proactor}) -+ #target_link_libraries (qpid-proton-proactor LINK_PUBLIC qpid-proton-core) -+ #target_link_libraries (qpid-proton-proactor LINK_PRIVATE ${PLATFORM_LIBS} ${PROACTOR_LIBS}) -+ #set_target_properties (qpid-proton-proactor -+ # PROPERTIES -+ # VERSION "${PN_LIB_PROACTOR_VERSION}" -+ # SOVERSION "${PN_LIB_PROACTOR_MAJOR_VERSION}" -+ # LINK_FLAGS "${CATCH_UNDEFINED} ${LTO}" -+ #) ++ # add_library (qpid-proton-proactor SHARED ${qpid-proton-proactor}) ++ # target_link_libraries (qpid-proton-proactor LINK_PUBLIC qpid-proton-core) ++ # target_link_libraries (qpid-proton-proactor LINK_PRIVATE ${PLATFORM_LIBS} ${PROACTOR_LIBS}) ++ # set_target_properties (qpid-proton-proactor ++ # PROPERTIES ++ # VERSION "${PN_LIB_PROACTOR_VERSION}" ++ # SOVERSION "${PN_LIB_PROACTOR_MAJOR_VERSION}" ++ # LINK_FLAGS "${CATCH_UNDEFINED} ${LTO}" ++ # ) if (BUILD_STATIC_LIBS) add_library (qpid-proton-proactor-static STATIC ${qpid-proton-proactor}) endif(BUILD_STATIC_LIBS) -@@ -518,7 +518,7 @@ +@@ -500,11 +500,11 @@ if (BUILD_STATIC_LIBS) set(STATIC_LIBS qpid-proton-static qpid-proton-core-static) endif() -install(TARGETS qpid-proton qpid-proton-core ${STATIC_LIBS} -+install(TARGETS ${STATIC_LIBS} - EXPORT proton - RUNTIME DESTINATION bin - ARCHIVE DESTINATION ${LIB_INSTALL_DIR} -@@ -538,11 +538,11 @@ +- EXPORT proton +- RUNTIME DESTINATION bin +- ARCHIVE DESTINATION ${LIB_INSTALL_DIR} +- LIBRARY DESTINATION ${LIB_INSTALL_DIR}) ++# install(TARGETS qpid-proton qpid-proton-core ${STATIC_LIBS} ++# EXPORT proton ++# RUNTIME DESTINATION bin ++# ARCHIVE DESTINATION ${LIB_INSTALL_DIR} ++# LIBRARY DESTINATION ${LIB_INSTALL_DIR}) + + # Install windows pdb files + if (MSVC) +@@ -520,11 +520,11 @@ if (BUILD_STATIC_LIBS) set(STATIC_LIBS qpid-proton-proactor-static) endif() @@ -92,95 +106,93 @@ diff -ur qpid-proton-0.26.0/c/CMakeLists.txt qpid-proton-patched/c/CMakeLists.tx - RUNTIME DESTINATION bin - ARCHIVE DESTINATION ${LIB_INSTALL_DIR} - LIBRARY DESTINATION ${LIB_INSTALL_DIR}) -+ #install(TARGETS qpid-proton-proactor ${STATIC_LIBS} -+ # EXPORT proton -+ # RUNTIME DESTINATION bin -+ # ARCHIVE DESTINATION ${LIB_INSTALL_DIR} -+ # LIBRARY DESTINATION ${LIB_INSTALL_DIR}) - ++ # install(TARGETS qpid-proton-proactor ${STATIC_LIBS} ++ # EXPORT proton ++ # RUNTIME DESTINATION bin ++ # ARCHIVE DESTINATION ${LIB_INSTALL_DIR} ++ # LIBRARY DESTINATION ${LIB_INSTALL_DIR}) + # Install windows pdb files if (MSVC) -@@ -594,10 +594,10 @@ +@@ -576,10 +576,10 @@ ${CMAKE_CURRENT_BINARY_DIR}/ProtonConfigVersion.cmake DESTINATION ${LIB_INSTALL_DIR}/cmake/Proton) - + -add_subdirectory(docs) -add_subdirectory(examples) -add_subdirectory(tests) -add_subdirectory(tools) -+#add_subdirectory(docs) -+#add_subdirectory(examples) -+#add_subdirectory(tests) -+#add_subdirectory(tools) - ++# add_subdirectory(docs) ++# add_subdirectory(examples) ++# add_subdirectory(tests) ++# add_subdirectory(tools) + install (DIRECTORY examples/ DESTINATION "${PROTON_SHARE}/examples/c" -diff -ur qpid-proton-0.26.0/CMakeLists.txt qpid-proton-patched/CMakeLists.txt ---- qpid-proton-0.26.0/CMakeLists.txt 2018-10-04 04:09:02.000000000 -0600 -+++ qpid-proton-patched/CMakeLists.txt 2019-03-25 17:32:41.521213312 -0600 -@@ -24,22 +24,22 @@ +diff -ur a/CMakeLists.txt b/CMakeLists.txt +--- a/CMakeLists.txt 2019-12-09 07:17:00.000000000 -0700 ++++ b/CMakeLists.txt 2019-12-19 18:11:57.128248724 -0700 +@@ -24,7 +24,7 @@ set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/tools/cmake/Modules") set (CMAKE_THREAD_PREFER_PTHREAD TRUE) - + -include (CTest) -+#include (CTest) ++# include (CTest) include (CheckLanguage) include (CheckLibraryExists) include (CheckSymbolExists) - include (CheckPythonModule) - --find_package (OpenSSL) -+#find_package (OpenSSL) +@@ -33,13 +33,13 @@ + find_package (OpenSSL) find_package (Threads) find_package (PythonInterp REQUIRED) -find_package (SWIG) --find_package (CyrusSASL) -+#find_package (SWIG) -+#find_package (CyrusSASL) - ++# find_package (SWIG) + find_package (CyrusSASL) + -enable_testing () +#enable_testing () - + # Set up runtime checks (valgrind, sanitizers etc.) --include(tests/RuntimeCheck.cmake) -+# include(tests/RuntimeCheck.cmake) - +-include(tests/RuntimeCheck.cmake) ++# include(tests/RuntimeCheck.cmake) + ## Variables used across components - -@@ -272,7 +272,7 @@ - + +@@ -260,7 +260,7 @@ + set (SYSINSTALL_BINDINGS OFF CACHE BOOL "If SYSINSTALL_BINDINGS is OFF then proton bindings will be installed underneath ${BINDINGS_DIR} and each user will need to modify their interpreter configuration to load the appropriate binding. If SYSINSTALL_BINDINGS is ON, then each language interpreter will be queried for the appropriate directory and proton bindings will be installed and available system wide with no additional per user configuration.") - + -set (BINDING_LANGS PYTHON RUBY) -+#set (BINDING_LANGS PYTHON RUBY) - ++# set (BINDING_LANGS PYTHON RUBY) + foreach (LANG ${BINDING_LANGS}) set (SYSINSTALL_${LANG} OFF CACHE BOOL "Install ${LANG} bindings into interpreter specified location.") -@@ -327,7 +327,7 @@ +@@ -315,7 +315,7 @@ endif() - + # Prerequisites for Go -find_program(GO_EXE go) -+#find_program(GO_EXE go) ++# find_program(GO_EXE go) mark_as_advanced(GO_EXE) if (GO_EXE) set (DEFAULT_GO ON) -diff -ur qpid-proton-0.26.0/cpp/CMakeLists.txt qpid-proton-patched/cpp/CMakeLists.txt ---- qpid-proton-0.26.0/cpp/CMakeLists.txt 2018-10-04 04:09:02.000000000 -0600 -+++ qpid-proton-patched/cpp/CMakeLists.txt 2019-03-25 17:32:41.521213312 -0600 -@@ -174,25 +174,25 @@ +diff -ur a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt +--- a/cpp/CMakeLists.txt 2019-12-09 07:17:00.000000000 -0700 ++++ b/cpp/CMakeLists.txt 2020-01-08 16:20:18.855394195 -0700 +@@ -174,30 +174,30 @@ set (CMAKE_DEBUG_POSTFIX "d") endif () - + -add_library(qpid-proton-cpp SHARED ${qpid-proton-cpp-source}) -+#add_library(qpid-proton-cpp SHARED ${qpid-proton-cpp-source}) ++# add_library(qpid-proton-cpp SHARED ${qpid-proton-cpp-source}) if(BUILD_STATIC_LIBS) add_library(qpid-proton-cpp-static STATIC ${qpid-proton-cpp-source}) + set(STATIC_LIBS qpid-proton-cpp-static) endif(BUILD_STATIC_LIBS) - + -target_link_libraries (qpid-proton-cpp LINK_PRIVATE ${PLATFORM_LIBS} qpid-proton-core qpid-proton-proactor ${CONNECT_CONFIG_LIBS}) -+#target_link_libraries (qpid-proton-cpp LINK_PRIVATE ${PLATFORM_LIBS} qpid-proton-core qpid-proton-proactor ${CONNECT_CONFIG_LIBS}) - ++# target_link_libraries (qpid-proton-cpp LINK_PRIVATE ${PLATFORM_LIBS} qpid-proton-core qpid-proton-proactor ${CONNECT_CONFIG_LIBS}) + -set_target_properties ( - qpid-proton-cpp - PROPERTIES @@ -189,44 +201,52 @@ diff -ur qpid-proton-0.26.0/cpp/CMakeLists.txt qpid-proton-patched/cpp/CMakeList - SOVERSION "${PN_LIB_CPP_MAJOR_VERSION}" - LINK_FLAGS "${CATCH_UNDEFINED} ${LTO}" - ) -+#set_target_properties ( -+# qpid-proton-cpp -+# PROPERTIES -+# LINKER_LANGUAGE CXX -+# VERSION "${PN_LIB_CPP_VERSION}" -+# SOVERSION "${PN_LIB_CPP_MAJOR_VERSION}" -+# LINK_FLAGS "${CATCH_UNDEFINED} ${LTO}" -+# ) - ++# set_target_properties ( ++# qpid-proton-cpp ++# PROPERTIES ++# LINKER_LANGUAGE CXX ++# VERSION "${PN_LIB_CPP_VERSION}" ++# SOVERSION "${PN_LIB_CPP_MAJOR_VERSION}" ++# LINK_FLAGS "${CATCH_UNDEFINED} ${LTO}" ++# ) + ## Install - --install(TARGETS qpid-proton-cpp -+install(TARGETS qpid-proton-cpp-static - EXPORT proton-cpp - RUNTIME DESTINATION bin - ARCHIVE DESTINATION ${LIB_INSTALL_DIR} -@@ -208,12 +208,12 @@ - + +-install(TARGETS qpid-proton-cpp ${STATIC_LIBS} +- EXPORT proton-cpp +- RUNTIME DESTINATION bin +- ARCHIVE DESTINATION ${LIB_INSTALL_DIR} +- LIBRARY DESTINATION ${LIB_INSTALL_DIR}) ++# install(TARGETS qpid-proton-cpp ${STATIC_LIBS} ++# EXPORT proton-cpp ++# RUNTIME DESTINATION bin ++# ARCHIVE DESTINATION ${LIB_INSTALL_DIR} ++# LIBRARY DESTINATION ${LIB_INSTALL_DIR}) + + # Install windows qpid-proton-cpp pdb files + if (MSVC) +@@ -209,12 +209,12 @@ + install (DIRECTORY "include/proton" DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.hpp") install (FILES "${CMAKE_CURRENT_BINARY_DIR}/config_presets.hpp" DESTINATION "${INCLUDE_INSTALL_DIR}/proton/internal") -install (DIRECTORY "examples/" - DESTINATION "${PROTON_SHARE}/examples/cpp" - USE_SOURCE_PERMISSIONS - PATTERN "ProtonCppConfig.cmake" EXCLUDE) -+#install (DIRECTORY "examples/" -+# DESTINATION "${PROTON_SHARE}/examples/cpp" -+# USE_SOURCE_PERMISSIONS -+# PATTERN "ProtonCppConfig.cmake" EXCLUDE) - ++# install (DIRECTORY "examples/" ++# DESTINATION "${PROTON_SHARE}/examples/cpp" ++# USE_SOURCE_PERMISSIONS ++# PATTERN "ProtonCppConfig.cmake" EXCLUDE) + -add_subdirectory(examples) -+#add_subdirectory(examples) ++# add_subdirectory(examples) add_subdirectory(docs) - + # Pkg config file -@@ -267,28 +267,28 @@ +@@ -268,40 +268,40 @@ set(test_env ${test_env} "PATH=$") endif() - + -macro(add_cpp_test test) - add_executable (${test} src/${test}.cpp) - target_link_libraries (${test} qpid-proton-cpp ${PLATFORM_LIBS}) @@ -242,9 +262,9 @@ diff -ur qpid-proton-0.26.0/cpp/CMakeLists.txt qpid-proton-patched/cpp/CMakeList -add_cpp_test(scalar_test) -add_cpp_test(value_test) -add_cpp_test(container_test) --add_cpp_test(url_test) -add_cpp_test(reconnect_test) -add_cpp_test(link_test) +-add_cpp_test(credit_test) -if (ENABLE_JSONCPP) - add_cpp_test(connect_config_test) - target_link_libraries(connect_config_test qpid-proton-core) # For pn_sasl_enabled @@ -252,48 +272,43 @@ diff -ur qpid-proton-0.26.0/cpp/CMakeLists.txt qpid-proton-patched/cpp/CMakeList - # Test data and output directories for connect_config_test - file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/testdata" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") -endif() -+#macro(add_cpp_test test) -+# add_executable (${test} src/${test}.cpp) -+# target_link_libraries (${test} qpid-proton-cpp ${PLATFORM_LIBS}) -+# add_test (NAME cpp-${test} -+# COMMAND ${PN_ENV_SCRIPT} -- ${test_env} ${TEST_EXE_PREFIX_CMD} $ ${ARGN}) -+#endmacro(add_cpp_test) ++# macro(add_cpp_test test) ++# add_executable (${test} src/${test}.cpp) ++# target_link_libraries (${test} qpid-proton-cpp ${PLATFORM_LIBS}) ++# add_test (NAME cpp-${test} ++# COMMAND ${PN_ENV_SCRIPT} -- ${test_env} ${TEST_EXE_PREFIX_CMD} $ ${ARGN}) ++# endmacro(add_cpp_test) +# -+#add_cpp_test(codec_test) -+#add_cpp_test(connection_driver_test) -+#add_cpp_test(interop_test ${CMAKE_SOURCE_DIR}/tests) -+#add_cpp_test(message_test) -+#add_cpp_test(map_test) -+#add_cpp_test(scalar_test) -+#add_cpp_test(value_test) -+#add_cpp_test(container_test) -+#add_cpp_test(url_test) -+#add_cpp_test(reconnect_test) -+#add_cpp_test(link_test) -+#if (ENABLE_JSONCPP) -+# add_cpp_test(connect_config_test) -+# target_link_libraries(connect_config_test qpid-proton-core) # For pn_sasl_enabled -+# set_tests_properties(cpp-connect_config_test PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") -+# # Test data and output directories for connect_config_test -+# file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/testdata" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") -+#endif() -diff -ur qpid-proton-0.26.0/cpp/include/proton/url.hpp qpid-proton-patched/cpp/include/proton/url.hpp ---- qpid-proton-0.26.0/cpp/include/proton/url.hpp 2018-10-04 04:09:02.000000000 -0600 -+++ qpid-proton-patched/cpp/include/proton/url.hpp 2019-03-25 17:33:50.956058757 -0600 -@@ -40,7 +40,6 @@ - /// An error encountered during URL parsing. - - struct --PN_CPP_DEPRECATED("Use a third-party URL library") - PN_CPP_CLASS_EXTERN url_error : public error { - /// @cond INTERNAL - /// Construct a URL error with a message. -@@ -62,7 +61,7 @@ - /// - /// - Path is normally used as a link source or target address. On a - /// broker it typically corresponds to a queue or topic name. --class PN_CPP_DEPRECATED("Use a third-party URL library") url { -+class url { - public: - static const std::string AMQP; ///< "amqp" prefix - static const std::string AMQPS; ///< "amqps" prefix ++# add_cpp_test(codec_test) ++# add_cpp_test(connection_driver_test) ++# add_cpp_test(interop_test ${CMAKE_SOURCE_DIR}/tests) ++# add_cpp_test(message_test) ++# add_cpp_test(map_test) ++# add_cpp_test(scalar_test) ++# add_cpp_test(value_test) ++# add_cpp_test(container_test) ++# add_cpp_test(reconnect_test) ++# add_cpp_test(link_test) ++# add_cpp_test(credit_test) ++# if (ENABLE_JSONCPP) ++# add_cpp_test(connect_config_test) ++# target_link_libraries(connect_config_test qpid-proton-core) # For pn_sasl_enabled ++# set_tests_properties(cpp-connect_config_test PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") ++# # Test data and output directories for connect_config_test ++# file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/testdata" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") ++# endif() + + # TODO aconway 2018-10-31: Catch2 tests + # This is a simple example of a C++ test using the Catch2 framework. + # See c/tests/ for more interesting examples. + # Eventually all the C++ tests will migrate to Catch2. + +-include_directories(${CMAKE_SOURCE_DIR}/tests/include) +-add_executable(cpp-test src/cpp-test.cpp src/url_test.cpp) +-target_link_libraries(cpp-test qpid-proton-cpp ${PLATFORM_LIBS}) ++#include_directories(${CMAKE_SOURCE_DIR}/tests/include) ++#add_executable(cpp-test src/cpp-test.cpp src/url_test.cpp) ++#target_link_libraries(cpp-test qpid-proton-cpp ${PLATFORM_LIBS}) + + macro(add_catch_test tag) + add_test ( diff --git a/doc/Doxyfile b/doc/Doxyfile index 84154e6ec..ec723e503 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1145,7 +1145,7 @@ EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 -# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 82afafc50..aa6e7d4c4 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -97,6 +97,10 @@ Development tips and tricks Run configure with the --enable-debug option, then make. Or run configure with CXXFLAGS="-g -ggdb -O0" or whatever debug flags you need. +**compiling for gprof profiling** + +Run configure with the --enable-gprof option, then make. + **debug.log** If the code is behaving strangely, take a look in the debug.log file in the data directory; @@ -121,6 +125,57 @@ can be very difficult to track down. Compiling with -DDEBUG_LOCKORDER (configure CXXFLAGS="-DDEBUG_LOCKORDER -g") inserts run-time checks to keep track of which locks are held, and adds warnings to the debug.log file if inconsistencies are detected. +**Sanitizers** + +Bitcoin can be compiled with various "sanitizers" enabled, which add +instrumentation for issues regarding things like memory safety, thread race +conditions, or undefined behavior. This is controlled with the +`--with-sanitizers` configure flag, which should be a comma separated list of +sanitizers to enable. The sanitizer list should correspond to supported +`-fsanitize=` options in your compiler. These sanitizers have runtime overhead, +so they are most useful when testing changes or producing debugging builds. + +Some examples: + +```bash +# Enable both the address sanitizer and the undefined behavior sanitizer +./configure --with-sanitizers=address,undefined + +# Enable the thread sanitizer +./configure --with-sanitizers=thread +``` + +If you are compiling with GCC you will typically need to install corresponding +"san" libraries to actually compile with these flags, e.g. libasan for the +address sanitizer, libtsan for the thread sanitizer, and libubsan for the +undefined sanitizer. If you are missing required libraries, the configure script +will fail with a linker error when testing the sanitizer flags. + +The test suite should pass cleanly with the `thread` and `undefined` sanitizers, +but there are a number of known problems when using the `address` sanitizer. The +address sanitizer is known to fail in +[sha256_sse4::Transform](/src/crypto/sha256_sse4.cpp) which makes it unusable +unless you also use `--disable-asm` when running configure. We would like to fix +sanitizer issues, so please send pull requests if you can fix any errors found +by the address sanitizer (or any other sanitizer). + +Not all sanitizer options can be enabled at the same time, e.g. trying to build +with `--with-sanitizers=address,thread` will fail in the configure script as +these sanitizers are mutually incompatible. Refer to your compiler manual to +learn more about these options and which sanitizers are supported by your +compiler. + +Additional resources: + + * [AddressSanitizer](https://clang.llvm.org/docs/AddressSanitizer.html) + * [LeakSanitizer](https://clang.llvm.org/docs/LeakSanitizer.html) + * [MemorySanitizer](https://clang.llvm.org/docs/MemorySanitizer.html) + * [ThreadSanitizer](https://clang.llvm.org/docs/ThreadSanitizer.html) + * [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) + * [GCC Instrumentation Options](https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html) + * [Google Sanitizers Wiki](https://github.com/google/sanitizers/wiki) + * [Issue #12691: Enable -fsanitize flags in Travis](https://github.com/bitcoin/bitcoin/issues/12691) + Locking/mutex usage notes ------------------------- @@ -182,4 +237,4 @@ ACK - A loose ACK can be confusing. It's best to avoid them unless it's a docum NACK - Disagree with the code changes/concept. Should be accompanied by an explanation. -See the [Development Guidelines](https://zcash.readthedocs.io/en/latest/rtd_pages/development_guidelines.html) documentation for preferred workflows, information on continuous integration and release versioning. \ No newline at end of file +See the [Development Guidelines](https://zcash.readthedocs.io/en/latest/rtd_pages/development_guidelines.html) documentation for preferred workflows, information on continuous integration and release versioning. diff --git a/doc/man/bitcoinz-cli.1 b/doc/man/bitcoinz-cli.1 index 34c461886..ac1b5505b 100644 --- a/doc/man/bitcoinz-cli.1 +++ b/doc/man/bitcoinz-cli.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH BITCOINZ-CLI "1" "Sep 2022" "bitcoinz-cli v2.0.8" "User Commands" +.TH BITCOINZ-CLI "1" "July 2024" "bitcoinz-cli v2.0.9-rc2" "User Commands" .SH NAME -bitcoinz-cli \- manual page for bitcoinz-cli v2.0.8 +bitcoinz-cli \- manual page for bitcoinz-cli v2.0.9-rc2 .SH DESCRIPTION -BitcoinZ RPC client version v2.0.8 +BitcoinZ RPC client version v2.0.9\-rc2 .PP In order to ensure you are adequately protecting your privacy when using BitcoinZ, please see . @@ -83,7 +83,3 @@ This is experimental software. Distributed under the MIT software license, see the accompanying file COPYING or . - -This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit and cryptographic software written -by Eric Young. diff --git a/doc/man/bitcoinz-tx.1 b/doc/man/bitcoinz-tx.1 index 9eb45c1c9..e66617b06 100644 --- a/doc/man/bitcoinz-tx.1 +++ b/doc/man/bitcoinz-tx.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH BITCOINZ-TX "1" "Sep 2022" "bitcoinz-tx v2.0.8" "User Commands" +.TH BITCOINZ-TX "1" "July 2024" "bitcoinz-tx v2.0.9-rc2" "User Commands" .SH NAME -bitcoinz-tx \- manual page for bitcoinz-tx v2.0.8 +bitcoinz-tx \- manual page for bitcoinz-tx v2.0.9-rc2 .SH DESCRIPTION -BitcoinZ bitcoinz\-tx utility version v2.0.8 +BitcoinZ bitcoinz\-tx utility version v2.0.9\-rc2 .SS "Usage:" .TP bitcoinz\-tx [options] [commands] @@ -96,7 +96,3 @@ This is experimental software. Distributed under the MIT software license, see the accompanying file COPYING or . - -This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit and cryptographic software written -by Eric Young. diff --git a/doc/man/bitcoinzd.1 b/doc/man/bitcoinzd.1 index ee85749ca..7275282e3 100644 --- a/doc/man/bitcoinzd.1 +++ b/doc/man/bitcoinzd.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH BITCOINZD "1" "Sep 2022" "bitcoinzd v2.0.8" "User Commands" +.TH BITCOINZD "1" "July 2024" "bitcoinzd v2.0.9-rc2" "User Commands" .SH NAME -bitcoinzd \- manual page for bitcoinzd v2.0.8 +bitcoinzd \- manual page for bitcoinzd v2.0.9-rc2 .SH DESCRIPTION -BitcoinZ Daemon version v2.0.8 +BitcoinZ Daemon version v2.0.9\-rc2 .PP In order to ensure you are adequately protecting your privacy when using BitcoinZ, please see . @@ -496,7 +496,3 @@ This is experimental software. Distributed under the MIT software license, see the accompanying file COPYING or . - -This product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit and cryptographic software written -by Eric Young. diff --git a/doc/man/zcash-fetch-params.1 b/doc/man/zcash-fetch-params.1 index 1add4658b..6c9cf5888 100644 --- a/doc/man/zcash-fetch-params.1 +++ b/doc/man/zcash-fetch-params.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6. -.TH ZCASH-FETCH-PARAMS "1" "January 2017" "Zcash - zcash-fetch-params" "User Commands" +.TH ZCASH-FETCH-PARAMS "1" "July 2024" "Zcash - zcash-fetch-params" "User Commands" .SH NAME zcash-fetch-params \- Downloads the Zcash network parameters .SH DESCRIPTION diff --git a/doc/release-notes.md b/doc/release-notes.md index a29094b51..f525d5096 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -1,6 +1,142 @@ -(note: this is a temporary file, to be added-to by anybody, and moved to -release-notes at release time) - Notable changes =============== +DoS Mitigation: Mempool Size Limit and Random Drop +-------------------------------------------------- + +This release adds a mechanism for preventing nodes from running out of memory +in the situation where an attacker is trying to overwhelm the network with +transactions. This is achieved by keeping track of and limiting the total +`cost` and `evictionWeight` of all transactions in the mempool. The `cost` of a +transaction is determined by its size in bytes, and its `evictionWeight` is a +function of the transaction's `cost` and its fee. The maximum total cost is +configurable via the parameter `mempooltxcostlimit` which defaults to +80,000,000 (up to 20,000 txs). If a node's total mempool `cost` exceeds this +limit the node will evict a random transaction, preferentially picking larger +transactions and ones with below the standard fee. To prevent a node from +re-accepting evicted transactions, it keeps track of ones that it has evicted +recently. By default, a transaction will be considered recently evicted for 60 +minutes, but this can be configured with the parameter +`mempoolevictionmemoryminutes`. + +For full details see ZIP 401. + +Asynchronous Operations Incorrectly Reporting Success +----------------------------------------------------- +We fixed an issue where asynchronous operations were sometimes reporting sucess +when they had actually failed. One way this could occur was when trying to use +`z_sendmany` to create a transaction spending coinbase funds in a way where +change would be generated (not a valid use of `z_sendmany`). In this case the +operation would erroneously report success, and the only way to see that the +transaction had actually failed was to look in the `debug.log` file. Such +operations will now correctly report that they have failed. + +Fake chain detection during initial block download +-------------------------------------------------- + +One of the mechanisms that `bitcoinzd` uses to detect whether it is in "initial +block download" (IBD) mode is to compare the active chain's cumulative work +against a hard-coded "minimum chain work" value. This mechanism (inherited from +Bitcoin Core) means that once a node exits IBD mode, it is either on the main +chain, or a fake alternate chain with similar amounts of work. In the latter +case, the node has most likely become the victim of a 50% + 1 adversary. + +Starting from this release, `bitcoinzd` additionally hard-codes the block hashes +for the activation blocks of each past network upgrade (NU). During initial +chain synchronization, and after the active chain has reached "minimum chain +work", the node checks the blocks at each NU activation height against the +hard-coded hashes. If any of them do not match, the node will immediately alert +the user and **shut down for safety**. + +Disabling old Sprout proofs +--------------------------- + +As part of our ongoing work to clean up the codebase and minimise the security +surface of `bitcoinzd`, we are removing `libsnark` from the codebase, and dropping +support for creating and verifying old Sprout proofs. Funds stored in Sprout +addresses are not affected, as they are spent using the hybrid Sprout circuit +(built using `bellman`) that was deployed during the Sapling network upgrade. + +This change has several implications: + +- `bitcoinzd` no longer verifies old Sprout proofs, and will instead assume they + are valid. This has a minor implication for nodes: during initial block + download, an adversary could feed the node fake blocks containing invalid old + Sprout proofs, and the node would accept the fake chain as valid. However, + as soon as the active chain contains at least as much work as the hard-coded + "minimum chain work" value, the node will detect this situation and shut down. + +- Shielded transactions can no longer be created before Sapling has activated. + This does not affect BitcoinZ itself, but will affect downstream codebases that + have not yet activated Sapling (or that start a new chain after this point and + do not activate Sapling from launch). Note that the old Sprout circuit is + [vulnerable to counterfeiting](https://z.cash/support/security/announcements/security-announcement-2019-02-05-cve-2019-7167/) + and should not be used in current deployments. + +- Starting from this release, the circuit parameters from the original Sprout + MPC are no longer required to start `bitcoinzd`, and will not be downloaded by + `fetch-params.sh`. They are not being automatically deleted at this time. + +Option parsing behavior +----------------------- + +Command line options are now parsed strictly in the order in which they are +specified. It used to be the case that `-X -noX` ends up, unintuitively, with X +set, as `-X` had precedence over `-noX`. This is no longer the case. Like for +other software, the last specified value for an option will hold. + +Low-level RPC changes +--------------------- + +- Bare multisig outputs to our keys are no longer automatically treated as + incoming payments. As this feature was only available for multisig outputs for + which you had all private keys in your wallet, there was generally no use for + them compared to single-key schemes. Furthermore, no address format for such + outputs is defined, and wallet software can't easily send to it. These outputs + will no longer show up in `listtransactions`, `listunspent`, or contribute to + your balance, unless they are explicitly watched (using `importaddress` or + `importmulti` with hex script argument). `signrawtransaction*` also still + works for them. + +View shielded information in wallet transactions +------------------------------------------------ + +In previous `bitcoinzd` versions, to obtain information about shielded transactions +you would use either the `z_listreceivedbyaddress` RPC method (which returns all +notes received by an address) or `z_listunspent` (which returns unspent notes, +optionally filtered by addresses). There were no RPC methods that directly +returned details about spends, or anything equivalent to the `gettransaction` +method (which returns transparent information about in-wallet transactions). + +This release introduces a new RPC method `z_viewtransaction` to fill that gap. +Given the ID of a transaction in the wallet, it decrypts the transaction and +returns detailed shielded information for all decryptable new and spent notes, +including: + +- The address that each note belongs to. +- Values in both decimal ZEC and zatoshis. +- The ID of the transaction that each spent note was received in. +- An `outgoing` flag on each new note, which will be `true` if the output is not + for an address in the wallet. +- A `memoStr` field for each new note, containing its text memo (if its memo + field contains a valid UTF-8 string). + +Information will be shown for any address that appears in `z_listaddresses`; +this includes watch-only addresses linked to viewing keys imported with +`z_importviewingkey`, as well as addresses with spending keys (both generated +with `z_getnewaddress` and imported with `z_importkey`). + +Build system +------------ + +- The `--enable-lcov`, `--disable-tests`, and `--disable-mining` flags for + `zcutil/build.sh` have been removed. You can pass these flags instead by using + the `CONFIGURE_FLAGS` environment variable. For example, to enable coverage + instrumentation (thus enabling "make cov" to work), call: + + ``` + CONFIGURE_FLAGS="--enable-lcov --disable-hardening" ./zcutil/build.sh + ``` + +- The build system no longer defaults to verbose output. You can re-enable + verbose output with `./zcutil/build.sh V=1` diff --git a/doc/release-notes/release-notes-2.0.8.md b/doc/release-notes/release-notes-2.0.8.md new file mode 100644 index 000000000..70cc8f33e --- /dev/null +++ b/doc/release-notes/release-notes-2.0.8.md @@ -0,0 +1,12 @@ +Notable changes +=============== + +* add z_gettreestate RPC +* Fix the use of 0 as expiryheight in createrawtransaction, to disable expiry +* Bitcoin 0.12 wallet PRs 1 +* Fix CVE-2017-18350 +* Wallet interface refactor +* Update z_viewtransaction +* insightexplorer: LOCK(cs_main) during rpcs +* Return address and type of imported key in z_importkey +* This release addresses an incoming deprecation to extend node for approximately 3.5 years. diff --git a/doc/release-notes/release-notes-2.0.9-rc1.md b/doc/release-notes/release-notes-2.0.9-rc1.md new file mode 100644 index 000000000..5586dd767 --- /dev/null +++ b/doc/release-notes/release-notes-2.0.9-rc1.md @@ -0,0 +1,78 @@ +Notable changes +=============== + +DoS Mitigation: Mempool Size Limit and Random Drop +-------------------------------------------------- + +This release adds a mechanism for preventing nodes from running out of memory +in the situation where an attacker is trying to overwhelm the network with +transactions. This is achieved by keeping track of and limiting the total +`cost` and `evictionWeight` of all transactions in the mempool. The `cost` of a +transaction is determined by its size in bytes, and its `evictionWeight` is a +function of the transaction's `cost` and its fee. The maximum total cost is +configurable via the parameter `mempooltxcostlimit` which defaults to +80,000,000 (up to 20,000 txs). If a node's total mempool `cost` exceeds this +limit the node will evict a random transaction, preferentially picking larger +transactions and ones with below the standard fee. To prevent a node from +re-accepting evicted transactions, it keeps track of ones that it has evicted +recently. By default, a transaction will be considered recently evicted for 60 +minutes, but this can be configured with the parameter +`mempoolevictionmemoryminutes`. + +For full details see ZIP 401. + +Asynchronous Operations Incorrectly Reporting Success +----------------------------------------------------- +We fixed an issue where asynchronous operations were sometimes reporting sucess +when they had actually failed. One way this could occur was when trying to use +`z_sendmany` to create a transaction spending coinbase funds in a way where +change would be generated (not a valid use of `z_sendmany`). In this case the +operation would erroneously report success, and the only way to see that the +transaction had actually failed was to look in the `debug.log` file. Such +operations will now correctly report that they have failed. + +Fake chain detection during initial block download +-------------------------------------------------- + +One of the mechanisms that `bitcoinzd` uses to detect whether it is in "initial +block download" (IBD) mode is to compare the active chain's cumulative work +against a hard-coded "minimum chain work" value. This mechanism (inherited from +Bitcoin Core) means that once a node exits IBD mode, it is either on the main +chain, or a fake alternate chain with similar amounts of work. In the latter +case, the node has most likely become the victim of a 50% + 1 adversary. + +Starting from this release, `bitcoinzd` additionally hard-codes the block hashes +for the activation blocks of each past network upgrade (NU). During initial +chain synchronization, and after the active chain has reached "minimum chain +work", the node checks the blocks at each NU activation height against the +hard-coded hashes. If any of them do not match, the node will immediately alert +the user and **shut down for safety**. + +Disabling old Sprout proofs +--------------------------- + +As part of our ongoing work to clean up the codebase and minimise the security +surface of `bitcoinzd`, we are removing `libsnark` from the codebase, and dropping +support for creating and verifying old Sprout proofs. Funds stored in Sprout +addresses are not affected, as they are spent using the hybrid Sprout circuit +(built using `bellman`) that was deployed during the Sapling network upgrade. + +This change has several implications: + +- `bitcoinzd` no longer verifies old Sprout proofs, and will instead assume they + are valid. This has a minor implication for nodes: during initial block + download, an adversary could feed the node fake blocks containing invalid old + Sprout proofs, and the node would accept the fake chain as valid. However, + as soon as the active chain contains at least as much work as the hard-coded + "minimum chain work" value, the node will detect this situation and shut down. + +- Shielded transactions can no longer be created before Sapling has activated. + This does not affect BitcoinZ itself, but will affect downstream codebases that + have not yet activated Sapling (or that start a new chain after this point and + do not activate Sapling from launch). Note that the old Sprout circuit is + [vulnerable to counterfeiting](https://z.cash/support/security/announcements/security-announcement-2019-02-05-cve-2019-7167/) + and should not be used in current deployments. + +- Starting from this release, the circuit parameters from the original Sprout + MPC are no longer required to start `bitcoinzd`, and will not be downloaded by + `fetch-params.sh`. They are not being automatically deleted at this time. diff --git a/libzcashconsensus.pc.in b/libzcashconsensus.pc.in index 5cb2d05e3..7391bb9da 100644 --- a/libzcashconsensus.pc.in +++ b/libzcashconsensus.pc.in @@ -8,4 +8,3 @@ Description: Library for the Zcash consensus protocol. Version: @PACKAGE_VERSION@ Libs: -L${libdir} -lzcashconsensus Cflags: -I${includedir} -Requires.private: libcrypto diff --git a/qa/bitcoinz/checksec.sh b/qa/bitcoinz/checksec.sh index dd1f72e54..731b340d4 100644 --- a/qa/bitcoinz/checksec.sh +++ b/qa/bitcoinz/checksec.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# The BSD License (http://www.opensource.org/licenses/bsd-license.php) +# The BSD License (https://www.opensource.org/licenses/bsd-license.php) # specifies the terms and conditions of use for checksec.sh: # # Copyright (c) 2009-2011, Tobias Klein. diff --git a/qa/bitcoinz/full_test_suite.py b/qa/bitcoinz/full_test_suite.py old mode 100644 new mode 100755 index e7ab9e135..4268e1fb5 --- a/qa/bitcoinz/full_test_suite.py +++ b/qa/bitcoinz/full_test_suite.py @@ -132,25 +132,25 @@ def util_test(): # STAGES = [ + 'check-depends', 'btest', 'gtest', 'sec-hard', 'no-dot-so', 'util-test', 'secp256k1', - 'libsnark', 'univalue', 'rpc', ] STAGE_COMMANDS = { - 'btest': [repofile('src/test/test_bitcoin'), '-p'], + 'check-depends': ['qa/bitcoinz/test-depends-sources-mirror.py'], + 'btest': [repofile('src/test/test_bitcoinz'), '-p'], 'gtest': [repofile('src/bitcoinz-gtest')], 'sec-hard': check_security_hardening, 'no-dot-so': ensure_no_dot_so_in_depends, 'util-test': util_test, 'secp256k1': ['make', '-C', repofile('src/secp256k1'), 'check'], - 'libsnark': ['make', '-C', repofile('src'), 'libsnark-tests'], 'univalue': ['make', '-C', repofile('src/univalue'), 'check'], 'rpc': [repofile('qa/pull-tester/rpc-tests.sh')], } diff --git a/qa/bitcoinz/updatecheck.py b/qa/bitcoinz/updatecheck.py new file mode 100755 index 000000000..238787a9c --- /dev/null +++ b/qa/bitcoinz/updatecheck.py @@ -0,0 +1,362 @@ +#!/usr/bin/env python +# +# This script checks for updates to bitcoinzd's dependencies. +# +# The SOURCE_ROOT constant specifies the location of the bitcoinzd codebase to +# check, and the GITHUB_API_* constants specify a personal access token for the +# GitHub API, which need not have any special privileges. +# +# All dependencies must be specified inside the get_dependency_list() function +# below. A dependency is specified by: +# +# (a) A way to fetch a list of current releases. +# +# This is usually regular-expression-based parsing of GitHub tags, but +# might otherwise parse version numbers out of the project's webpage. +# +# GitHub tag regexps can be tested by specifying test cases in the third +# argument to GithubTagReleaseLister's constructor. +# +# (b) A way to fetch the currently-used version out of the source tree. +# +# This is typically parsed out of the depends/packages/*.mk files. +# +# If any dependency is found to be out-of-date, or there are un-accounted-for +# .mk files in depends/packages, this script will exit with +# a nonzero status. The latter case would suggest someone added a new dependency +# without adding a corresponding entry to get_dependency_list() below. + +import requests +import os +import re +import sys + +SOURCE_ROOT = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", "..") +# The email for this account is taylor@electriccoin.co and the token does not +# have any privileges. +GITHUB_API_BASIC_AUTH_USER = "taylor-ecc" +GITHUB_API_BASIC_AUTH_PASSWORD = "df2cb6d13a29837e9dc97c7db1eff058e8fa6618" + +def get_dependency_list(): + dependencies = [ + Dependency("bdb", + BerkeleyDbReleaseLister(), + DependsVersionGetter("bdb")), + Dependency("boost", + GithubTagReleaseLister("boostorg", "boost", "^boost-(\d+)\.(\d+)\.(\d+)$", + { "boost-1.69.0": (1, 69, 0), "boost-1.69.0-beta1": None }), + DependsVersionGetter("boost")), + Dependency("googletest", + GithubTagReleaseLister("google", "googletest", "^release-(\d+)\.(\d+)\.(\d+)$", + { "release-1.8.1": (1, 8, 1) }), + DependsVersionGetter("googletest")), + Dependency("libevent", + GithubTagReleaseLister("libevent", "libevent", "^release-(\d+)\.(\d+)\.(\d+)-stable$", + { "release-2.0.22-stable": (2, 0, 22), "release-2.1.9-beta": None }), + DependsVersionGetter("libevent")), + Dependency("libsodium", + GithubTagReleaseLister("jedisct1", "libsodium", "^(\d+)\.(\d+)\.(\d+)$", + { "1.0.17": (1, 0, 17) }), + DependsVersionGetter("libsodium")), + Dependency("native_ccache", + GithubTagReleaseLister("ccache", "ccache", "^v?(\d+)\.(\d+)(?:\.(\d+))?$", + { "v3.5.1": (3, 5, 1), "v3.6": (3, 6)}), + DependsVersionGetter("native_ccache")), + Dependency("openssl", + GithubTagReleaseLister("openssl", "openssl", "^OpenSSL_(\d+)_(\d+)_(\d+)([a-z]+)?$", + { "OpenSSL_1_1_1b": (1, 1, 1, 'b'), "OpenSSL_1_1_1-pre9": None }), + DependsVersionGetter("openssl")), + Dependency("proton", + GithubTagReleaseLister("apache", "qpid-proton", "^(\d+)\.(\d+)(?:\.(\d+))?$", + { "0.27.0": (0, 27, 0), "0.10": (0, 10), "0.12.0-rc": None }), + DependsVersionGetter("proton")), + Dependency("rust", + GithubTagReleaseLister("rust-lang", "rust", "^(\d+)\.(\d+)(?:\.(\d+))?$", + { "1.33.0": (1, 33, 0), "0.9": (0, 9) }), + DependsVersionGetter("rust")), + Dependency("zeromq", + GithubTagReleaseLister("zeromq", "libzmq", "^v(\d+)\.(\d+)(?:\.(\d+))?$", + { "v4.3.1": (4, 3, 1), "v4.2.0-rc1": None }), + DependsVersionGetter("zeromq")), + Dependency("leveldb", + GithubTagReleaseLister("google", "leveldb", "^v(\d+)\.(\d+)$", + { "v1.13": (1, 13) }), + LevelDbVersionGetter()), + ] + + # Rust crates. + crates = [ + "aes", "aesni", "aes_soft", "arrayvec", "bellman", + "arrayref", "autocfg", "bech32", "blake2b_simd", "blake2s_simd", + "bit_vec", "block_cipher_trait", "byteorder", + "block_buffer", "block_padding", "c2_chacha", "cfg_if", + "byte_tools", "constant_time_eq", "crossbeam", "digest", "fpe", + "crossbeam_channel", "crossbeam_deque", "crossbeam_epoch", + "crossbeam_utils", "crossbeam_queue", "crypto_api", "crypto_api_chachapoly", + "directories", "fake_simd", "getrandom", "hex", "log", + "futures_cpupool", "futures", + "generic_array", "lazy_static", "libc", "nodrop", "num_bigint", + "memoffset", "ppv_lite86", "proc_macro2", "quote", + "num_cpus", "num_integer", "num_traits", "opaque_debug", "pairing", + "rand", "typenum", + "rand_chacha", "rand_core", "rand_hc", "rand_os", "rand_xorshift", + "rustc_version", "scopeguard", "semver", "semver_parser", "sha2", "syn", + "unicode_xid", "wasi", + "winapi_i686_pc_windows_gnu", "winapi", "winapi_x86_64_pc_windows_gnu", + ] + + for crate in crates: + dependencies.append( + Dependency("crate_" + crate, + RustCrateReleaseLister(crate), + DependsVersionGetter("crate_" + crate) + ) + ) + + return dependencies + +class Version(list): + def __init__(self, version_tuple): + for part in version_tuple: + if part: # skip None's which can come from optional regexp groups + if str(part).isdigit(): + self.append(int(part)) + else: + self.append(part) + + def __str__(self): + return '.'.join(map(str, self)) + + def __hash__(self): + return hash(tuple(self)) + +class Dependency: + def __init__(self, name, release_lister, current_getter): + self.name = name + self.release_lister = release_lister + self.current_getter = current_getter + self.cached_known_releases = None + + def current_version(self): + return self.current_getter.current_version() + + def known_releases(self): + if self.cached_known_releases is None: + self.cached_known_releases = sorted(self.release_lister.known_releases()) + return self.cached_known_releases + + def released_versions_after_current_version(self): + current_version = self.current_version() + releases_after_current = [] + + for release in self.known_releases(): + if release > current_version: + releases_after_current.append(release) + + return releases_after_current + + def is_up_to_date(self): + return len(self.released_versions_after_current_version()) == 0 + +class GithubTagReleaseLister: + def __init__(self, org, repo, regex, testcases={}): + self.org = org + self.repo = repo + self.regex = regex + self.testcases = testcases + + for tag, expected in testcases.items(): + match = re.match(self.regex, tag) + if (expected and not match) or (match and not expected) or (match and Version(match.groups()) != list(expected)): + groups = str(match.groups()) + raise RuntimeError("GitHub tag regex test case [" + tag + "] failed, got [" + groups + "].") + + def known_releases(self): + release_versions = [] + all_tags = self.all_tag_names() + + # sanity check against the test cases + for tag, expected in self.testcases.items(): + if tag not in all_tags: + raise RuntimeError("Didn't find expected tag [" + tag + "].") + + for tag_name in all_tags: + match = re.match(self.regex, tag_name) + if match: + release_versions.append(Version(match.groups())) + + return release_versions + + def all_tag_names(self): + url = "https://api.github.com/repos/" + safe(self.org) + "/" + safe(self.repo) + "/git/refs/tags" + r = requests.get(url, auth=requests.auth.HTTPBasicAuth(GITHUB_API_BASIC_AUTH_USER, GITHUB_API_BASIC_AUTH_PASSWORD)) + if r.status_code != 200: + raise RuntimeError("Request to GitHub tag API failed.") + json = r.json() + return list(map(lambda t: t["ref"].split("/")[-1], json)) + +class RustCrateReleaseLister: + def __init__(self, crate): + self.crate = crate + + def known_releases(self): + url = "https://crates.io/api/v1/crates/" + safe(self.crate) + "/versions" + r = requests.get(url) + if r.status_code != 200: + raise RuntimeError("Request to crates.io versions API failed.") + json = r.json() + version_numbers = list(map(lambda t: t["num"], json["versions"])) + + release_versions = [] + for num in version_numbers: + match = re.match("^(\d+)\.(\d+)\.(\d+)$", num) + if match: + release_versions.append(Version(match.groups())) + + if len(release_versions) == 0: + raise RuntimeError("Failed to list release versions from crates.io.") + + return release_versions + +class LibGmpReleaseLister: + def known_releases(self): + url = "https://gmplib.org/download/gmp/" + r = requests.get(url) + if r.status_code != 200: + raise RuntimeError("Request to libgmp download directory failed.") + page = r.text + + # We use a set because the search will result in duplicates. + release_versions = set() + for match in re.findall("gmp-(\d+)\.(\d+)\.(\d+)\.tar.bz2", page): + release_versions.add(Version(match)) + + if Version((6, 1, 2)) not in release_versions: + raise RuntimeError("Missing expected version from libgmp download directory.") + + return list(release_versions) + +class BerkeleyDbReleaseLister: + def known_releases(self): + url = "https://www.oracle.com/technetwork/products/berkeleydb/downloads/index-082944.html" + r = requests.get(url) + if r.status_code != 200: + raise RuntimeError("Request to Berkeley DB download directory failed.") + page = r.text + + # We use a set because the search will result in duplicates. + release_versions = set() + for match in re.findall("Berkeley DB (\d+)\.(\d+)\.(\d+)\.tar.gz", page): + release_versions.add(Version(match)) + + if Version((6, 2, 38)) not in release_versions: + raise RuntimeError("Missing expected version from Oracle web page.") + + return list(release_versions) + +class DependsVersionGetter: + def __init__(self, name): + self.name = name + + def current_version(self): + mk_file_path = os.path.join(SOURCE_ROOT, "depends", "packages", safe(self.name) + ".mk") + mk_file = open(mk_file_path, 'r').read() + + regexp_whitelist = [ + "package\)_version=(\d+)\.(\d+)\.(\d+)$", + "package\)_version=(\d+)\.(\d+)$", + "package\)_version=(\d+)_(\d+)_(\d+)$", + "package\)_version=(\d+)\.(\d+)\.(\d+)([a-z])$" + ] + + current_version = None + + for regexp in regexp_whitelist: + match = re.search(regexp, mk_file, re.MULTILINE) + if match: + current_version = Version(match.groups()) + + if not current_version: + raise RuntimeError("Couldn't parse version number from depends .mk file.") + + return current_version + +class LevelDbVersionGetter: + def current_version(self): + header_path = os.path.join(SOURCE_ROOT, "src", "leveldb", "include", "leveldb", "db.h") + header_contents = open(header_path, 'r').read() + + match = re.search("kMajorVersion\s*=\s*(\d+);\s*.*kMinorVersion\s*=\s*(\d+);\s*$", header_contents, re.MULTILINE) + if match: + return Version(match.groups()) + else: + raise RuntimeError("Couldn't parse LevelDB's version from db.h") + +def safe(string): + if re.match('^[a-zA-Z0-9_-]*$', string): + return string + else: + raise RuntimeError("Potentially-dangerous string encountered.") + +def print_row(name, status, current_version, known_versions): + COL_FMT_LARGE = "{:<35}" + COL_FMT_SMALL = "{:<18}" + print(COL_FMT_LARGE.format(name) + + COL_FMT_SMALL.format(status) + + COL_FMT_SMALL.format(current_version) + + COL_FMT_SMALL.format(known_versions)) + +def main(): + # Get a list of all depends-system dependencies so we can verify that we're + # checking them all for updates. + unchecked_dependencies = [f[:-3] for f in os.listdir(os.path.join(SOURCE_ROOT, "depends", "packages")) if f.endswith(".mk")] + + untracked = [ + # packages.mk is not a dependency, it just specifies the list of them all. + "packages", + # just a template + "vendorcrate", + # These are pinned to specific git revisions. + "librustzcash", + "crate_sapling_crypto", + "crate_zip32", + # This package doesn't have conventional version numbers + "native_cctools" + ] + + print_row("NAME", "STATUS", "CURRENT VERSION", "NEWER VERSIONS") + + for dep in untracked: + print_row(dep, "skipped", "", "") + unchecked_dependencies.remove(dep) + + deps = get_dependency_list() + status = 0 + for dependency in deps: + if dependency.name in unchecked_dependencies: + unchecked_dependencies.remove(dependency.name) + if len(sys.argv) == 2 and sys.argv[1] == "skipcheck": + print("Skipping the actual dependency update checks.") + else: + if dependency.is_up_to_date(): + print_row( + dependency.name, + "up to date", + str(dependency.current_version()), + "") + else: + print_row( + dependency.name, + "OUT OF DATE", + str(dependency.current_version()), + str(list(map(str, dependency.released_versions_after_current_version())))) + status = 1 + + if len(unchecked_dependencies) > 0: + unchecked_dependencies.sort() + print("WARNING: The following dependences are not being checked for updates by this script: " + unchecked_dependencies) + status = 2 + + sys.exit(status) + +main() diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 4ab7fc3b9..2684bb04f 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -18,7 +18,7 @@ testScripts=( 'wallet_changeaddresses.py' 'wallet_changeindicator.py' 'wallet_import_export.py' - 'wallet_protectcoinbase.py' + 'wallet_shieldingcoinbase.py' 'wallet_shieldcoinbase_sprout.py' 'wallet_shieldcoinbase_sapling.py' 'wallet_listreceived.py' @@ -41,10 +41,11 @@ testScripts=( 'rawtransactions.py' 'getrawtransaction_insight.py' 'rest.py' + 'mempool_limit.py' 'mempool_spendcoinbase.py' 'mempool_coinbase_spends.py' - 'mempool_tx_input_limit.py' 'httpbasics.py' + 'multi_rpc.py' 'zapwallettxes.py' # 'proxy_test.py' 'merkle_blocks.py' @@ -94,6 +95,7 @@ testScriptsExt=( 'invalidblockrequest.py' # 'forknotify.py' 'p2p-acceptblock.py' + 'wallet_db_flush.py' ); if [ "x$ENABLE_ZMQ" = "x1" ]; then @@ -117,13 +119,14 @@ function runTestScript echo -e "=== Running testscript ${testName} ===" + local startTime=$(date +%s) if eval "$@" then successCount=$(expr $successCount + 1) - echo "--- Success: ${testName} ---" + echo "--- Success: ${testName} ($(($(date +%s) - $startTime))s) ---" else failures[${#failures[@]}]="$testName" - echo "!!! FAIL: ${testName} !!!" + echo "!!! FAIL: ${testName} ($(($(date +%s) - $startTime))s) !!!" fi echo diff --git a/qa/rpc-tests/addressindex.py b/qa/rpc-tests/addressindex.py index 023fb0155..066c8be0c 100755 --- a/qa/rpc-tests/addressindex.py +++ b/qa/rpc-tests/addressindex.py @@ -2,35 +2,31 @@ # Copyright (c) 2020 The BitcoinZ Community # Copyright (c) 2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # -# Test addressindex generation and fetching for insightexplorer +# Test addressindex generation and fetching for insightexplorer or lightwalletd # # RPCs tested here: # # getaddresstxids # getaddressbalance # getaddressdeltas -# getaddressutxos +# getaddressutxos - available only for insightexplorer # getaddressmempool -# import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.test_framework import BitcoinTestFramework - from test_framework.util import ( assert_equal, initialize_chain_clean, start_nodes, stop_nodes, connect_nodes, + wait_bitcoinds ) -from test_framework.util import wait_bitcoinds - from test_framework.script import ( CScript, OP_HASH160, @@ -39,8 +35,11 @@ OP_DROP, ) -from test_framework.mininode import COIN, CTransaction -from test_framework.mininode import CTxIn, CTxOut, COutPoint +from test_framework.mininode import ( + COIN, + CTransaction, + CTxIn, CTxOut, COutPoint, +) from binascii import hexlify @@ -49,14 +48,18 @@ class AddressIndexTest(BitcoinTestFramework): def setup_chain(self): print("Initializing test directory "+self.options.tmpdir) - initialize_chain_clean(self.options.tmpdir, 3) + initialize_chain_clean(self.options.tmpdir, 4) def setup_network(self): # -insightexplorer causes addressindex to be enabled (fAddressIndex = true) - args = ('-debug', '-txindex', '-experimentalfeatures', '-insightexplorer') - self.nodes = start_nodes(3, self.options.tmpdir, [args] * 3) + args_insight = ('-debug', '-txindex', '-experimentalfeatures', '-insightexplorer') + # -lightwallet also causes addressindex to be enabled + args_lightwallet = ('-debug', '-txindex', '-experimentalfeatures', '-lightwalletd') + self.nodes = start_nodes(4, self.options.tmpdir, [args_insight] * 3 + [args_lightwallet]) + connect_nodes(self.nodes[0], 1) connect_nodes(self.nodes[0], 2) + connect_nodes(self.nodes[0], 3) # node3 is only for testing lightwalletd self.is_network_split = False self.sync_all() @@ -101,7 +104,7 @@ def check_balance(node_index, address, expected_balance, expected_received=None) assert_equal(self.nodes[1].getbalance(), 0) # only the oldest 5; subsequent are not yet mature - unspent_txids = [ u['txid'] for u in self.nodes[0].listunspent() ] + unspent_txids = [u['txid'] for u in self.nodes[0].listunspent()] # Currently our only unspents are coinbase transactions, choose any one tx = self.nodes[0].getrawtransaction(unspent_txids[0], 1) @@ -123,6 +126,9 @@ def check_balance(node_index, address, expected_balance, expected_received=None) assert_equal(len(self.nodes[1].getaddresstxids(addr_p2pkh)), 105) assert_equal(len(self.nodes[1].getaddresstxids(addr_p2sh)), 105) + # test getaddresstxids for lightwalletd + assert_equal(len(self.nodes[3].getaddresstxids(addr_p2pkh)), 105) + assert_equal(len(self.nodes[3].getaddresstxids(addr_p2sh)), 105) # only the oldest 5 transactions are in the unspent list, # dup addresses are ignored @@ -184,6 +190,9 @@ def check_balance(node_index, address, expected_balance, expected_received=None) # check that duplicate addresses are processed correctly mempool = self.nodes[0].getaddressmempool({'addresses': [addr2, addr1, addr2]}) assert_equal(len(mempool), 3) + # test getaddressmempool for lightwalletd node + mempool = self.nodes[3].getaddressmempool({'addresses': [addr2, addr1, addr2]}) + assert_equal(len(mempool), 3) # addr2 (first arg) assert_equal(mempool[0]['address'], addr2) @@ -201,7 +210,13 @@ def check_balance(node_index, address, expected_balance, expected_received=None) assert_equal(mempool[2]['txid'], txid) # a single address can be specified as a string (not json object) - assert_equal([mempool[1]], self.nodes[0].getaddressmempool(addr1)) + addr1_mempool = self.nodes[0].getaddressmempool(addr1) + assert_equal(len(addr1_mempool), 1) + # Don't check the timestamp; it's local to the node, and can mismatch + # due to propagation delay. + del addr1_mempool[0]['timestamp'] + for key in addr1_mempool[0].keys(): + assert_equal(mempool[1][key], addr1_mempool[0][key]) tx = self.nodes[0].getrawtransaction(txid, 1) assert_equal(tx['vin'][0]['address'], addr1) @@ -256,8 +271,12 @@ def check_balance(node_index, address, expected_balance, expected_received=None) tx = self.nodes[0].getrawtransaction(txid, 1) change_vout = filter(lambda v: v['valueZat'] != 3 * COIN, tx['vout']) change = change_vout[0]['scriptPubKey']['addresses'][0] - bal = self.nodes[2].getaddressbalance(change) - assert(bal['received'] > 0) + + # test getaddressbalance + for node in (2, 3): + bal = self.nodes[node].getaddressbalance(change) + assert(bal['received'] > 0) + # the inequality is due to randomness in the tx fee assert(bal['received'] < (4 - 3) * COIN) assert_equal(bal['received'], bal['balance']) @@ -286,13 +305,15 @@ def check_balance(node_index, address, expected_balance, expected_received=None) # set(txids_all) removes its (expected) duplicates assert_equal(set(multitxids), set(txids_all)) - deltas = self.nodes[1].getaddressdeltas({'addresses': [addr1]}) - assert_equal(len(deltas), len(expected_deltas)) - for i in range(len(deltas)): - assert_equal(deltas[i]['address'], addr1) - assert_equal(deltas[i]['height'], expected_deltas[i]['height']) - assert_equal(deltas[i]['satoshis'], expected_deltas[i]['satoshis']) - assert_equal(deltas[i]['txid'], expected_deltas[i]['txid']) + # test getaddressdeltas + for node in (1, 3): + deltas = self.nodes[node].getaddressdeltas({'addresses': [addr1]}) + assert_equal(len(deltas), len(expected_deltas)) + for i in range(len(deltas)): + assert_equal(deltas[i]['address'], addr1) + assert_equal(deltas[i]['height'], expected_deltas[i]['height']) + assert_equal(deltas[i]['satoshis'], expected_deltas[i]['satoshis']) + assert_equal(deltas[i]['txid'], expected_deltas[i]['txid']) # 106-111 is the full range (also the default) deltas_limited = getaddressdeltas(1, [addr1], 106, 111) diff --git a/qa/rpc-tests/bip65-cltv-p2p.py b/qa/rpc-tests/bip65-cltv-p2p.py index 254c075c3..c2091cc0c 100755 --- a/qa/rpc-tests/bip65-cltv-p2p.py +++ b/qa/rpc-tests/bip65-cltv-p2p.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . # @@ -66,7 +66,9 @@ def invalidate_transaction(self, tx): def get_tests(self): self.coinbase_blocks = self.nodes[0].generate(1) self.nodes[0].generate(100) - self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0) + hashTip = self.nodes[0].getbestblockhash() + hashFinalSaplingRoot = int("0x" + self.nodes[0].getblock(hashTip)['finalsaplingroot'] + "L", 0) + self.tip = int ("0x" + hashTip + "L", 0) self.nodeaddress = self.nodes[0].getnewaddress() '''Check that the rules are enforced.''' @@ -83,7 +85,8 @@ def get_tests(self): self.block_bits = int("0x" + gbt["bits"], 0) block = create_block(self.tip, create_coinbase(101), - self.block_time, self.block_bits) + self.block_time, self.block_bits, + hashFinalSaplingRoot) block.nVersion = 4 block.vtx.append(spendtx) block.hashMerkleRoot = block.calc_merkle_root() diff --git a/qa/rpc-tests/bipdersig-p2p.py b/qa/rpc-tests/bipdersig-p2p.py index 7eca0404d..ab0bed143 100755 --- a/qa/rpc-tests/bipdersig-p2p.py +++ b/qa/rpc-tests/bipdersig-p2p.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . # @@ -73,7 +73,9 @@ def invalidate_transaction(self, tx): def get_tests(self): self.coinbase_blocks = self.nodes[0].generate(1) self.nodes[0].generate(100) - self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0) + hashTip = self.nodes[0].getbestblockhash() + hashFinalSaplingRoot = int("0x" + self.nodes[0].getblock(hashTip)['finalsaplingroot'] + "L", 0) + self.tip = int ("0x" + hashTip + "L", 0) self.nodeaddress = self.nodes[0].getnewaddress() '''Check that the rules are enforced.''' @@ -90,7 +92,8 @@ def get_tests(self): self.block_bits = int("0x" + gbt["bits"], 0) block = create_block(self.tip, create_coinbase(101), - self.block_time, self.block_bits) + self.block_time, self.block_bits, + hashFinalSaplingRoot) block.nVersion = 4 block.vtx.append(spendtx) block.hashMerkleRoot = block.calc_merkle_root() diff --git a/qa/rpc-tests/finalsaplingroot.py b/qa/rpc-tests/finalsaplingroot.py index 3d37edd4e..1fa918767 100755 --- a/qa/rpc-tests/finalsaplingroot.py +++ b/qa/rpc-tests/finalsaplingroot.py @@ -31,8 +31,6 @@ def setup_chain(self): def setup_network(self, split=False): self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[[ - '-nuparams=5ba81b19:100', # Overwinter - '-nuparams=76b809bb:200', # Sapling '-txindex' # Avoid JSONRPC error: No information available about transaction ]] * 4 ) connect_nodes_bi(self.nodes,0,1) @@ -43,16 +41,12 @@ def setup_network(self, split=False): self.sync_all() def run_test(self): - # Activate Overwinter and Sapling self.nodes[0].generate(200) self.sync_all() - # Verfify genesis block contains null field for what is now called the final sapling root field. + # Verify genesis block contains null field for what is now called the final sapling root field. blk = self.nodes[0].getblock("0") assert_equal(blk["finalsaplingroot"], NULL_FIELD) - - - treestate = self.nodes[0].z_gettreestate("0") assert_equal(treestate["height"], 0) assert_equal(treestate["hash"], self.nodes[0].getblockhash(0)) @@ -67,8 +61,6 @@ def run_test(self): assert("finalState" not in treestate["sapling"]) assert("skipHash" not in treestate["sapling"]) - - # Verify all generated blocks contain the empty root of the Sapling tree. blockcount = self.nodes[0].getblockcount() for height in xrange(1, blockcount + 1): @@ -109,9 +101,6 @@ def run_test(self): result = self.nodes[0].getrawtransaction(mytxid, 1) assert_equal(len(result["vShieldedOutput"]), 1) - - - # Since there is a now sapling shielded input in the blockchain, # the sapling values should have changed new_treestate = self.nodes[0].z_gettreestate(str(-1)) @@ -123,9 +112,6 @@ def run_test(self): assert_equal(len(new_treestate["sapling"]["commitments"]["finalState"]), 70) treestate = new_treestate - - - # Mine an empty block and verify the final Sapling root does not change self.sync_all() self.nodes[0].generate(1) @@ -159,9 +145,6 @@ def run_test(self): assert_equal(self.nodes[1].z_getbalance(zaddr1), Decimal("10")) assert_equal(root, self.nodes[0].getblock("204")["finalsaplingroot"]) - - - new_treestate = self.nodes[0].z_gettreestate(str(-1)) assert_equal(new_treestate["sapling"]["commitments"]["finalRoot"], root) assert_equal(new_treestate["sapling"], treestate["sapling"]) @@ -171,10 +154,6 @@ def run_test(self): assert_equal(len(new_treestate["sprout"]["commitments"]["finalState"]), 134) treestate = new_treestate - - - - # Mine a block with a Sapling shielded recipient and verify the final Sapling root changes saplingAddr1 = self.nodes[1].z_getnewaddress("sapling") recipients = [] @@ -194,8 +173,6 @@ def run_test(self): result = self.nodes[0].getrawtransaction(mytxid, 1) assert_equal(len(result["vShieldedOutput"]), 2) # there is Sapling shielded change - - new_treestate = self.nodes[0].z_gettreestate(str(-1)) assert_equal(new_treestate["sprout"], treestate["sprout"]) assert(new_treestate["sapling"]["commitments"]["finalRoot"] != treestate["sapling"]["commitments"]["finalRoot"]) @@ -204,9 +181,6 @@ def run_test(self): assert_equal(len(new_treestate["sapling"]["commitments"]["finalState"]), 136) treestate = new_treestate - - - # Mine a block with a Sapling shielded sender and transparent recipient and verify the final Sapling root doesn't change taddr2 = self.nodes[0].getnewaddress() recipients = [] @@ -225,13 +199,10 @@ def run_test(self): root = blk["finalsaplingroot"] assert_equal(root, self.nodes[0].getblock("205")["finalsaplingroot"]) - - new_treestate = self.nodes[0].z_gettreestate(str(-1)) assert_equal(new_treestate["sprout"], treestate["sprout"]) assert_equal(new_treestate["sapling"], treestate["sapling"]) - if __name__ == '__main__': FinalSaplingRootTest().main() diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 311ef743a..09da3d810 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -66,7 +66,7 @@ def run_test(self): rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enought inputs + assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enough inputs ############################## # simple test with two coins # @@ -190,8 +190,8 @@ def run_test(self): outputs = { self.nodes[0].getnewaddress() : 1.0 } rawtx = self.nodes[2].createrawtransaction(inputs, outputs) - # 4-byte version + 1-byte vin count + 36-byte prevout then script_len - rawtx = rawtx[:82] + "0100" + rawtx[84:] + # 4-byte version + 4-byte versionGroupId + 1-byte vin count + 36-byte prevout then script_len + rawtx = rawtx[:90] + "0100" + rawtx[92:] dec_tx = self.nodes[2].decoderawtransaction(rawtx) assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py index 11e2c1385..360b2c6f5 100755 --- a/qa/rpc-tests/httpbasics.py +++ b/qa/rpc-tests/httpbasics.py @@ -100,5 +100,18 @@ def run_test(self): assert_equal('"error":null' in out1, True) assert_equal(conn.sock!=None, True) # connection must be closed because bitcoind should use keep-alive by default + # Check excessive request size + conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port) + conn.connect() + conn.request('GET', '/' + ('x'*1000), '', headers) + out1 = conn.getresponse().read() + assert_equal(out1.status, NOT_FOUND) + + conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port) + conn.connect() + conn.request('GET', '/' + ('x'*10000), '', headers) + out1 = conn.getresponse().read() + assert_equal(out1.status, BAD_REQUEST) + if __name__ == '__main__': HTTPBasicsTest().main() diff --git a/qa/rpc-tests/invalidblockrequest.py b/qa/rpc-tests/invalidblockrequest.py index d27feccd6..80124fddf 100755 --- a/qa/rpc-tests/invalidblockrequest.py +++ b/qa/rpc-tests/invalidblockrequest.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . # diff --git a/qa/rpc-tests/maxblocksinflight.py b/qa/rpc-tests/maxblocksinflight.py index c56cd608c..51210defe 100755 --- a/qa/rpc-tests/maxblocksinflight.py +++ b/qa/rpc-tests/maxblocksinflight.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . # diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py new file mode 100644 index 000000000..918c61414 --- /dev/null +++ b/qa/rpc-tests/mempool_limit.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python +# Copyright (c) 2019 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . + +import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, + get_coinbase_address, + fail, + initialize_chain_clean, + start_nodes, + wait_and_assert_operationid_status, +) + +from decimal import Decimal +from time import sleep + +# Test wallet behaviour with Sapling addresses +class MempoolLimit(BitcoinTestFramework): + def setup_chain(self): + print("Initializing test directory " + self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 4) + + def setup_nodes(self): + extra_args = [ + ["-debug=mempool", '-mempooltxcostlimit=8000'], # 2 transactions at min cost + ["-debug=mempool", '-mempooltxcostlimit=8000'], # 2 transactions at min cost + ["-debug=mempool", '-mempooltxcostlimit=8000'], # 2 transactions at min cost + # Let node 3 hold one more transaction + ["-debug=mempool", '-mempooltxcostlimit=12000'], # 3 transactions at min cost + ] + return start_nodes(4, self.options.tmpdir, extra_args) + + def check_mempool_sizes(self, expected_size, check_node3=True): + for i in range(4 if check_node3 else 3): + mempool = self.nodes[i].getrawmempool() + if len(mempool) != expected_size: + # print all nodes' mempools before failing + for i in range(4): + print("Mempool for node {}: {}".format(i, mempool)) + fail("Fail: Mempool for node {}: size={}, expected={}".format(i, len(mempool), expected_size)) + + def run_test(self): + print("Mining blocks...") + self.sync_all() + self.nodes[1].generate(1) + self.sync_all() + self.nodes[2].generate(1) + self.sync_all() + self.nodes[3].generate(1) + self.sync_all() + self.nodes[0].generate(100) + self.sync_all() + assert_equal(Decimal("10.00"), Decimal(self.nodes[1].z_gettotalbalance()['transparent'])) + assert_equal(Decimal("10.00"), Decimal(self.nodes[2].z_gettotalbalance()['transparent'])) + assert_equal(Decimal("10.00"), Decimal(self.nodes[3].z_gettotalbalance()['transparent'])) + + zaddr1 = self.nodes[0].z_getnewaddress('sapling') + zaddr2 = self.nodes[0].z_getnewaddress('sapling') + zaddr3 = self.nodes[0].z_getnewaddress('sapling') + + print("Filling mempool...") + opid1 = self.nodes[1].z_sendmany(get_coinbase_address(self.nodes[1]), [{"address": zaddr1, "amount": Decimal('9.999')}]) + wait_and_assert_operationid_status(self.nodes[1], opid1) + opid2 = self.nodes[2].z_sendmany(get_coinbase_address(self.nodes[2]), [{"address": zaddr2, "amount": Decimal('9.999')}]) + wait_and_assert_operationid_status(self.nodes[2], opid2) + self.sync_all() + + self.check_mempool_sizes(2) + + print("Adding one more transaction...") + opid3 = self.nodes[3].z_sendmany(get_coinbase_address(self.nodes[3]), [{"address": zaddr3, "amount": Decimal('9.999')}]) + wait_and_assert_operationid_status(self.nodes[3], opid3) + # The mempools are no longer guaranteed to be in a consistent state, so we cannot sync + sleep(5) + mempool_node3 = self.nodes[3].getrawmempool() + assert_equal(3, len(mempool_node3), "node {}".format(3)) + + print("Checking mempool size...") + # Due to the size limit, there should only be 2 transactions in the mempool + self.check_mempool_sizes(2, False) + + self.nodes[3].generate(1) + self.sync_all() + + # The mempool sizes should be reset + print("Checking mempool size reset after block mined...") + self.check_mempool_sizes(0) + zaddr4 = self.nodes[0].z_getnewaddress('sapling') + opid4 = self.nodes[0].z_sendmany(zaddr1, [{"address": zaddr4, "amount": Decimal('9.998')}]) + wait_and_assert_operationid_status(self.nodes[0], opid4) + opid5 = self.nodes[0].z_sendmany(zaddr2, [{"address": zaddr4, "amount": Decimal('9.998')}]) + wait_and_assert_operationid_status(self.nodes[0], opid5) + self.sync_all() + + self.check_mempool_sizes(2) + + # Make sure the transactions are mined without error + self.nodes[3].generate(1) + self.sync_all() + + +if __name__ == '__main__': + MempoolLimit().main() diff --git a/qa/rpc-tests/mempool_nu_activation.py b/qa/rpc-tests/mempool_nu_activation.py index 20d435f95..ab6a1ff6f 100755 --- a/qa/rpc-tests/mempool_nu_activation.py +++ b/qa/rpc-tests/mempool_nu_activation.py @@ -13,8 +13,6 @@ get_coinbase_address ) -from test_framework.authproxy import JSONRPCException - from decimal import Decimal # Test mempool behaviour around network upgrade activation @@ -24,9 +22,7 @@ class MempoolUpgradeActivationTest(BitcoinTestFramework): def setup_network(self): args = ["-checkmempool", "-debug=mempool", "-blockmaxsize=4000", - "-nuparams=5ba81b19:200", # Overwinter - "-nuparams=76b809bb:210", # Sapling - "-nuparams=2bb40e60:220", # Blossom + "-nuparams=2bb40e60:200", # Blossom ] self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir, args)) @@ -45,23 +41,24 @@ def run_test(self): # Mine 97 blocks. After this, nodes[1] blocks # 1 to 97 are spend-able. - self.nodes[0].generate(97) + self.nodes[0].generate(94) self.sync_all() # Shield some ZEC node1_taddr = get_coinbase_address(self.nodes[1]) - node0_zaddr = self.nodes[0].z_getnewaddress('sprout') + node0_zaddr = self.nodes[0].z_getnewaddress('sapling') recipients = [{'address': node0_zaddr, 'amount': Decimal('10')}] myopid = self.nodes[1].z_sendmany(node1_taddr, recipients, 1, Decimal('0')) print wait_and_assert_operationid_status(self.nodes[1], myopid) self.sync_all() + self.nodes[0].generate(1) + self.sync_all() # Mempool checks for activation of upgrade Y at height H on base X def nu_activation_checks(): - # Mine block H - 2. After this, the mempool expects - # block H - 1, which is the last X block. - self.nodes[0].generate(1) - self.sync_all() + # Start at block H - 5. After this, the mempool expects block H - 4, which is + # the last height at which we can create transactions for X blocks (due to the + # expiring-soon restrictions). # Mempool should be empty. assert_equal(set(self.nodes[0].getrawmempool()), set()) @@ -69,40 +66,64 @@ def nu_activation_checks(): # Check node 0 shielded balance assert_equal(self.nodes[0].z_getbalance(node0_zaddr), Decimal('10')) - # Fill the mempool with twice as many transactions as can fit into blocks + # Fill the mempool with more transactions than can fit into 4 blocks node0_taddr = self.nodes[0].getnewaddress() x_txids = [] - info = self.nodes[0].getblockchaininfo() - chaintip_branchid = info["consensus"]["chaintip"] - while self.nodes[1].getmempoolinfo()['bytes'] < 2 * 4000: - try: - x_txids.append(self.nodes[1].sendtoaddress(node0_taddr, Decimal('0.001'))) - - except JSONRPCException: - # This fails due to expiring soon threshold, which applies from Overwinter onwards. - upgrade_name = info["upgrades"][chaintip_branchid]["name"] - assert_true(upgrade_name in ("Overwinter", "Sapling"), upgrade_name) - break + while self.nodes[1].getmempoolinfo()['bytes'] < 8 * 4000: + x_txids.append(self.nodes[1].sendtoaddress(node0_taddr, Decimal('0.001'))) self.sync_all() # Spends should be in the mempool x_mempool = set(self.nodes[0].getrawmempool()) assert_equal(x_mempool, set(x_txids)) + assert_equal(set(self.nodes[1].getrawmempool()), set(x_txids)) + + blocks = [] + + # Mine block H - 4. After this, the mempool expects + # block H - 3, which is an X block. + self.nodes[0].generate(1) + self.sync_all() + blocks.append(self.nodes[0].getblock(self.nodes[0].getbestblockhash())['tx']) + + # mempool should not be empty. + assert_true(len(set(self.nodes[0].getrawmempool())) > 0) + assert_true(len(set(self.nodes[1].getrawmempool())) > 0) + + # Mine block H - 3. After this, the mempool expects + # block H - 2, which is an X block. + self.nodes[0].generate(1) + self.sync_all() + blocks.append(self.nodes[0].getblock(self.nodes[0].getbestblockhash())['tx']) + + # mempool should not be empty. + assert_true(len(set(self.nodes[0].getrawmempool())) > 0) + assert_true(len(set(self.nodes[1].getrawmempool())) > 0) + + # Mine block H - 2. After this, the mempool expects + # block H - 1, which is an X block. + self.nodes[0].generate(1) + self.sync_all() + blocks.append(self.nodes[0].getblock(self.nodes[0].getbestblockhash())['tx']) + + # mempool should not be empty. + assert_true(len(set(self.nodes[0].getrawmempool())) > 0) + assert_true(len(set(self.nodes[1].getrawmempool())) > 0) # Mine block H - 1. After this, the mempool expects # block H, which is the first Y block. self.nodes[0].generate(1) self.sync_all() + blocks.append(self.nodes[0].getblock(self.nodes[0].getbestblockhash())['tx']) # mempool should be empty. assert_equal(set(self.nodes[0].getrawmempool()), set()) + assert_equal(set(self.nodes[1].getrawmempool()), set()) - # When transitioning from Sprout to Overwinter, where expiring soon threshold does not apply: - # Block H - 1 should contain a subset of the original mempool + # Blocks [H - 4..H - 1] should contain a subset of the original mempool # (with all other transactions having been dropped) - block_txids = self.nodes[0].getblock(self.nodes[0].getbestblockhash())['tx'] - if chaintip_branchid is "00000000": - assert(len(block_txids) < len(x_txids)) + assert(sum([len(block_txids) for block_txids in blocks]) < len(x_txids)) + for block_txids in blocks: for txid in block_txids[1:]: # Exclude coinbase assert(txid in x_txids) @@ -120,6 +141,7 @@ def nu_activation_checks(): # Spends should be in the mempool assert_equal(set(self.nodes[0].getrawmempool()), set(y_txids)) + assert_equal(set(self.nodes[1].getrawmempool()), set(y_txids)) # Node 0 note should be unspendable assert_equal(self.nodes[0].z_getbalance(node0_zaddr), Decimal('0')) @@ -138,6 +160,9 @@ def nu_activation_checks(): #assert_equal(set(self.nodes[0].getrawmempool()), set(block_txids[1:])) assert_equal(set(self.nodes[0].getrawmempool()), set()) + # Node 1's mempool is unaffected because it still considers block H - 1 valid. + assert_equal(set(self.nodes[1].getrawmempool()), set(y_txids)) + # Node 0 note should be spendable again assert_equal(self.nodes[0].z_getbalance(node0_zaddr), Decimal('10')) @@ -149,25 +174,10 @@ def nu_activation_checks(): self.nodes[1].generate(6) self.sync_all() - print('Testing Sprout -> Overwinter activation boundary') - # Current height = 197 - nu_activation_checks() - # Current height = 205 - - self.nodes[0].generate(2) - self.sync_all() - - print('Testing Overwinter -> Sapling activation boundary') - # Current height = 207 - nu_activation_checks() - # Current height = 215 - self.nodes[0].generate(2) - self.sync_all() - print('Testing Sapling -> Blossom activation boundary') - # Current height = 217 + # Current height = 195 nu_activation_checks() - # Current height = 225 + # Current height = 205 if __name__ == '__main__': MempoolUpgradeActivationTest().main() diff --git a/qa/rpc-tests/mempool_coinbase_spends.py b/qa/rpc-tests/mempool_reorg.py similarity index 70% rename from qa/rpc-tests/mempool_coinbase_spends.py rename to qa/rpc-tests/mempool_reorg.py index 6b9df7d35..dd966f07c 100644 --- a/qa/rpc-tests/mempool_coinbase_spends.py +++ b/qa/rpc-tests/mempool_reorg.py @@ -11,7 +11,8 @@ import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, start_node, connect_nodes +from test_framework.authproxy import JSONRPCException +from test_framework.util import assert_equal, assert_raises, start_node, connect_nodes # Create one-input, one-output, no-fee transaction: @@ -51,16 +52,25 @@ def run_test(self): # 3. Indirect (coinbase and child both in chain) : spend_103 and spend_103_1 # Use invalidatblock to make all of the above coinbase spends invalid (immature coinbase), # and make sure the mempool code behaves correctly. - b = [ self.nodes[0].getblockhash(n) for n in range(102, 105) ] + b = [ self.nodes[0].getblockhash(n) for n in range(101, 105) ] coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ] - spend_101_raw = self.create_tx(coinbase_txids[0], node1_address, 12500) - spend_102_raw = self.create_tx(coinbase_txids[1], node0_address, 12500) - spend_103_raw = self.create_tx(coinbase_txids[2], node0_address, 12500) + spend_101_raw = self.create_tx(coinbase_txids[1], node1_address, 12500) + spend_102_raw = self.create_tx(coinbase_txids[2], node0_address, 12500) + spend_103_raw = self.create_tx(coinbase_txids[3], node0_address, 12500) + + # Create a block-height-locked transaction which will be invalid after reorg + timelock_tx = self.nodes[0].createrawtransaction([{"txid": coinbase_txids[0], "vout": 0}], {node0_address: 10}) + # Set the time lock, ensuring we don't clobber the rest of the Sapling v4 tx format + timelock_tx = timelock_tx.replace("ffffffff", "11111111", 1) + timelock_tx = timelock_tx[:-38] + hex(self.nodes[0].getblockcount() + 2)[2:] + "000000" + timelock_tx[-30:] + timelock_tx = self.nodes[0].signrawtransaction(timelock_tx)["hex"] + assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, timelock_tx) # Broadcast and mine spend_102 and 103: spend_102_id = self.nodes[0].sendrawtransaction(spend_102_raw) spend_103_id = self.nodes[0].sendrawtransaction(spend_103_raw) self.nodes[0].generate(1) + assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, timelock_tx) # Create 102_1 and 103_1: spend_102_1_raw = self.create_tx(spend_102_id, node1_address, 12500) @@ -68,8 +78,8 @@ def run_test(self): # Broadcast and mine 103_1: spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw) - [spend_103_1_id] # hush pyflakes - self.nodes[0].generate(1) + last_block = self.nodes[0].generate(1) + timelock_tx_id = self.nodes[0].sendrawtransaction(timelock_tx) # ... now put spend_101 and spend_102_1 in memory pools: spend_101_id = self.nodes[0].sendrawtransaction(spend_101_raw) @@ -77,7 +87,11 @@ def run_test(self): self.sync_all() - assert_equal(set(self.nodes[0].getrawmempool()), set([ spend_101_id, spend_102_1_id ])) + assert_equal(set(self.nodes[0].getrawmempool()), set([ spend_101_id, spend_102_1_id, timelock_tx_id ])) + + for node in self.nodes: + node.invalidateblock(last_block[0]) + assert_equal(set(self.nodes[0].getrawmempool()), set([ spend_101_id, spend_102_1_id, spend_103_1_id ])) # Use invalidateblock to re-org back and make all those coinbase spends # immature/invalid: diff --git a/qa/rpc-tests/mempool_tx_expiry.py b/qa/rpc-tests/mempool_tx_expiry.py index 7d66fd0e9..04e24be7c 100755 --- a/qa/rpc-tests/mempool_tx_expiry.py +++ b/qa/rpc-tests/mempool_tx_expiry.py @@ -4,7 +4,7 @@ # file COPYING or https://www.opensource.org/licenses/mit-license.php . # -# Test proper expiry for transactions >= version 3 +# Test proper expiry for transactions >= version 4 # import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." @@ -17,7 +17,6 @@ from decimal import Decimal -SAPLING_ACTIVATION_HEIGHT = 300 TX_EXPIRING_SOON_THRESHOLD = 3 TX_EXPIRY_DELTA = 10 @@ -26,8 +25,6 @@ class MempoolTxExpiryTest(BitcoinTestFramework): def setup_nodes(self): return start_nodes(4, self.options.tmpdir, [[ - "-nuparams=5ba81b19:205", # Overwinter - "-nuparams=76b809bb:%d" % SAPLING_ACTIVATION_HEIGHT, # Sapling "-txexpirydelta=%d" % TX_EXPIRY_DELTA, "-debug=mempool" ]] * 4) @@ -40,22 +37,13 @@ def run_test(self): bob = self.nodes[2].getnewaddress() z_bob = self.nodes[2].z_getnewaddress('sapling') - # When Overwinter not yet activated, no expiryheight in tx - tx = self.nodes[0].sendtoaddress(bob, 0.01) - rawtx = self.nodes[0].getrawtransaction(tx, 1) - assert_equal(rawtx["overwintered"], False) - assert("expiryheight" not in rawtx) - - self.nodes[0].generate(6) - self.sync_all() - print "Splitting network..." self.split_network() - # When Overwinter is activated, test dependent txs + # Test dependent txs firstTx = self.nodes[0].sendtoaddress(alice, 0.1) firstTxInfo = self.nodes[0].getrawtransaction(firstTx, 1) - assert_equal(firstTxInfo["version"], 3) + assert_equal(firstTxInfo["version"], 4) assert_equal(firstTxInfo["overwintered"], True) assert("expiryheight" in firstTxInfo) print "First tx expiry height:", firstTxInfo['expiryheight'] @@ -88,12 +76,6 @@ def run_test(self): assert_equal(set(self.nodes[0].getrawmempool()), set()) assert_equal(set(self.nodes[2].getrawmempool()), set()) - # Activate Sapling - n = SAPLING_ACTIVATION_HEIGHT - self.nodes[0].getblockcount() - assert(n > 0) - self.nodes[0].generate(n) - self.sync_all() - ## Shield one of Alice's coinbase funds to her zaddr res = self.nodes[0].z_shieldcoinbase("*", z_alice, 0.0001, 1) wait_and_assert_operationid_status(self.nodes[0], res['opid']) @@ -130,7 +112,7 @@ def run_test(self): assert_equal(rawtx["overwintered"], True) assert_equal(rawtx["expiryheight"], blockheight + 1 + TX_EXPIRY_DELTA) - print "\n Blockheight advances to less than expiry block height. After reorg, txs should persist in mempool" + print "\nBlockheight advances to less than expiry block height. After reorg, txs should persist in mempool" assert(persist_transparent in self.nodes[0].getrawmempool()) assert(persist_shielded in self.nodes[0].getrawmempool()) assert_equal(set(self.nodes[2].getrawmempool()), set()) @@ -176,7 +158,7 @@ def run_test(self): print "Splitting network..." self.split_network() - print "\n Blockheight advances to equal expiry block height. After reorg, txs should persist in mempool" + print "\nBlockheight advances to equal expiry block height. After reorg, txs should persist in mempool" myopid = self.nodes[0].z_sendmany(z_alice, recipients) persist_shielded_2 = wait_and_assert_operationid_status(self.nodes[0], myopid) persist_transparent_2 = self.nodes[0].sendtoaddress(bob, 0.01) @@ -210,7 +192,7 @@ def run_test(self): print "Splitting network..." self.split_network() - print "\n Blockheight advances to greater than expiry block height. After reorg, txs should expire from mempool" + print "\nBlockheight advances to greater than expiry block height. After reorg, txs should expire from mempool" print "Balance before expire_shielded is sent: ", self.nodes[0].z_gettotalbalance() myopid = self.nodes[0].z_sendmany(z_alice, recipients) expire_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid) @@ -241,7 +223,7 @@ def run_test(self): print "Splitting network..." self.split_network() - print "\n Blockheight advances to just before expiring soon threshold. Txs should be rejected from entering mempool." + print "\nBlockheight advances to just before expiring soon threshold. Txs should be rejected from entering mempool." print "Balance before expire_shielded is sent: ", self.nodes[0].z_gettotalbalance() myopid = self.nodes[0].z_sendmany(z_alice, recipients) expire_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid) diff --git a/qa/rpc-tests/mempool_tx_input_limit.py b/qa/rpc-tests/mempool_tx_input_limit.py deleted file mode 100755 index 0e9ea786a..000000000 --- a/qa/rpc-tests/mempool_tx_input_limit.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2017 The Zcash developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or https://www.opensource.org/licenses/mit-license.php . - -import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." - -from test_framework.test_framework import BitcoinTestFramework -from test_framework.authproxy import JSONRPCException -from test_framework.util import assert_equal, initialize_chain_clean, \ - start_node, connect_nodes, wait_and_assert_operationid_status, \ - get_coinbase_address - -from decimal import Decimal - -# Test -mempooltxinputlimit -class MempoolTxInputLimitTest(BitcoinTestFramework): - - alert_filename = None # Set by setup_network - - def setup_network(self): - args = ["-checkmempool", "-debug=mempool", "-mempooltxinputlimit=2", "-nuparams=5ba81b19:110"] - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, args)) - self.nodes.append(start_node(1, self.options.tmpdir, args)) - connect_nodes(self.nodes[1], 0) - self.is_network_split = False - self.sync_all - - def setup_chain(self): - print "Initializing test directory "+self.options.tmpdir - initialize_chain_clean(self.options.tmpdir, 2) - - def call_z_sendmany(self, from_addr, to_addr, amount): - recipients = [] - recipients.append({"address": to_addr, "amount": amount}) - myopid = self.nodes[0].z_sendmany(from_addr, recipients) - return wait_and_assert_operationid_status(self.nodes[0], myopid) - - def run_test(self): - self.nodes[0].generate(100) - self.sync_all() - # Mine three blocks. After this, nodes[0] blocks - # 1, 2, and 3 are spend-able. - self.nodes[1].generate(3) - self.sync_all() - - # Check 1: z_sendmany is limited by -mempooltxinputlimit - - # Add zaddr to node 0 - node0_zaddr = self.nodes[0].z_getnewaddress('sprout') - - # Send three inputs from node 0 taddr to zaddr to get out of coinbase - node0_taddr = get_coinbase_address(self.nodes[0]) - recipients = [] - recipients.append({"address":node0_zaddr, "amount":Decimal('37500.0')-Decimal('0.0001')}) # utxo amount less fee - myopid = self.nodes[0].z_sendmany(node0_taddr, recipients) - - # Spend should fail due to -mempooltxinputlimit - wait_and_assert_operationid_status(self.nodes[0], myopid, "failed", "Too many transparent inputs 3 > limit 2", 120) - - # Mempool should be empty. - assert_equal(set(self.nodes[0].getrawmempool()), set()) - - # Reduce amount to only use two inputs - spend_zaddr_amount = Decimal('25000.0') - Decimal('0.0001') - spend_zaddr_id = self.call_z_sendmany(node0_taddr, node0_zaddr, spend_zaddr_amount) # utxo amount less fee - self.sync_all() - - # Spend should be in the mempool - assert_equal(set(self.nodes[0].getrawmempool()), set([ spend_zaddr_id ])) - - self.nodes[0].generate(1) - self.sync_all() - - # mempool should be empty. - assert_equal(set(self.nodes[0].getrawmempool()), set()) - - # Check 2: sendfrom is limited by -mempooltxinputlimit - recipients = [] - spend_taddr_amount = spend_zaddr_amount - Decimal('0.0001') - spend_taddr_output = Decimal('8') - - # Create three outputs - recipients.append({"address":self.nodes[1].getnewaddress(), "amount": spend_taddr_output}) - recipients.append({"address":self.nodes[1].getnewaddress(), "amount": spend_taddr_output}) - recipients.append({"address":self.nodes[1].getnewaddress(), "amount": spend_taddr_amount - spend_taddr_output - spend_taddr_output}) - - myopid = self.nodes[0].z_sendmany(node0_zaddr, recipients) - wait_and_assert_operationid_status(self.nodes[0], myopid) - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() - - # Should use three UTXOs and fail - try: - self.nodes[1].sendfrom("", node0_taddr, spend_taddr_amount - Decimal('1')) - assert(False) - except JSONRPCException,e: - msg = e.error['message'] - assert_equal("Too many transparent inputs 3 > limit 2", msg) - - # mempool should be empty. - assert_equal(set(self.nodes[1].getrawmempool()), set()) - - # Should use two UTXOs and succeed - spend_taddr_id2 = self.nodes[1].sendfrom("", node0_taddr, spend_taddr_output + spend_taddr_output - Decimal('1')) - - # Spend should be in the mempool - assert_equal(set(self.nodes[1].getrawmempool()), set([ spend_taddr_id2 ])) - - # Mine three blocks - self.nodes[1].generate(3) - self.sync_all() - # The next block to be mined, 109, is the last Sprout block - bci = self.nodes[0].getblockchaininfo() - assert_equal(bci['consensus']['chaintip'], '00000000') - assert_equal(bci['consensus']['nextblock'], '00000000') - - # z_sendmany should be limited by -mempooltxinputlimit - recipients = [] - recipients.append({"address":node0_zaddr, "amount":Decimal('30.0')-Decimal('0.0001')}) # utxo amount less fee - myopid = self.nodes[0].z_sendmany(node0_taddr, recipients) - wait_and_assert_operationid_status(self.nodes[0], myopid, 'failed', 'Too many transparent inputs 3 > limit 2') - - # Mine one block - self.nodes[1].generate(1) - self.sync_all() - # The next block to be mined, 110, is the first Overwinter block - bci = self.nodes[0].getblockchaininfo() - assert_equal(bci['consensus']['chaintip'], '00000000') - assert_equal(bci['consensus']['nextblock'], '5ba81b19') - - # z_sendmany should no longer be limited by -mempooltxinputlimit - myopid = self.nodes[0].z_sendmany(node0_taddr, recipients) - wait_and_assert_operationid_status(self.nodes[0], myopid) - -if __name__ == '__main__': - MempoolTxInputLimitTest().main() diff --git a/qa/rpc-tests/mergetoaddress_helper.py b/qa/rpc-tests/mergetoaddress_helper.py index 346b3c7fd..3369ebd9a 100755 --- a/qa/rpc-tests/mergetoaddress_helper.py +++ b/qa/rpc-tests/mergetoaddress_helper.py @@ -27,7 +27,7 @@ def assert_mergetoaddress_exception(expected_error_msg, merge_to_address_lambda) class MergeToAddressHelper: - def __init__(self, addr_type, any_zaddr, utxos_to_generate, utxos_in_tx1, utxos_in_tx2, test_mempooltxinputlimit): + def __init__(self, addr_type, any_zaddr, utxos_to_generate, utxos_in_tx1, utxos_in_tx2): self.addr_type = addr_type self.any_zaddr = [any_zaddr] self.any_zaddr_or_utxo = [any_zaddr, "ANY_TADDR"] @@ -35,19 +35,18 @@ def __init__(self, addr_type, any_zaddr, utxos_to_generate, utxos_in_tx1, utxos_ self.utxos_to_generate = utxos_to_generate self.utxos_in_tx1 = utxos_in_tx1 self.utxos_in_tx2 = utxos_in_tx2 - self.test_mempooltxinputlimit = test_mempooltxinputlimit def setup_chain(self, test): print("Initializing test directory "+test.options.tmpdir) initialize_chain_clean(test.options.tmpdir, 4) def setup_network(self, test, additional_args=[]): - args = ['-debug=zrpcunsafe', '-experimentalfeatures', '-zmergetoaddress'] + args = ['-debug=zrpcunsafe'] args += additional_args test.nodes = [] test.nodes.append(start_node(0, test.options.tmpdir, args)) test.nodes.append(start_node(1, test.options.tmpdir, args)) - args2 = ['-debug=zrpcunsafe', '-experimentalfeatures', '-zmergetoaddress', '-mempooltxinputlimit=7'] + args2 = ['-debug=zrpcunsafe'] args2 += additional_args test.nodes.append(start_node(2, test.options.tmpdir, args2)) connect_nodes_bi(test.nodes, 0, 1) @@ -283,16 +282,10 @@ def run_test(self, test): test.nodes[1].generate(1) test.sync_all() - # Verify maximum number of UTXOs which node 2 can shield is limited by option -mempooltxinputlimit - # This option is used when the limit parameter is set to 0. - - # -mempooltxinputlimit is not used after overwinter activation - if self.test_mempooltxinputlimit: - expected_to_merge = 7 - expected_remaining = 13 - else: - expected_to_merge = 20 - expected_remaining = 0 + # Verify maximum number of UTXOs which node 2 can shield is not limited + # when the limit parameter is set to 0. + expected_to_merge = 20 + expected_remaining = 0 result = test.nodes[2].z_mergetoaddress([n2taddr], myzaddr, Decimal('0.0001'), 0) assert_equal(result["mergingUTXOs"], expected_to_merge) @@ -326,9 +319,7 @@ def run_test(self, test): # Remaining notes are only counted if we are trying to merge any notes assert_equal(result["remainingNotes"], Decimal('0')) wait_and_assert_operationid_status(test.nodes[0], result['opid']) - # Don't sync node 2 which rejects the tx due to its mempooltxinputlimit - sync_blocks(test.nodes[:2]) - sync_mempools(test.nodes[:2]) + test.sync_all() test.nodes[1].generate(1) test.sync_all() diff --git a/qa/rpc-tests/mergetoaddress_mixednotes.py b/qa/rpc-tests/mergetoaddress_mixednotes.py index 1aa59db97..2ff03827f 100755 --- a/qa/rpc-tests/mergetoaddress_mixednotes.py +++ b/qa/rpc-tests/mergetoaddress_mixednotes.py @@ -15,11 +15,7 @@ class MergeToAddressMixedNotes(BitcoinTestFramework): def setup_nodes(self): - return start_nodes(4, self.options.tmpdir, [[ - '-nuparams=5ba81b19:100', # Overwinter - '-nuparams=76b809bb:100', # Sapling - '-experimentalfeatures', '-zmergetoaddress' - ]] * 4) + return start_nodes(4, self.options.tmpdir) def setup_chain(self): print("Initializing test directory " + self.options.tmpdir) diff --git a/qa/rpc-tests/mergetoaddress_sapling.py b/qa/rpc-tests/mergetoaddress_sapling.py index 72ca6929a..9c3c96e13 100755 --- a/qa/rpc-tests/mergetoaddress_sapling.py +++ b/qa/rpc-tests/mergetoaddress_sapling.py @@ -12,16 +12,13 @@ class MergeToAddressSapling (BitcoinTestFramework): # 13505 would be the maximum number of utxos based on the transaction size limits for Sapling # but testing this causes the test to take an indeterminately long time to run. - helper = MergeToAddressHelper('sapling', 'ANY_SAPLING', 800, 800, 0, False) + helper = MergeToAddressHelper('sapling', 'ANY_SAPLING', 800, 800, 0) def setup_chain(self): self.helper.setup_chain(self) def setup_network(self, split=False): - self.helper.setup_network(self, [ - '-nuparams=5ba81b19:100', # Overwinter - '-nuparams=76b809bb:100', # Sapling - ]) + self.helper.setup_network(self) def run_test(self): self.helper.run_test(self) diff --git a/qa/rpc-tests/mergetoaddress_sprout.py b/qa/rpc-tests/mergetoaddress_sprout.py index 8d3e2cbec..669606c1e 100755 --- a/qa/rpc-tests/mergetoaddress_sprout.py +++ b/qa/rpc-tests/mergetoaddress_sprout.py @@ -10,7 +10,9 @@ class MergeToAddressSprout (BitcoinTestFramework): - helper = MergeToAddressHelper('sprout', 'ANY_SPROUT', 800, 662, 138, True) + # 13505 would be the maximum number of utxos based on the transaction size limits for Sapling + # but testing this causes the test to take an indeterminately long time to run. + helper = MergeToAddressHelper('sprout', 'ANY_SPROUT', 800, 800, 0) def setup_chain(self): self.helper.setup_chain(self) diff --git a/qa/rpc-tests/merkle_blocks.py b/qa/rpc-tests/merkle_blocks.py index f6d1ce3d2..1f7cfa9b9 100755 --- a/qa/rpc-tests/merkle_blocks.py +++ b/qa/rpc-tests/merkle_blocks.py @@ -76,7 +76,7 @@ def run_test(self): txid_spent = txin_spent["txid"] txid_unspent = txid1 if txin_spent["txid"] != txid1 else txid2 - # We cant find the block from a fully-spent tx + # We can't find the block from a fully-spent tx assert_raises(JSONRPCException, self.nodes[2].gettxoutproof, [txid_spent]) # ...but we can if we specify the block assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid_spent], blockhash)), [txid_spent]) diff --git a/qa/rpc-tests/multi_rpc.py b/qa/rpc-tests/multi_rpc.py new file mode 100755 index 000000000..d9390afbf --- /dev/null +++ b/qa/rpc-tests/multi_rpc.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python2 +# Copyright (c) 2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . + +# +# Test mulitple rpc user config option rpcauth +# + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, + initialize_chain, + start_nodes, +) +import base64 +import os + +try: + import http.client as httplib +except ImportError: + import httplib +try: + import urllib.parse as urlparse +except ImportError: + import urlparse + +class HTTPBasicsTest (BitcoinTestFramework): + def setup_nodes(self): + return start_nodes(4, self.options.tmpdir) + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain(self.options.tmpdir) + #Append rpcauth to zcash.conf before initialization + rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144" + rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e" + with open(os.path.join(self.options.tmpdir+"/node0", "zcash.conf"), 'a') as f: + f.write(rpcauth+"\n") + f.write(rpcauth2+"\n") + + def run_test(self): + + ################################################## + # Check correctness of the rpcauth config option # + ################################################## + url = urlparse.urlparse(self.nodes[0].url) + + #Old authpair + authpair = url.username + ':' + url.password + + #New authpair generated via share/rpcuser tool + #rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144" + password = "cA773lm788buwYe4g4WT+05pKyNruVKjQ25x3n0DQcM=" + + #Second authpair with different username + #rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e" + password2 = "8/F3uMDw4KSEbw96U3CA1C4X05dkHDN2BPFjTgZW4KI=" + authpairnew = "rt:"+password + + headers = {"Authorization": "Basic " + base64.b64encode(authpair)} + + conn = httplib.HTTPConnection(url.hostname, url.port) + conn.connect() + conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) + resp = conn.getresponse() + assert_equal(resp.status==401, False) + conn.close() + + #Use new authpair to confirm both work + headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)} + + conn = httplib.HTTPConnection(url.hostname, url.port) + conn.connect() + conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) + resp = conn.getresponse() + assert_equal(resp.status==401, False) + conn.close() + + #Wrong login name with rt's password + authpairnew = "rtwrong:"+password + headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)} + + conn = httplib.HTTPConnection(url.hostname, url.port) + conn.connect() + conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) + resp = conn.getresponse() + assert_equal(resp.status==401, True) + conn.close() + + #Wrong password for rt + authpairnew = "rt:"+password+"wrong" + headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)} + + conn = httplib.HTTPConnection(url.hostname, url.port) + conn.connect() + conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) + resp = conn.getresponse() + assert_equal(resp.status==401, True) + conn.close() + + #Correct for rt2 + authpairnew = "rt2:"+password2 + headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)} + + conn = httplib.HTTPConnection(url.hostname, url.port) + conn.connect() + conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) + resp = conn.getresponse() + assert_equal(resp.status==401, False) + conn.close() + + #Wrong password for rt2 + authpairnew = "rt2:"+password2+"wrong" + headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)} + + conn = httplib.HTTPConnection(url.hostname, url.port) + conn.connect() + conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) + resp = conn.getresponse() + assert_equal(resp.status==401, True) + conn.close() + + + +if __name__ == '__main__': + HTTPBasicsTest ().main () diff --git a/qa/rpc-tests/nodehandling.py b/qa/rpc-tests/nodehandling.py index 7ab65f664..424583bfb 100755 --- a/qa/rpc-tests/nodehandling.py +++ b/qa/rpc-tests/nodehandling.py @@ -26,7 +26,7 @@ def run_test(self): ########################### assert_equal(len(self.nodes[2].getpeerinfo()), 4) #we should have 4 nodes at this point self.nodes[2].setban("127.0.0.1", "add") - time.sleep(3) #wait till the nodes are disconected + time.sleep(3) #wait till the nodes are disconnected assert_equal(len(self.nodes[2].getpeerinfo()), 0) #all nodes must be disconnected at this point assert_equal(len(self.nodes[2].listbanned()), 1) self.nodes[2].clearbanned() diff --git a/qa/rpc-tests/p2p-acceptblock.py b/qa/rpc-tests/p2p-acceptblock.py index 61474d516..054967b24 100755 --- a/qa/rpc-tests/p2p-acceptblock.py +++ b/qa/rpc-tests/p2p-acceptblock.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . # diff --git a/qa/rpc-tests/p2p_node_bloom.py b/qa/rpc-tests/p2p_node_bloom.py index dd8709c04..7c5a07b23 100755 --- a/qa/rpc-tests/p2p_node_bloom.py +++ b/qa/rpc-tests/p2p_node_bloom.py @@ -6,7 +6,7 @@ import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.mininode import NodeConn, NodeConnCB, NetworkThread, \ - msg_filteradd, msg_filterclear, mininode_lock, SPROUT_PROTO_VERSION + msg_filteradd, msg_filterclear, mininode_lock, SAPLING_PROTO_VERSION from test_framework.test_framework import BitcoinTestFramework from test_framework.util import initialize_chain_clean, start_nodes, \ p2p_port, assert_equal @@ -74,10 +74,10 @@ def run_test(self): # Verify mininodes are connected to zcashd nodes peerinfo = self.nodes[0].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(SPROUT_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) peerinfo = self.nodes[1].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(SPROUT_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) # Mininodes send filterclear message to zcashd node. nobf_node.send_message(msg_filterclear()) @@ -88,10 +88,10 @@ def run_test(self): # Verify mininodes are still connected to zcashd nodes peerinfo = self.nodes[0].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(SPROUT_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) peerinfo = self.nodes[1].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(SPROUT_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) # Mininodes send filteradd message to zcashd node. nobf_node.send_message(msg_filteradd()) @@ -102,10 +102,10 @@ def run_test(self): # Verify NoBF mininode has been dropped, and BF mininode is still connected. peerinfo = self.nodes[0].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(0, versions.count(SPROUT_PROTO_VERSION)) + assert_equal(0, versions.count(SAPLING_PROTO_VERSION)) peerinfo = self.nodes[1].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(SPROUT_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) [ c.disconnect_node() for c in connections ] diff --git a/qa/rpc-tests/p2p_txexpiringsoon.py b/qa/rpc-tests/p2p_txexpiringsoon.py index bd631a5ad..01fd90768 100755 --- a/qa/rpc-tests/p2p_txexpiringsoon.py +++ b/qa/rpc-tests/p2p_txexpiringsoon.py @@ -7,7 +7,7 @@ from test_framework.authproxy import JSONRPCException from test_framework.mininode import NodeConn, NetworkThread, CInv, \ - msg_mempool, msg_getdata, msg_tx, mininode_lock, OVERWINTER_PROTO_VERSION + msg_mempool, msg_getdata, msg_tx, mininode_lock, SAPLING_PROTO_VERSION from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, connect_nodes_bi, fail, \ initialize_chain_clean, p2p_port, start_nodes, sync_blocks, sync_mempools @@ -23,8 +23,7 @@ def setup_chain(self): initialize_chain_clean(self.options.tmpdir, 3) def setup_network(self): - self.nodes = start_nodes(3, self.options.tmpdir, - extra_args=[['-nuparams=5ba81b19:10']] * 3) + self.nodes = start_nodes(3, self.options.tmpdir) connect_nodes_bi(self.nodes, 0, 1) # We don't connect node 2 @@ -85,7 +84,7 @@ def run_test(self): testnode0 = TestNode() connections = [] connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], - testnode0, "regtest", OVERWINTER_PROTO_VERSION)) + testnode0, "regtest", SAPLING_PROTO_VERSION)) testnode0.add_connection(connections[0]) # Start up network handling in another thread @@ -95,7 +94,7 @@ def run_test(self): # Verify mininodes are connected to zcashd nodes peerinfo = self.nodes[0].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(OVERWINTER_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) assert_equal(0, peerinfo[0]["banscore"]) # Mine some blocks so we can spend @@ -150,7 +149,7 @@ def run_test(self): # Set up test node for node 2 testnode2 = TestNode() connections.append(NodeConn('127.0.0.1', p2p_port(2), self.nodes[2], - testnode2, "regtest", OVERWINTER_PROTO_VERSION)) + testnode2, "regtest", SAPLING_PROTO_VERSION)) testnode2.add_connection(connections[-1]) # Verify block count diff --git a/qa/rpc-tests/p2p_txexpiry_dos.py b/qa/rpc-tests/p2p_txexpiry_dos.py index e51bf2cb6..633f00284 100755 --- a/qa/rpc-tests/p2p_txexpiry_dos.py +++ b/qa/rpc-tests/p2p_txexpiry_dos.py @@ -6,7 +6,7 @@ import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.mininode import NodeConn, NetworkThread, \ - msg_tx, OVERWINTER_PROTO_VERSION + msg_tx, SAPLING_PROTO_VERSION from test_framework.test_framework import BitcoinTestFramework from test_framework.util import initialize_chain_clean, start_nodes, \ p2p_port, assert_equal @@ -22,15 +22,14 @@ def setup_chain(self): initialize_chain_clean(self.options.tmpdir, 1) def setup_network(self): - self.nodes = start_nodes(1, self.options.tmpdir, - extra_args=[['-nuparams=5ba81b19:10']]) + self.nodes = start_nodes(1, self.options.tmpdir) def run_test(self): test_node = TestNode() connections = [] connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], - test_node, "regtest", OVERWINTER_PROTO_VERSION)) + test_node, "regtest", SAPLING_PROTO_VERSION)) test_node.add_connection(connections[0]) # Start up network handling in another thread @@ -41,7 +40,7 @@ def run_test(self): # Verify mininodes are connected to zcashd nodes peerinfo = self.nodes[0].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(OVERWINTER_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) assert_equal(0, peerinfo[0]["banscore"]) coinbase_blocks = self.nodes[0].generate(1) @@ -62,7 +61,7 @@ def run_test(self): # and still has a banscore of 0. peerinfo = self.nodes[0].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(OVERWINTER_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) assert_equal(0, peerinfo[0]["banscore"]) # Mine a block and resend the transaction @@ -75,7 +74,7 @@ def run_test(self): # but has a banscore of 10. peerinfo = self.nodes[0].getpeerinfo() versions = [x["version"] for x in peerinfo] - assert_equal(1, versions.count(OVERWINTER_PROTO_VERSION)) + assert_equal(1, versions.count(SAPLING_PROTO_VERSION)) assert_equal(10, peerinfo[0]["banscore"]) [c.disconnect_node() for c in connections] diff --git a/qa/rpc-tests/proxy_test.py b/qa/rpc-tests/proxy_test.py index 8db56c5cb..503445666 100755 --- a/qa/rpc-tests/proxy_test.py +++ b/qa/rpc-tests/proxy_test.py @@ -5,13 +5,13 @@ import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." -from test_framework.socks5 import Socks5Configuration, Socks5Command, Socks5Server, AddressType -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, start_nodes - import socket import os +from test_framework.socks5 import Socks5Configuration, Socks5Command, Socks5Server, AddressType +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal, start_nodes +from test_framework.netutil import test_ipv6_local ''' Test plan: - Start bitcoind's with different proxy configurations @@ -38,6 +38,7 @@ class ProxyTest(BitcoinTestFramework): def __init__(self): + self.have_ipv6 = test_ipv6_local() # Create two proxies on different ports # ... one unauthenticated self.conf1 = Socks5Configuration() @@ -49,29 +50,36 @@ def __init__(self): self.conf2.addr = ('127.0.0.1', 14000 + (os.getpid() % 1000)) self.conf2.unauth = True self.conf2.auth = True - # ... one on IPv6 with similar configuration - self.conf3 = Socks5Configuration() - self.conf3.af = socket.AF_INET6 - self.conf3.addr = ('::1', 15000 + (os.getpid() % 1000)) - self.conf3.unauth = True - self.conf3.auth = True + if self.have_ipv6: + # ... one on IPv6 with similar configuration + self.conf3 = Socks5Configuration() + self.conf3.af = socket.AF_INET6 + self.conf3.addr = ('::1', 15000 + (os.getpid() % 1000)) + self.conf3.unauth = True + self.conf3.auth = True + else: + print "Warning: testing without local IPv6 support" self.serv1 = Socks5Server(self.conf1) self.serv1.start() self.serv2 = Socks5Server(self.conf2) self.serv2.start() - self.serv3 = Socks5Server(self.conf3) - self.serv3.start() + if self.have_ipv6: + self.serv3 = Socks5Server(self.conf3) + self.serv3.start() def setup_nodes(self): # Note: proxies are not used to connect to local nodes # this is because the proxy to use is based on CService.GetNetwork(), which return NET_UNROUTABLE for localhost - return start_nodes(4, self.options.tmpdir, extra_args=[ + args = [ ['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'], ['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'], ['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'], - ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion'] - ]) + [] + ] + if self.have_ipv6: + args[3] = ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion'] + return start_nodes(4, self.options.tmpdir, extra_args=args) def node_test(self, node, proxies, auth, test_onion=True): rv = [] @@ -88,18 +96,19 @@ def node_test(self, node, proxies, auth, test_onion=True): assert_equal(cmd.password, None) rv.append(cmd) - # Test: outgoing IPv6 connection through node - node.addnode("[1233:3432:2434:2343:3234:2345:6546:4534]:5443", "onetry") - cmd = proxies[1].queue.get() - assert(isinstance(cmd, Socks5Command)) - # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6 - assert_equal(cmd.atyp, AddressType.DOMAINNAME) - assert_equal(cmd.addr, "1233:3432:2434:2343:3234:2345:6546:4534") - assert_equal(cmd.port, 5443) - if not auth: - assert_equal(cmd.username, None) - assert_equal(cmd.password, None) - rv.append(cmd) + if self.have_ipv6: + # Test: outgoing IPv6 connection through node + node.addnode("[1233:3432:2434:2343:3234:2345:6546:4534]:5443", "onetry") + cmd = proxies[1].queue.get() + assert(isinstance(cmd, Socks5Command)) + # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6 + assert_equal(cmd.atyp, AddressType.DOMAINNAME) + assert_equal(cmd.addr, "1233:3432:2434:2343:3234:2345:6546:4534") + assert_equal(cmd.port, 5443) + if not auth: + assert_equal(cmd.username, None) + assert_equal(cmd.password, None) + rv.append(cmd) if test_onion: # Test: outgoing onion connection through node @@ -139,10 +148,11 @@ def run_test(self): rv = self.node_test(self.nodes[2], [self.serv2, self.serv2, self.serv2, self.serv2], True) # Check that credentials as used for -proxyrandomize connections are unique credentials = set((x.username,x.password) for x in rv) - assert_equal(len(credentials), 4) + assert_equal(len(credentials), len(rv)) - # proxy on IPv6 localhost - self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False, False) + if self.have_ipv6: + # proxy on IPv6 localhost + self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False, False) def networks_dict(d): r = {} @@ -171,11 +181,12 @@ def networks_dict(d): assert_equal(n2[net]['proxy_randomize_credentials'], True) assert_equal(n2['onion']['reachable'], True) - n3 = networks_dict(self.nodes[3].getnetworkinfo()) - for net in ['ipv4','ipv6']: - assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr)) - assert_equal(n3[net]['proxy_randomize_credentials'], False) - assert_equal(n3['onion']['reachable'], False) + if self.have_ipv6: + n3 = networks_dict(self.nodes[3].getnetworkinfo()) + for net in ['ipv4','ipv6']: + assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr)) + assert_equal(n3[net]['proxy_randomize_credentials'], False) + assert_equal(n3['onion']['reachable'], False) if __name__ == '__main__': ProxyTest().main() diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py index f10011f9f..7e8dae4b5 100755 --- a/qa/rpc-tests/pruning.py +++ b/qa/rpc-tests/pruning.py @@ -154,7 +154,7 @@ def reorg_test(self): print "Invalidating block at height:",invalidheight,badhash self.nodes[1].invalidateblock(badhash) - # We've now switched to our previously mined-24 block fork on node 1, but thats not what we want + # We've now switched to our previously mined-24 block fork on node 1, but that's not what we want # So invalidate that fork as well, until we're on the same chain as node 0/2 (but at an ancestor 288 blocks ago) mainchainhash = self.nodes[0].getblockhash(invalidheight - 1) curhash = self.nodes[1].getblockhash(invalidheight - 1) @@ -212,7 +212,7 @@ def reorg_back(self): goalbesthash = self.mainchainhash2 # As of 0.10 the current block download logic is not able to reorg to the original chain created in - # create_chain_with_stale_blocks because it doesn't know of any peer thats on that chain from which to + # create_chain_with_stale_blocks because it doesn't know of any peer that's on that chain from which to # redownload its missing blocks. # Invalidate the reorg_test chain in node 0 as well, it can successfully switch to the original chain # because it has all the block data. diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py index 6deaafad1..0dd779183 100755 --- a/qa/rpc-tests/rawtransactions.py +++ b/qa/rpc-tests/rawtransactions.py @@ -132,7 +132,7 @@ def run_test(self): break; bal = self.nodes[0].getbalance() - inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex']}] + inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "amount" : vout['value']}] outputs = { self.nodes[0].getnewaddress() : 2.199 } rawTx = self.nodes[2].createrawtransaction(inputs, outputs) rawTxPartialSigned = self.nodes[1].signrawtransaction(rawTx, inputs) diff --git a/qa/rpc-tests/receivedby.py b/qa/rpc-tests/receivedby.py index dcce3831f..83e20de4c 100755 --- a/qa/rpc-tests/receivedby.py +++ b/qa/rpc-tests/receivedby.py @@ -14,7 +14,7 @@ def get_sub_array_from_array(object_array, to_match): ''' Finds and returns a sub array from an array of arrays. - to_match should be a unique idetifier of a sub array + to_match should be a unique identifier of a sub array ''' for item in object_array: all_match = True diff --git a/qa/rpc-tests/regtest_signrawtransaction.py b/qa/rpc-tests/regtest_signrawtransaction.py index 4b2b524bc..acdba0397 100755 --- a/qa/rpc-tests/regtest_signrawtransaction.py +++ b/qa/rpc-tests/regtest_signrawtransaction.py @@ -6,16 +6,10 @@ import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import start_nodes, wait_and_assert_operationid_status +from test_framework.util import wait_and_assert_operationid_status class RegtestSignrawtransactionTest (BitcoinTestFramework): - def setup_nodes(self): - return start_nodes(4, self.options.tmpdir, [[ - "-nuparams=5ba81b19:200", # Overwinter - "-nuparams=76b809bb:206", # Sapling - ]] * 4) - def run_test(self): self.nodes[0].generate(1) self.sync_all() @@ -26,7 +20,7 @@ def run_test(self): self.nodes[0].generate(1) self.sync_all() - # Create and sign Overwinter transaction. + # Create and sign Sapling transaction. # If the incorrect consensus branch id is selected, there will be a signing error. opid = self.nodes[1].z_sendmany(taddr, [{'address': zaddr1, 'amount': 1}]) diff --git a/qa/rpc-tests/reindex.py b/qa/rpc-tests/reindex.py index c19d9c1f5..a9674d8ba 100755 --- a/qa/rpc-tests/reindex.py +++ b/qa/rpc-tests/reindex.py @@ -4,7 +4,7 @@ # file COPYING or https://www.opensource.org/licenses/mit-license.php . # -# Test -reindex with CheckBlockIndex +# Test -reindex and -reindex-chainstate with CheckBlockIndex # import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." @@ -13,6 +13,7 @@ from test_framework.util import assert_equal, initialize_chain_clean, \ start_node, stop_node, wait_bitcoinds +import time class ReindexTest(BitcoinTestFramework): @@ -25,13 +26,22 @@ def setup_network(self): self.is_network_split = False self.nodes.append(start_node(0, self.options.tmpdir)) - def run_test(self): + def reindex(self, justchainstate=False): self.nodes[0].generate(3) + blockcount = self.nodes[0].getblockcount() stop_node(self.nodes[0], 0) wait_bitcoinds() - self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug", "-reindex", "-checkblockindex=1"]) - assert_equal(self.nodes[0].getblockcount(), 3) + self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug", "-reindex-chainstate" if justchainstate else "-reindex", "-checkblockindex=1"]) + while self.nodes[0].getblockcount() < blockcount: + time.sleep(0.1) + assert_equal(self.nodes[0].getblockcount(), blockcount) print "Success" + def run_test(self): + self.reindex(False) + self.reindex(True) + self.reindex(False) + self.reindex(True) + if __name__ == '__main__': ReindexTest().main() diff --git a/qa/rpc-tests/rest.py b/qa/rpc-tests/rest.py index 63e9f0fa8..5c3f253fe 100755 --- a/qa/rpc-tests/rest.py +++ b/qa/rpc-tests/rest.py @@ -100,9 +100,9 @@ def run_test(self): n = vout['n'] - ###################################### - # GETUTXOS: query a unspent outpoint # - ###################################### + ####################################### + # GETUTXOS: query an unspent outpoint # + ####################################### json_request = '/checkmempool/'+txid+'-'+str(n) json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json') json_obj = json.loads(json_string) @@ -115,9 +115,9 @@ def run_test(self): assert_equal(json_obj['utxos'][0]['value'], 0.1) - ################################################ - # GETUTXOS: now query a already spent outpoint # - ################################################ + ################################################# + # GETUTXOS: now query an already spent outpoint # + ################################################# json_request = '/checkmempool/'+vintx+'-0' json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json') json_obj = json.loads(json_string) @@ -179,24 +179,24 @@ def run_test(self): json_request = '/'+txid+'-'+str(n) json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json') json_obj = json.loads(json_string) - assert_equal(len(json_obj['utxos']), 0) # there should be a outpoint because it has just added to the mempool + assert_equal(len(json_obj['utxos']), 0) # there should be an outpoint because it has just added to the mempool json_request = '/checkmempool/'+txid+'-'+str(n) json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json') json_obj = json.loads(json_string) - assert_equal(len(json_obj['utxos']), 1) # there should be a outpoint because it has just added to the mempool + assert_equal(len(json_obj['utxos']), 1) # there should be an outpoint because it has just added to the mempool # do some invalid requests json_request = '{"checkmempool' response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'json', json_request, True) - assert_equal(response.status, 500) # must be a 500 because we send a invalid json request + assert_equal(response.status, 500) # must be a 500 because we send an invalid json request json_request = '{"checkmempool' response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', json_request, True) - assert_equal(response.status, 500) # must be a 500 because we send a invalid bin request + assert_equal(response.status, 500) # must be a 500 because we send an invalid bin request response = http_post_call(url.hostname, url.port, '/rest/getutxos/checkmempool'+self.FORMAT_SEPARATOR+'bin', '', True) - assert_equal(response.status, 500) # must be a 500 because we send a invalid bin request + assert_equal(response.status, 500) # must be a 500 because we send an invalid bin request # test limits json_request = '/checkmempool/' diff --git a/qa/rpc-tests/rewind_index.py b/qa/rpc-tests/rewind_index.py index 9a30f393c..14ad3f86a 100755 --- a/qa/rpc-tests/rewind_index.py +++ b/qa/rpc-tests/rewind_index.py @@ -11,6 +11,8 @@ import time +FAKE_SPROUT = ['-nuparams=5ba81b19:210', '-nuparams=76b809bb:220'] +FAKE_OVERWINTER = ['-nuparams=5ba81b19:10', '-nuparams=76b809bb:220'] class RewindBlockIndexTest (BitcoinTestFramework): @@ -22,7 +24,11 @@ def setup_network(self, split=False): # Node 0 - Overwinter, then Sprout, then Overwinter again # Node 1 - Sprout # Node 2 - Overwinter - self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[['-nuparams=5ba81b19:10'], [], ['-nuparams=5ba81b19:10']]) + self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[ + FAKE_OVERWINTER, + FAKE_SPROUT, + FAKE_OVERWINTER, + ]) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -52,7 +58,7 @@ def run_test (self): print("Switching node 0 from Overwinter to Sprout") self.nodes[0].stop() bitcoind_processes[0].wait() - self.nodes[0] = start_node(0,self.options.tmpdir) + self.nodes[0] = start_node(0, self.options.tmpdir, extra_args=FAKE_SPROUT) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -69,7 +75,7 @@ def run_test (self): print("Switching node 0 from Sprout to Overwinter") self.nodes[0].stop() bitcoind_processes[0].wait() - self.nodes[0] = start_node(0,self.options.tmpdir, extra_args=['-nuparams=5ba81b19:10']) + self.nodes[0] = start_node(0, self.options.tmpdir, extra_args=FAKE_OVERWINTER) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) diff --git a/qa/rpc-tests/script_test.py b/qa/rpc-tests/script_test.py index 433683231..58627b99d 100755 --- a/qa/rpc-tests/script_test.py +++ b/qa/rpc-tests/script_test.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . # diff --git a/qa/rpc-tests/shorter_block_times.py b/qa/rpc-tests/shorter_block_times.py index 7bbf3c618..58032f06f 100755 --- a/qa/rpc-tests/shorter_block_times.py +++ b/qa/rpc-tests/shorter_block_times.py @@ -20,8 +20,6 @@ class ShorterBlockTimes(BitcoinTestFramework): def setup_nodes(self): return start_nodes(4, self.options.tmpdir, [[ - #'-nuparams=5ba81b19:0', # Overwinter - #'-nuparams=76b809bb:0', # Sapling '-nuparams=2bb40e60:106', # Blossom ]] * 4) diff --git a/qa/rpc-tests/signrawtransaction_offline.py b/qa/rpc-tests/signrawtransaction_offline.py index a4478c3c4..f2e498815 100755 --- a/qa/rpc-tests/signrawtransaction_offline.py +++ b/qa/rpc-tests/signrawtransaction_offline.py @@ -13,7 +13,7 @@ def setup_chain(self): initialize_chain_clean(self.options.tmpdir, 2) def setup_network(self): - self.nodes = [ start_node(0, self.options.tmpdir, ["-nuparams=5ba81b19:10"]) ] + self.nodes = [ start_node(0, self.options.tmpdir, ["-nuparams=2bb40e60:10"]) ] self.is_network_split = False self.sync_all() @@ -22,7 +22,7 @@ def run_test(self): print "Mining blocks..." self.nodes[0].generate(101) - offline_node = start_node(1, self.options.tmpdir, ["-maxconnections=0", "-nuparams=5ba81b19:10"]) + offline_node = start_node(1, self.options.tmpdir, ["-maxconnections=0", "-nuparams=2bb40e60:10"]) self.nodes.append(offline_node) assert_equal(0, len(offline_node.getpeerinfo())) # make sure node 1 has no peers @@ -49,11 +49,11 @@ def run_test(self): pass # Passing in the consensus branch id resolves the issue for offline regtest nodes. - signed_tx = offline_node.signrawtransaction(create_hex, sign_inputs, privkeys, "ALL", "5ba81b19") + signed_tx = offline_node.signrawtransaction(create_hex, sign_inputs, privkeys, "ALL", "2bb40e60") # If we return the transaction hash, then we have have not thrown an error (success) online_tx_hash = self.nodes[0].sendrawtransaction(signed_tx['hex']) assert_true(len(online_tx_hash) > 0) if __name__ == '__main__': - SignOfflineTest().main() \ No newline at end of file + SignOfflineTest().main() diff --git a/qa/rpc-tests/signrawtransactions.py b/qa/rpc-tests/signrawtransactions.py index acb1cbfd8..622b18bf5 100755 --- a/qa/rpc-tests/signrawtransactions.py +++ b/qa/rpc-tests/signrawtransactions.py @@ -38,7 +38,6 @@ def successful_signing_test(self): outputs = {'tmJXomn8fhYy3AFqDEteifjHRMUdKtBuTGM': 0.1} - # rawTx = self.nodes[0].createrawtransaction(inputs, outputs) # Also test setting an expiry height of 0. rawTx = self.nodes[0].createrawtransaction(inputs, outputs, 0, 0) rawTxSigned = self.nodes[0].signrawtransaction(rawTx, inputs, privKeys) diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py index 073e7e86e..f2e95440a 100755 --- a/qa/rpc-tests/smartfees.py +++ b/qa/rpc-tests/smartfees.py @@ -17,7 +17,7 @@ from decimal import Decimal, ROUND_DOWN # Construct 2 trivial P2SH's and the ScriptSigs that spend them -# So we can create many many transactions without needing to spend +# So we can create many transactions without needing to spend # time signing. P2SH_1 = "2MySexEGVzZpRgNQ1JdjdP5bRETznm3roQ2" # P2SH of "OP_1 OP_DROP" P2SH_2 = "2NBdpwq8Aoo1EEKEXPNrKvr5xQr3M9UfcZA" # P2SH of "OP_2 OP_DROP" @@ -31,7 +31,7 @@ def satoshi_round(amount): def small_txpuzzle_randfee(from_node, conflist, unconflist, amount, min_fee, fee_increment): ''' Create and send a transaction with a random fee. - The transaction pays to a trival P2SH script, and assumes that its inputs + The transaction pays to a trivial P2SH script, and assumes that its inputs are of the same form. The function takes a list of confirmed outputs and unconfirmed outputs and attempts to use the confirmed list first for its inputs. diff --git a/qa/rpc-tests/spentindex.py b/qa/rpc-tests/spentindex.py index 13a71714f..3533ef425 100755 --- a/qa/rpc-tests/spentindex.py +++ b/qa/rpc-tests/spentindex.py @@ -2,25 +2,28 @@ # Copyright (c) 2020 The BitcoinZ Community # Copyright (c) 2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -# -# Test spentindex generation and fetching +# file COPYING or https://www.opensource.org/licenses/mit-license.php . # +# Test spentindex generation and fetching for insightexplorer import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.test_framework import BitcoinTestFramework from test_framework.authproxy import JSONRPCException -from test_framework.util import assert_equal -from test_framework.util import initialize_chain_clean -from test_framework.util import start_nodes, stop_nodes, connect_nodes -from test_framework.util import wait_bitcoinds -from test_framework.util import fail +from test_framework.util import ( + assert_equal, + initialize_chain_clean, + start_nodes, + stop_nodes, + connect_nodes, + wait_bitcoinds, + fail, +) from test_framework.mininode import COIN + class SpentIndexTest(BitcoinTestFramework): def setup_chain(self): @@ -30,7 +33,8 @@ def setup_chain(self): def setup_network(self): # -insightexplorer causes spentindex to be enabled (fSpentIndex = true) - self.nodes = start_nodes(3, self.options.tmpdir, + self.nodes = start_nodes( + 3, self.options.tmpdir, [['-debug', '-txindex', '-experimentalfeatures', '-insightexplorer']]*3) connect_nodes(self.nodes[0], 1) connect_nodes(self.nodes[0], 2) @@ -179,5 +183,6 @@ def run_test(self): assert_equal(len(out), 1) assert_equal(out[0]['address'], addr2) + if __name__ == '__main__': SpentIndexTest().main() diff --git a/qa/rpc-tests/sprout_sapling_migration.py b/qa/rpc-tests/sprout_sapling_migration.py index 29d045e9f..22fd158a6 100755 --- a/qa/rpc-tests/sprout_sapling_migration.py +++ b/qa/rpc-tests/sprout_sapling_migration.py @@ -52,10 +52,7 @@ def check_migration_status(node, destination_address, migration_state): class SproutSaplingMigration(BitcoinTestFramework): def setup_nodes(self): - # Activate overwinter/sapling on all nodes extra_args = [[ - '-nuparams=5ba81b19:100', # Overwinter - '-nuparams=76b809bb:100', # Sapling ]] * 4 # Add migration parameters to nodes[0] extra_args[0] = extra_args[0] + [ @@ -63,8 +60,8 @@ def setup_nodes(self): '-migrationdestaddress=' + SAPLING_ADDR, '-debug=zrpcunsafe' ] - assert_equal(5, len(extra_args[0])) - assert_equal(2, len(extra_args[1])) + assert_equal(3, len(extra_args[0])) + assert_equal(0, len(extra_args[1])) return start_nodes(4, self.options.tmpdir, extra_args) def setup_chain(self): @@ -168,6 +165,19 @@ def send_to_sprout_zaddr(self, tAddr, sproutAddr): self.sync_all() def run_test(self): + # Wallet RPCs that depend on accurate chain state are blocked while in IBD. This + # test starts from a clean chain state, so we need to mine a single block first to + # ensure that the chain tip's block time is within 24 hours of the current time. + # + # We mine 2 blocks because we need to make two transparent->Sprout spends below + # (to load Sprout addresses with funds), and `get_coinbase_address` only selects + # a coinbase address with spendable coins. If we only mined one block here and 100 + # below, the selected coinbase address would only have one coin (due to the way + # the `generate` RPC uses one address per call). + print("Mining blocks...") + self.nodes[0].generate(2) + self.sync_all() + # Check enabling via '-migration' and disabling via rpc check_migration_status(self.nodes[0], SAPLING_ADDR, ENABLED_NO_FUNDS) self.nodes[0].z_setmigration(False) @@ -175,8 +185,7 @@ def run_test(self): # 1. Test using self.nodes[0] which has the parameter print("Running test using '-migrationdestaddress'...") - print("Mining blocks...") - self.nodes[0].generate(101) + self.nodes[0].generate(99) self.sync_all() tAddr = get_coinbase_address(self.nodes[0]) diff --git a/qa/rpc-tests/test_framework/bignum.py b/qa/rpc-tests/test_framework/bignum.py index ddc00cf19..29658d4c6 100644 --- a/qa/rpc-tests/test_framework/bignum.py +++ b/qa/rpc-tests/test_framework/bignum.py @@ -4,7 +4,7 @@ # # This file is copied from python-bitcoinlib. # -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . # diff --git a/qa/rpc-tests/test_framework/blockstore.py b/qa/rpc-tests/test_framework/blockstore.py old mode 100644 new mode 100755 index fc157f718..4a8dc0992 --- a/qa/rpc-tests/test_framework/blockstore.py +++ b/qa/rpc-tests/test_framework/blockstore.py @@ -7,7 +7,7 @@ import sys import cStringIO -import dbm +import dbm.dumb as dbm class BlockStore(object): def __init__(self, datadir): diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py index e1b4321de..0f744d31e 100644 --- a/qa/rpc-tests/test_framework/blocktools.py +++ b/qa/rpc-tests/test_framework/blocktools.py @@ -1,6 +1,6 @@ # blocktools.py - utilities for manipulating blocks and transactions # -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . # @@ -8,7 +8,7 @@ from script import CScript, OP_0, OP_EQUAL, OP_HASH160 # Create a block (with regtest difficulty) -def create_block(hashprev, coinbase, nTime=None, nBits=None): +def create_block(hashprev, coinbase, nTime=None, nBits=None, hashFinalSaplingRoot=None): block = CBlock() if nTime is None: import time @@ -16,6 +16,8 @@ def create_block(hashprev, coinbase, nTime=None, nBits=None): else: block.nTime = nTime block.hashPrevBlock = hashprev + if hashFinalSaplingRoot is not None: + block.hashFinalSaplingRoot = hashFinalSaplingRoot if nBits is None: block.nBits = 0x200f0f0f # Will break after a difficulty adjustment... else: diff --git a/qa/rpc-tests/test_framework/comptool.py b/qa/rpc-tests/test_framework/comptool.py index a6ae9e623..153ded981 100755 --- a/qa/rpc-tests/test_framework/comptool.py +++ b/qa/rpc-tests/test_framework/comptool.py @@ -1,6 +1,6 @@ #!/usr/bin/env python2 # -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . # diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 5e3c25d3d..47067eb63 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -1,6 +1,6 @@ # mininode.py - Bitcoin P2P network half-a-node # -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . # # This python code was modified from ArtForz' public domain half-a-node, as @@ -355,8 +355,72 @@ def serialize(self): return r def __repr__(self): - return "CBlockLocator(nVersion=%i vHave=%s)" \ - % (self.nVersion, repr(self.vHave)) + return "CBlockLocator(nVersion=%i vHave=%r)" \ + % (self.nVersion, self.vHave) + + +class SpendDescription(object): + def __init__(self): + self.cv = None + self.anchor = None + self.nullifier = None + self.rk = None + self.zkproof = None + self.spendAuthSig = None + + def deserialize(self, f): + self.cv = deser_uint256(f) + self.anchor = deser_uint256(f) + self.nullifier = deser_uint256(f) + self.rk = deser_uint256(f) + self.zkproof = f.read(192) + self.spendAuthSig = f.read(64) + + def serialize(self): + r = "" + r += ser_uint256(self.cv) + r += ser_uint256(self.anchor) + r += ser_uint256(self.nullifier) + r += ser_uint256(self.rk) + r += self.zkproof + r += self.spendAuthSig + return r + + def __repr__(self): + return "SpendDescription(cv=%064x, anchor=%064x, nullifier=%064x, rk=%064x, zkproof=%064x, spendAuthSig=%064x)" \ + % (self.cv, self.anchor, self.nullifier, self.rk, self.zkproof, self.spendauthsig) + + +class OutputDescription(object): + def __init__(self): + self.cv = None + self.cmu = None + self.ephemeralKey = None + self.encCiphertext = None + self.outCiphertext = None + self.zkproof = None + + def deserialize(self, f): + self.cv = deser_uint256(f) + self.cmu = deser_uint256(f) + self.ephemeralKey = deser_uint256(f) + self.encCiphertext = f.read(580) + self.outCiphertext = f.read(80) + self.zkproof = f.read(192) + + def serialize(self): + r = "" + r += ser_uint256(self.cv) + r += ser_uint256(self.cmu) + r += ser_uint256(self.ephemeralKey) + r += self.encCiphertext + r += self.outCiphertext + r += self.zkproof + return r + + def __repr__(self): + return "OutputDescription(cv=%064x, cmu=%064x, ephemeralKey=%064x, encCiphertext=%064x, outCiphertext=%064x, zkproof=%064x)" \ + % (self.cv, self.cmu, self.ephemeralKey, self.encCiphertext, self.outCiphertext, self.zkproof) G1_PREFIX_MASK = 0x02 @@ -412,11 +476,11 @@ def ser_g2(self, p): return r def __repr__(self): - return "ZCProof(g_A=%s g_A_prime=%s g_B=%s g_B_prime=%s g_C=%s g_C_prime=%s g_K=%s g_H=%s)" \ - % (repr(self.g_A), repr(self.g_A_prime), - repr(self.g_B), repr(self.g_B_prime), - repr(self.g_C), repr(self.g_C_prime), - repr(self.g_K), repr(self.g_H)) + return "ZCProof(g_A=%r g_A_prime=%r g_B=%r g_B_prime=%r g_C=%r g_C_prime=%r g_K=%r g_H=%r)" \ + % (self.g_A, self.g_A_prime, + self.g_B, self.g_B_prime, + self.g_C, self.g_C_prime, + self.g_K, self.g_H) ZC_NUM_JS_INPUTS = 2 @@ -502,9 +566,9 @@ def serialize(self): return r def __repr__(self): - return "JSDescription(vpub_old=%i.%08i vpub_new=%i.%08i anchor=%064x onetimePubKey=%064x randomSeed=%064x proof=%s)" \ + return "JSDescription(vpub_old=%i.%08i vpub_new=%i.%08i anchor=%064x onetimePubKey=%064x randomSeed=%064x proof=%r)" \ % (self.vpub_old, self.vpub_new, self.anchor, - self.onetimePubKey, self.randomSeed, repr(self.proof)) + self.onetimePubKey, self.randomSeed, self.proof) class COutPoint(object): @@ -549,8 +613,8 @@ def serialize(self): return r def __repr__(self): - return "CTxIn(prevout=%s scriptSig=%s nSequence=%i)" \ - % (repr(self.prevout), binascii.hexlify(self.scriptSig), + return "CTxIn(prevout=%r scriptSig=%s nSequence=%i)" \ + % (self.prevout, binascii.hexlify(self.scriptSig), self.nSequence) @@ -578,16 +642,20 @@ def __repr__(self): class CTransaction(object): def __init__(self, tx=None): if tx is None: - self.fOverwintered = False - self.nVersion = 1 - self.nVersionGroupId = 0 + self.fOverwintered = True + self.nVersion = 4 + self.nVersionGroupId = SAPLING_VERSION_GROUP_ID self.vin = [] self.vout = [] self.nLockTime = 0 self.nExpiryHeight = 0 + self.valueBalance = 0 + self.shieldedSpends = [] + self.shieldedOutputs = [] self.vJoinSplit = [] self.joinSplitPubKey = None self.joinSplitSig = None + self.bindingSig = None self.sha256 = None self.hash = None else: @@ -598,9 +666,13 @@ def __init__(self, tx=None): self.vout = copy.deepcopy(tx.vout) self.nLockTime = tx.nLockTime self.nExpiryHeight = tx.nExpiryHeight + self.valueBalance = tx.valueBalance + self.shieldedSpends = copy.deepcopy(tx.shieldedSpends) + self.shieldedOutputs = copy.deepcopy(tx.shieldedOutputs) self.vJoinSplit = copy.deepcopy(tx.vJoinSplit) self.joinSplitPubKey = tx.joinSplitPubKey self.joinSplitSig = tx.joinSplitSig + self.bindingSig = tx.bindingSig self.sha256 = None self.hash = None @@ -614,19 +686,30 @@ def deserialize(self, f): isOverwinterV3 = (self.fOverwintered and self.nVersionGroupId == OVERWINTER_VERSION_GROUP_ID and self.nVersion == 3) + isSaplingV4 = (self.fOverwintered and + self.nVersionGroupId == SAPLING_VERSION_GROUP_ID and + self.nVersion == 4) self.vin = deser_vector(f, CTxIn) self.vout = deser_vector(f, CTxOut) self.nLockTime = struct.unpack("= 2: self.vJoinSplit = deser_vector(f, JSDescription) if len(self.vJoinSplit) > 0: self.joinSplitPubKey = deser_uint256(f) self.joinSplitSig = f.read(64) + if isSaplingV4 and not (len(self.shieldedSpends) == 0 and len(self.shieldedOutputs) == 0): + self.bindingSig = f.read(64) + self.sha256 = None self.hash = None @@ -635,6 +718,9 @@ def serialize(self): isOverwinterV3 = (self.fOverwintered and self.nVersionGroupId == OVERWINTER_VERSION_GROUP_ID and self.nVersion == 3) + isSaplingV4 = (self.fOverwintered and + self.nVersionGroupId == SAPLING_VERSION_GROUP_ID and + self.nVersion == 4) r = "" r += struct.pack("= 2: r += ser_vector(self.vJoinSplit) if len(self.vJoinSplit) > 0: r += ser_uint256(self.joinSplitPubKey) r += self.joinSplitSig + if isSaplingV4 and not (len(self.shieldedSpends) == 0 and len(self.shieldedOutputs) == 0): + r += self.bindingSig return r def rehash(self): @@ -670,14 +762,18 @@ def is_valid(self): def __repr__(self): r = ("CTransaction(fOverwintered=%r nVersion=%i nVersionGroupId=0x%08x " - "vin=%s vout=%s nLockTime=%i nExpiryHeight=%i" + "vin=%r vout=%r nLockTime=%i nExpiryHeight=%i " + "valueBalance=%i shieldedSpends=%r shieldedOutputs=%r" % (self.fOverwintered, self.nVersion, self.nVersionGroupId, - repr(self.vin), repr(self.vout), self.nLockTime, self.nExpiryHeight)) + self.vin, self.vout, self.nLockTime, self.nExpiryHeight, + self.valueBalance, self.shieldedSpends, self.shieldedOutputs)) if self.nVersion >= 2: - r += " vJoinSplit=%s" % repr(self.vJoinSplit) + r += " vJoinSplit=%r" % (self.vJoinSplit,) if len(self.vJoinSplit) > 0: r += " joinSplitPubKey=%064x joinSplitSig=%064x" \ (self.joinSplitPubKey, self.joinSplitSig) + if len(self.shieldedSpends) > 0 or len(self.shieldedOutputs) > 0: + r += " bindingSig=%064x" % (self.bindingSig,) r += ")" return r @@ -690,7 +786,7 @@ def __init__(self, header=None): self.nVersion = header.nVersion self.hashPrevBlock = header.hashPrevBlock self.hashMerkleRoot = header.hashMerkleRoot - self.hashReserved = header.hashReserved + self.hashFinalSaplingRoot = header.hashFinalSaplingRoot self.nTime = header.nTime self.nBits = header.nBits self.nNonce = header.nNonce @@ -703,7 +799,7 @@ def set_null(self): self.nVersion = 4 self.hashPrevBlock = 0 self.hashMerkleRoot = 0 - self.hashReserved = 0 + self.hashFinalSaplingRoot = 0 self.nTime = 0 self.nBits = 0 self.nNonce = 0 @@ -715,7 +811,7 @@ def deserialize(self, f): self.nVersion = struct.unpack(" 2**32 struct_size = 40 if is_64bits else 32 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) @@ -137,3 +138,18 @@ def addr_to_hex(addr): else: raise ValueError('Could not parse address %s' % addr) return binascii.hexlify(bytearray(addr)) + +def test_ipv6_local(): + ''' + Check for (local) IPv6 support. + ''' + import socket + # By using SOCK_DGRAM this will not actually make a connection, but it will + # fail if there is no route to IPv6 localhost. + have_ipv6 = True + try: + s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) + s.connect(('::1', 0)) + except socket.error: + have_ipv6 = False + return have_ipv6 diff --git a/qa/rpc-tests/test_framework/script.py b/qa/rpc-tests/test_framework/script.py old mode 100644 new mode 100755 index a5afe22a3..8c2c8c228 --- a/qa/rpc-tests/test_framework/script.py +++ b/qa/rpc-tests/test_framework/script.py @@ -3,7 +3,7 @@ # # This file is modified from python-bitcoinlib. # -# Distributed under the MIT/X11 software license, see the accompanying +# Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . # @@ -14,8 +14,6 @@ from __future__ import absolute_import, division, print_function, unicode_literals -from test_framework.mininode import CTransaction, CTxOut, hash256 - import sys bchr = chr bord = ord @@ -820,77 +818,3 @@ def GetSigOpCount(self, fAccurate): n += 20 lastOpcode = opcode return n - - -SIGHASH_ALL = 1 -SIGHASH_NONE = 2 -SIGHASH_SINGLE = 3 -SIGHASH_ANYONECANPAY = 0x80 - -def FindAndDelete(script, sig): - """Consensus critical, see FindAndDelete() in Satoshi codebase""" - r = b'' - last_sop_idx = sop_idx = 0 - skip = True - for (opcode, data, sop_idx) in script.raw_iter(): - if not skip: - r += script[last_sop_idx:sop_idx] - last_sop_idx = sop_idx - if script[sop_idx:sop_idx + len(sig)] == sig: - skip = True - else: - skip = False - if not skip: - r += script[last_sop_idx:] - return CScript(r) - - -def SignatureHash(script, txTo, inIdx, hashtype): - """Consensus-correct SignatureHash - - Returns (hash, err) to precisely match the consensus-critical behavior of - the SIGHASH_SINGLE bug. (inIdx is *not* checked for validity) - """ - HASH_ONE = b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' - - if inIdx >= len(txTo.vin): - return (HASH_ONE, "inIdx %d out of range (%d)" % (inIdx, len(txTo.vin))) - txtmp = CTransaction(txTo) - - for txin in txtmp.vin: - txin.scriptSig = b'' - txtmp.vin[inIdx].scriptSig = FindAndDelete(script, CScript([OP_CODESEPARATOR])) - - if (hashtype & 0x1f) == SIGHASH_NONE: - txtmp.vout = [] - - for i in range(len(txtmp.vin)): - if i != inIdx: - txtmp.vin[i].nSequence = 0 - - elif (hashtype & 0x1f) == SIGHASH_SINGLE: - outIdx = inIdx - if outIdx >= len(txtmp.vout): - return (HASH_ONE, "outIdx %d out of range (%d)" % (outIdx, len(txtmp.vout))) - - tmp = txtmp.vout[outIdx] - txtmp.vout = [] - for i in range(outIdx): - txtmp.vout.append(CTxOut()) - txtmp.vout.append(tmp) - - for i in range(len(txtmp.vin)): - if i != inIdx: - txtmp.vin[i].nSequence = 0 - - if hashtype & SIGHASH_ANYONECANPAY: - tmp = txtmp.vin[inIdx] - txtmp.vin = [] - txtmp.vin.append(tmp) - - s = txtmp.serialize() - s += struct.pack(b" 0: args.append("-connect=127.0.0.1:"+str(p2p_port(0))) bitcoind_processes[i] = subprocess.Popen(args) @@ -200,9 +204,13 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary= if binary is None: binary = os.getenv("BITCOIND", "bitcoind") args = [ binary, "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest" ] + args.extend([ + '-nuparams=5ba81b19:1', # Overwinter + '-nuparams=76b809bb:1', # Sapling + ]) if extra_args is not None: args.extend(extra_args) bitcoind_processes[i] = subprocess.Popen(args) - devnull = open("/dev/null", "w+") + devnull = open(os.devnull, "w+") if os.getenv("PYTHON_DEBUG", ""): print "start_node: bitcoind started, calling bitcoin-cli -rpcwait getblockcount" subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir] + @@ -410,7 +418,7 @@ def wait_and_assert_operationid_status_result(node, myopid, in_status='success', break time.sleep(1) - assert_true(result is not None, "timeout occured") + assert_true(result is not None, "timeout occurred") status = result['status'] debug = os.getenv("PYTHON_DEBUG", "") diff --git a/qa/rpc-tests/turnstile.py b/qa/rpc-tests/turnstile.py index 129a91ee5..31451d116 100755 --- a/qa/rpc-tests/turnstile.py +++ b/qa/rpc-tests/turnstile.py @@ -40,8 +40,6 @@ ) from decimal import Decimal -NUPARAMS_ARGS = ['-nuparams=5ba81b19:100', # Overwinter - '-nuparams=76b809bb:101'] # Sapling TURNSTILE_ARGS = ['-experimentalfeatures', '-developersetpoolsizezero'] @@ -52,8 +50,7 @@ def setup_chain(self): initialize_chain_clean(self.options.tmpdir, 3) def setup_network(self, split=False): - self.nodes = start_nodes(3, self.options.tmpdir, - extra_args=[NUPARAMS_ARGS] * 3) + self.nodes = start_nodes(3, self.options.tmpdir) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) self.is_network_split=False @@ -70,7 +67,7 @@ def assert_pool_balance(self, node, name, balance): # Helper method to start a single node with extra args and sync to the network def start_and_sync_node(self, index, args=[]): - self.nodes[index] = start_node(index, self.options.tmpdir, extra_args=NUPARAMS_ARGS + args) + self.nodes[index] = start_node(index, self.options.tmpdir, extra_args=args) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index fcf8ee131..dee944935 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -93,7 +93,7 @@ def run_test (self): # Catch an attempt to send a transaction with an absurdly high fee. # Send 1.0 from an utxo of value 10.0 but don't specify a change output, so then - # the change of 9.0 becomes the fee, which is greater than estimated fee of 0.0019. + # the change of 9.0 becomes the fee, which is greater than estimated fee of 0.0021. inputs = [] outputs = {} for utxo in node2utxos: @@ -109,7 +109,7 @@ def run_test (self): except JSONRPCException,e: errorString = e.error['message'] assert("absurdly high fees" in errorString) - assert("900000000 > 190000" in errorString) + assert("900000000 > 10000000" in errorString) # create both transactions txns_to_send = [] @@ -287,12 +287,16 @@ def run_test (self): myzaddr = self.nodes[0].z_getnewaddress('sprout') recipients = [] - num_t_recipients = 3000 + num_t_recipients = 1000 + num_z_recipients = 2100 amount_per_recipient = Decimal('0.00000001') errorString = '' for i in xrange(0,num_t_recipients): newtaddr = self.nodes[2].getnewaddress() recipients.append({"address":newtaddr, "amount":amount_per_recipient}) + for i in xrange(0,num_z_recipients): + newzaddr = self.nodes[2].z_getnewaddress('sprout') + recipients.append({"address":newzaddr, "amount":amount_per_recipient}) # Issue #2759 Workaround START # HTTP connection to node 0 may fall into a state, during the few minutes it takes to process @@ -303,47 +307,12 @@ def run_test (self): self.nodes[0].getinfo() # Issue #2759 Workaround END - try: - self.nodes[0].z_sendmany(myzaddr, recipients) - except JSONRPCException,e: - errorString = e.error['message'] - assert("Too many outputs, size of raw transaction" in errorString) - - recipients = [] - num_t_recipients = 2000 - num_z_recipients = 50 - amount_per_recipient = Decimal('0.00000001') - errorString = '' - for i in xrange(0,num_t_recipients): - newtaddr = self.nodes[2].getnewaddress() - recipients.append({"address":newtaddr, "amount":amount_per_recipient}) - for i in xrange(0,num_z_recipients): - newzaddr = self.nodes[2].z_getnewaddress('sprout') - recipients.append({"address":newzaddr, "amount":amount_per_recipient}) - - # Issue #2759 Workaround START - self.nodes[0].getinfo() - # Issue #2759 Workaround END - try: self.nodes[0].z_sendmany(myzaddr, recipients) except JSONRPCException,e: errorString = e.error['message'] assert("size of raw transaction would be larger than limit" in errorString) - recipients = [] - num_z_recipients = 100 - amount_per_recipient = Decimal('0.00000001') - errorString = '' - for i in xrange(0,num_z_recipients): - newzaddr = self.nodes[2].z_getnewaddress('sprout') - recipients.append({"address":newzaddr, "amount":amount_per_recipient}) - try: - self.nodes[0].z_sendmany(myzaddr, recipients) - except JSONRPCException,e: - errorString = e.error['message'] - assert("Invalid parameter, too many zaddr outputs" in errorString) - # add zaddr to node 2 myzaddr = self.nodes[2].z_getnewaddress('sprout') diff --git a/qa/rpc-tests/wallet_1941.py b/qa/rpc-tests/wallet_1941.py index aabc40e50..35d2d908a 100755 --- a/qa/rpc-tests/wallet_1941.py +++ b/qa/rpc-tests/wallet_1941.py @@ -23,14 +23,14 @@ def setup_chain(self): print("Initializing test directory "+self.options.tmpdir) initialize_chain_clean(self.options.tmpdir, 1) - # Start nodes with -regtestprotectcoinbase to set fCoinbaseMustBeProtected to true. + # Start nodes with -regtestshieldcoinbase to set fCoinbaseMustBeShielded to true. def setup_network(self, split=False): - self.nodes = start_nodes(1, self.options.tmpdir, extra_args=[['-regtestprotectcoinbase','-debug=zrpc']] ) + self.nodes = start_nodes(1, self.options.tmpdir, extra_args=[['-regtestshieldcoinbase','-debug=zrpc']] ) self.is_network_split=False def add_second_node(self): initialize_datadir(self.options.tmpdir, 1) - self.nodes.append(start_node(1, self.options.tmpdir, extra_args=['-regtestprotectcoinbase','-debug=zrpc'])) + self.nodes.append(start_node(1, self.options.tmpdir, extra_args=['-regtestshieldcoinbase','-debug=zrpc'])) self.nodes[1].setmocktime(starttime + 9000) connect_nodes_bi(self.nodes,0,1) self.sync_all() @@ -38,7 +38,7 @@ def add_second_node(self): def restart_second_node(self, extra_args=[]): self.nodes[1].stop() bitcoind_processes[1].wait() - self.nodes[1] = start_node(1, self.options.tmpdir, extra_args=['-regtestprotectcoinbase','-debug=zrpc'] + extra_args) + self.nodes[1] = start_node(1, self.options.tmpdir, extra_args=['-regtestshieldcoinbase','-debug=zrpc'] + extra_args) self.nodes[1].setmocktime(starttime + 9000) connect_nodes_bi(self.nodes, 0, 1) self.sync_all() @@ -67,6 +67,7 @@ def run_test (self): self.nodes[0].generate(1) self.nodes[0].setmocktime(starttime + 9000) self.nodes[0].generate(1) + self.sync_all() # Confirm the balance on node 0. resp = self.nodes[0].z_getbalance(myzaddr) diff --git a/qa/rpc-tests/wallet_addresses.py b/qa/rpc-tests/wallet_addresses.py index c9a6ab7c3..332bba15d 100755 --- a/qa/rpc-tests/wallet_addresses.py +++ b/qa/rpc-tests/wallet_addresses.py @@ -6,17 +6,11 @@ import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, start_nodes +from test_framework.util import assert_equal -# Test wallet address behaviour across network upgradesa\ +# Test wallet address behaviour across network upgrades\ class WalletAddressesTest(BitcoinTestFramework): - def setup_nodes(self): - return start_nodes(4, self.options.tmpdir, [[ - '-nuparams=5ba81b19:202', # Overwinter - '-nuparams=76b809bb:204', # Sapling - ]] * 4) - def run_test(self): def addr_checks(default_type): # Check default type, as well as explicit types @@ -38,41 +32,17 @@ def addr_checks(default_type): # Sanity-check the test harness assert_equal(self.nodes[0].getblockcount(), 200) - # Current height = 200 -> Sprout - # Default address type is Sapling - print "Testing height 200 (Sprout)" - addr_checks('sapling') - - self.nodes[0].generate(1) - self.sync_all() - - # Current height = 201 -> Sprout - # Default address type is Sapling - print "Testing height 201 (Sprout)" - addr_checks('sapling') - - self.nodes[0].generate(1) - self.sync_all() - - # Current height = 202 -> Overwinter - # Default address type is Sapling - print "Testing height 202 (Overwinter)" - addr_checks('sapling') - - self.nodes[0].generate(1) - self.sync_all() - - # Current height = 203 -> Overwinter + # Current height = 200 -> Sapling # Default address type is Sapling - print "Testing height 203 (Overwinter)" + print "Testing height 200 (Sapling)" addr_checks('sapling') self.nodes[0].generate(1) self.sync_all() - # Current height = 204 -> Sapling + # Current height = 201 -> Sapling # Default address type is Sapling - print "Testing height 204 (Sapling)" + print "Testing height 201 (Sapling)" addr_checks('sapling') if __name__ == '__main__': diff --git a/qa/rpc-tests/wallet_anchorfork.py b/qa/rpc-tests/wallet_anchorfork.py index 81c254713..69d0bcaee 100755 --- a/qa/rpc-tests/wallet_anchorfork.py +++ b/qa/rpc-tests/wallet_anchorfork.py @@ -8,7 +8,8 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, initialize_chain_clean, \ start_nodes, stop_nodes, connect_nodes_bi, \ - wait_and_assert_operationid_status, wait_bitcoinds, get_coinbase_address + wait_and_assert_operationid_status, wait_bitcoinds, get_coinbase_address, \ + sync_blocks, sync_mempools from decimal import Decimal class WalletAnchorForkTest (BitcoinTestFramework): @@ -17,9 +18,9 @@ def setup_chain(self): print("Initializing test directory "+self.options.tmpdir) initialize_chain_clean(self.options.tmpdir, 4) - # Start nodes with -regtestprotectcoinbase to set fCoinbaseMustBeProtected to true. + # Start nodes with -regtestshieldcoinbase to set fCoinbaseMustBeShielded to true. def setup_network(self, split=False): - self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[['-regtestprotectcoinbase', '-debug=zrpc']] * 3 ) + self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[['-regtestshieldcoinbase', '-debug=zrpc']] * 3 ) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -65,7 +66,7 @@ def run_test (self): # Relaunch nodes and partition network into two: # A: node 0 # B: node 1, 2 - self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[['-regtestprotectcoinbase', '-debug=zrpc']] * 3 ) + self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[['-regtestshieldcoinbase', '-debug=zrpc']] * 3 ) connect_nodes_bi(self.nodes,1,2) # Partition B, node 1 mines an empty block @@ -80,11 +81,16 @@ def run_test (self): # Partition A, node 0 mines a block with the transaction self.nodes[0].generate(1) + # Same as self.sync_all() but only for node 0 + sync_blocks(self.nodes[:1]) + sync_mempools(self.nodes[:1]) # Partition B, node 1 mines the same joinsplit transaction txid2 = self.nodes[1].sendrawtransaction(rawhex) assert_equal(txid, txid2) self.nodes[1].generate(1) + sync_blocks(self.nodes[1:]) + sync_mempools(self.nodes[1:]) # Check that Partition B is one block ahead and that they have different tips assert_equal(self.nodes[0].getblockcount() + 1, self.nodes[1].getblockcount()) @@ -95,7 +101,7 @@ def run_test (self): wait_bitcoinds() # Relaunch nodes and reconnect the entire network - self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[['-regtestprotectcoinbase', '-debug=zrpc']] * 3 ) + self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[['-regtestshieldcoinbase', '-debug=zrpc']] * 3 ) connect_nodes_bi(self.nodes,0, 1) connect_nodes_bi(self.nodes,1, 2) connect_nodes_bi(self.nodes,0, 2) diff --git a/qa/rpc-tests/wallet_changeaddresses.py b/qa/rpc-tests/wallet_changeaddresses.py index 746002734..2eb6de679 100755 --- a/qa/rpc-tests/wallet_changeaddresses.py +++ b/qa/rpc-tests/wallet_changeaddresses.py @@ -2,7 +2,7 @@ # Copyright (c) 2020 The BitcoinZ Community # Copyright (c) 2019 The Zcash developers # Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# file COPYING or https://www.opensource.org/licenses/mit-license.php . import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." @@ -28,8 +28,7 @@ def setup_network(self): args = [ '-nuparams=5ba81b19:1', # Overwinter '-nuparams=76b809bb:1', # Sapling - '-txindex', # Avoid JSONRPC error: No information available about transaction - '-experimentalfeatures', '-zmergetoaddress', + '-txindex' # Avoid JSONRPC error: No information available about transaction ] self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir, args)) @@ -50,8 +49,9 @@ def run_test(self): taddrSource = self.nodes[0].getnewaddress() for _ in range(6): recipients = [{"address": taddrSource, "amount": Decimal('2')}] - myopid = self.nodes[0].z_sendmany(midAddr, recipients, 1, 0) + myopid = self.nodes[0].z_sendmany(midAddr, recipients, 1, Decimal('0')) wait_and_assert_operationid_status(self.nodes[0], myopid) + self.sync_all() self.nodes[1].generate(1) self.sync_all() @@ -59,11 +59,11 @@ def check_change_taddr_reuse(target): recipients = [{"address": target, "amount": Decimal('1')}] # Send funds to recipient address twice - myopid = self.nodes[0].z_sendmany(taddrSource, recipients, 1, 0) + myopid = self.nodes[0].z_sendmany(taddrSource, recipients, 1, Decimal('0')) txid1 = wait_and_assert_operationid_status(self.nodes[0], myopid) self.nodes[1].generate(1) self.sync_all() - myopid = self.nodes[0].z_sendmany(taddrSource, recipients, 1, 0) + myopid = self.nodes[0].z_sendmany(taddrSource, recipients, 1, Decimal('0')) txid2 = wait_and_assert_operationid_status(self.nodes[0], myopid) self.nodes[1].generate(1) self.sync_all() diff --git a/qa/rpc-tests/wallet_db_flush.py b/qa/rpc-tests/wallet_db_flush.py new file mode 100644 index 000000000..8ad61fc9a --- /dev/null +++ b/qa/rpc-tests/wallet_db_flush.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +# Copyright (c) 2020 The Zcash developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . +# +# This test reproduces https://github.com/zcash/zcash/issues/4301 +# It takes an hour to run! +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, + bitcoind_processes, + initialize_chain_clean, + start_node, +) +import time + +class WalletDBFlush (BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 1) + + def start_node_with(self, index, extra_args=[]): + args = [ + "-nuparams=2bb40e60:1", # Blossom + "-nuparams=f5b9230b:2", # Heartwood + "-nurejectoldversions=false", + ] + return start_node(index, self.options.tmpdir, args + extra_args) + + def setup_network(self, split=False): + self.nodes = [] + self.nodes.append(self.start_node_with(0)) + self.is_network_split=False + self.sync_all() + + def run_test (self): + print("PLEASE NOTE: This test takes an hour to run!") + + # This test requires shielded funds in the local wallet so + # there is witness data, and the easiest way to get shielded + # funds is to mine (since Heartwood, mining reward can go to + # a zaddr), so first create a Sapling address to mine to. + zaddr = self.nodes[0].z_getnewaddress('sapling') + self.nodes[0].generate(2) + + self.nodes[0].stop() + bitcoind_processes[0].wait() + + print("Start mining to address ", zaddr) + self.nodes[0] = self.start_node_with(0, [ + "-mineraddress=%s" % zaddr, + ]) + self.nodes[0].generate(1) + self.sync_all() + self.nodes[0].stop() + bitcoind_processes[0].wait() + + # If you replace main.cpp:3129 DATABASE_WRITE_INTERVAL with + # 60 (seconds), then sleeptime here can be 80, and this test + # will fail (pre-PR) much faster. + sleeptime = 3620 # just over one hour (DATABASE_WRITE_INTERVAL) + + print("Restart, sleep {}, mine (pre-PR will flush bad wallet state)".format(sleeptime)) + self.nodes[0] = self.start_node_with(0, [ + "-mineraddress=%s" % zaddr, + ]) + assert_equal(self.nodes[0].z_getbalance(zaddr, 0), 5) + time.sleep(sleeptime) + self.nodes[0].generate(1) + self.sync_all() + self.nodes[0].stop() + bitcoind_processes[0].wait() + + print("Restart, generate, expect assert in CopyPreviousWitnesses") + self.nodes[0] = self.start_node_with(0, [ + "-mineraddress=%s" % zaddr, + ]) + self.nodes[0].generate(1) + self.sync_all() + self.nodes[0].stop() + +if __name__ == '__main__': + WalletDBFlush().main() diff --git a/qa/rpc-tests/wallet_import_export.py b/qa/rpc-tests/wallet_import_export.py index e4a6dd6a9..072a7e833 100755 --- a/qa/rpc-tests/wallet_import_export.py +++ b/qa/rpc-tests/wallet_import_export.py @@ -53,14 +53,14 @@ def run_test(self): assert_true(sapling_address0 in sapling_keys1) assert_true(sapling_address2 in sapling_keys1) - # make sure we have perserved the metadata + # make sure we have preserved the metadata for sapling_key0 in sapling_keys0.splitlines(): assert_true(sapling_key0 in sapling_keys1) # Helper functions def parse_wallet_file(dump_path): file_lines = open(dump_path, "r").readlines() - # We expect information about the HDSeed and fingerpring in the header + # We expect information about the HDSeed and fingerprint in the header assert_true("HDSeed" in file_lines[4], "Expected HDSeed") assert_true("fingerprint" in file_lines[4], "Expected fingerprint") seed_comment_line = file_lines[4][2:].split() # ["HDSeed=...", "fingerprint=..."] @@ -83,4 +83,4 @@ def parse_wallet_file_lines(file_lines, i): return ("".join(keys), i) if __name__ == '__main__': - WalletImportExportTest().main() \ No newline at end of file + WalletImportExportTest().main() diff --git a/qa/rpc-tests/wallet_listnotes.py b/qa/rpc-tests/wallet_listnotes.py index 9f9b09937..169d4be56 100755 --- a/qa/rpc-tests/wallet_listnotes.py +++ b/qa/rpc-tests/wallet_listnotes.py @@ -9,7 +9,6 @@ from test_framework.util import ( assert_equal, get_coinbase_address, - start_nodes, wait_and_assert_operationid_status, ) @@ -18,29 +17,21 @@ # Test wallet z_listunspent behaviour across network upgrades class WalletListNotes(BitcoinTestFramework): - def setup_nodes(self): - return start_nodes(4, self.options.tmpdir, [[ - '-nuparams=5ba81b19:202', # Overwinter - '-nuparams=76b809bb:214', # Sapling - ]] * 4) - def run_test(self): - # Current height = 200 -> Sprout + # Current height = 200 assert_equal(200, self.nodes[0].getblockcount()) sproutzaddr = self.nodes[0].z_getnewaddress('sprout') - - # test that we can create a sapling zaddr before sapling activates saplingzaddr = self.nodes[0].z_getnewaddress('sapling') # we've got lots of coinbase (taddr) but no shielded funds yet assert_equal(0, Decimal(self.nodes[0].z_gettotalbalance()['private'])) - - # Set current height to 201 -> Sprout + + # Set current height to 201 self.nodes[0].generate(1) self.sync_all() assert_equal(201, self.nodes[0].getblockcount()) - # Shield coinbase funds (must be a multiple of 10, no change allowed pre-sapling) + # Shield coinbase funds (must be a multiple of 10, no change allowed) receive_amount_10 = Decimal('10.0') - Decimal('0.0001') recipients = [{"address":sproutzaddr, "amount":receive_amount_10}] myopid = self.nodes[0].z_sendmany(get_coinbase_address(self.nodes[0]), recipients) @@ -70,8 +61,8 @@ def run_test(self): # Generate a block to confirm shield coinbase tx self.nodes[0].generate(1) self.sync_all() - - # Current height = 202 -> Overwinter. Default address type remains Sprout + + # Current height = 202 assert_equal(202, self.nodes[0].getblockcount()) # Send 1.0 (actually 0.9999) from sproutzaddr to a new zaddr @@ -108,12 +99,7 @@ def run_test(self): unspent_tx_filter = self.nodes[0].z_listunspent(0, 9999, False, [sproutzaddr]) assert_equal(1, len(unspent_tx_filter)) assert_equal(unspent_tx[1], unspent_tx_filter[0]) - - # Set current height to 204 -> Sapling - self.nodes[0].generate(12) - self.sync_all() - assert_equal(214, self.nodes[0].getblockcount()) - + # No funds in saplingzaddr yet assert_equal(0, len(self.nodes[0].z_listunspent(0, 9999, False, [saplingzaddr]))) diff --git a/qa/rpc-tests/wallet_listreceived.py b/qa/rpc-tests/wallet_listreceived.py index 0ab104c64..a3da3d8ef 100755 --- a/qa/rpc-tests/wallet_listreceived.py +++ b/qa/rpc-tests/wallet_listreceived.py @@ -7,7 +7,7 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, assert_true, assert_false -from test_framework.util import start_nodes, wait_and_assert_operationid_status +from test_framework.util import wait_and_assert_operationid_status from decimal import Decimal my_memo_str = 'c0ffee' # stay awake @@ -20,12 +20,6 @@ class ListReceivedTest (BitcoinTestFramework): - def setup_nodes(self): - return start_nodes(4, self.options.tmpdir, [[ - "-nuparams=5ba81b19:201", # Overwinter - "-nuparams=76b809bb:214", # Sapling - ]] * 4) - def generate_and_sync(self, new_height): current_height = self.nodes[0].getblockcount() assert(new_height > current_height) diff --git a/qa/rpc-tests/wallet_nullifiers.py b/qa/rpc-tests/wallet_nullifiers.py index 99d433585..f23c60121 100755 --- a/qa/rpc-tests/wallet_nullifiers.py +++ b/qa/rpc-tests/wallet_nullifiers.py @@ -124,10 +124,14 @@ def run_test (self): 'total': node3mined + zsendmany2notevalue, }) - # add node 1 address and node 2 viewing key to node 3 + # Add node 1 address and node 2 viewing key to node 3 myzvkey = self.nodes[2].z_exportviewingkey(myzaddr) self.nodes[3].importaddress(mytaddr1) - self.nodes[3].z_importviewingkey(myzvkey, 'whenkeyisnew', 1) + importvk_result = self.nodes[3].z_importviewingkey(myzvkey, 'whenkeyisnew', 1) + + # Check results of z_importviewingkey + assert_equal(importvk_result["type"], "sprout") + assert_equal(importvk_result["address"], myzaddr) # Check the address has been imported assert_equal(myzaddr in self.nodes[3].z_listaddresses(), False) @@ -135,7 +139,7 @@ def run_test (self): # Node 3 should see the same received notes as node 2; however, # some of the notes were change for node 2 but not for node 3. - # Aside from that the recieved notes should be the same. So, + # Aside from that the received notes should be the same. So, # group by txid and then check that all properties aside from # change are equal. node2Received = dict([r['txid'], r] for r in self.nodes[2].z_listreceivedbyaddress(myzaddr)) diff --git a/qa/rpc-tests/wallet_overwintertx.py b/qa/rpc-tests/wallet_overwintertx.py index 8915789bb..92b14d78f 100755 --- a/qa/rpc-tests/wallet_overwintertx.py +++ b/qa/rpc-tests/wallet_overwintertx.py @@ -6,9 +6,15 @@ import sys; assert sys.version_info < (3,), ur"This script does not run under Python 3. Please use Python 2.7.x." from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal, initialize_chain_clean, \ - start_nodes, connect_nodes_bi, wait_and_assert_operationid_status, \ - assert_greater_than, get_coinbase_address +from test_framework.util import ( + assert_equal, + assert_greater_than, + connect_nodes_bi, + get_coinbase_address, + initialize_chain_clean, + start_nodes, + wait_and_assert_operationid_status, +) from test_framework.authproxy import JSONRPCException from decimal import Decimal @@ -20,7 +26,11 @@ def setup_chain(self): initialize_chain_clean(self.options.tmpdir, 4) def setup_network(self, split=False): - self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[["-nuparams=5ba81b19:200", "-debug=zrpcunsafe", "-txindex"]] * 4 ) + self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[[ + "-nuparams=2bb40e60:200", + "-debug=zrpcunsafe", + "-txindex", + ]] * 4 ) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -31,9 +41,9 @@ def setup_network(self, split=False): def run_test (self): self.nodes[0].generate(100) self.sync_all() - self.nodes[1].generate(98) + self.nodes[1].generate(95) self.sync_all() - # Node 0 has reward from blocks 1 to 98 which are spendable. + # Node 0 has reward from blocks 1 to 95 which are spendable. taddr0 = get_coinbase_address(self.nodes[0]) taddr1 = self.nodes[1].getnewaddress() @@ -43,19 +53,12 @@ def run_test (self): zaddr3 = self.nodes[3].z_getnewaddress('sprout') # - # Currently at block 198. The next block to be mined 199 is a Sprout block + # Currently at block 195. The next block to be mined 196 is a Sapling block # bci = self.nodes[0].getblockchaininfo() - assert_equal(bci['consensus']['chaintip'], '00000000') - assert_equal(bci['consensus']['nextblock'], '00000000') - assert_equal(bci['upgrades']['5ba81b19']['status'], 'pending') - - # Cannot use the expiryheight parameter of createrawtransaction if Overwinter is not active in the next block - try: - self.nodes[0].createrawtransaction([], {}, 0, 99) - except JSONRPCException,e: - errorString = e.error['message'] - assert_equal("Invalid parameter, expiryheight can only be used if Overwinter is active when the transaction is mined" in errorString, True) + assert_equal(bci['consensus']['chaintip'], '76b809bb') + assert_equal(bci['consensus']['nextblock'], '76b809bb') + assert_equal(bci['upgrades']['2bb40e60']['status'], 'pending') # Node 0 sends transparent funds to Node 2 tsendamount = Decimal('1.0') @@ -75,8 +78,10 @@ def run_test (self): myopid = self.nodes[0].z_sendmany(taddr0, recipients) txid_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid) + # Skip over the three blocks prior to activation; no transactions can be mined + # in them due to the nearly-expiring restrictions. self.sync_all() - self.nodes[0].generate(1) + self.nodes[0].generate(4) self.sync_all() # Verify balance @@ -84,26 +89,26 @@ def run_test (self): assert_equal(self.nodes[2].getbalance(), Decimal('0.4999')) assert_equal(self.nodes[2].z_getbalance(zaddr2), zsendamount) - # Verify transaction versions are 1 or 2 (intended for Sprout) + # Verify transaction version is 4 (intended for Sapling+) result = self.nodes[0].getrawtransaction(txid_transparent, 1) - assert_equal(result["version"], 1) - assert_equal(result["overwintered"], False) + assert_equal(result["version"], 4) + assert_equal(result["overwintered"], True) result = self.nodes[0].getrawtransaction(txid_zsendmany, 1) - assert_equal(result["version"], 1) - assert_equal(result["overwintered"], False) + assert_equal(result["version"], 4) + assert_equal(result["overwintered"], True) result = self.nodes[0].getrawtransaction(txid_shielded, 1) - assert_equal(result["version"], 2) - assert_equal(result["overwintered"], False) + assert_equal(result["version"], 4) + assert_equal(result["overwintered"], True) # - # Currently at block 199. The next block to be mined 200 is an Overwinter block + # Currently at block 199. The next block to be mined 200 is a Blossom block # bci = self.nodes[0].getblockchaininfo() - assert_equal(bci['consensus']['chaintip'], '00000000') - assert_equal(bci['consensus']['nextblock'], '5ba81b19') - assert_equal(bci['upgrades']['5ba81b19']['status'], 'pending') + assert_equal(bci['consensus']['chaintip'], '76b809bb') + assert_equal(bci['consensus']['nextblock'], '2bb40e60') + assert_equal(bci['upgrades']['2bb40e60']['status'], 'pending') - # Test using expiryheight parameter of createrawtransaction when Overwinter is active in the next block + # Test using expiryheight parameter of createrawtransaction when Blossom is active in the next block errorString = "" try: self.nodes[0].createrawtransaction([], {}, 0, 499999999) @@ -144,7 +149,7 @@ def run_test (self): myopid = self.nodes[0].z_sendmany(taddr0, recipients) txid_shielded = wait_and_assert_operationid_status(self.nodes[0], myopid) - # Mine the first Overwinter block + # Mine the first Blossom block self.sync_all() self.nodes[0].generate(1) self.sync_all() @@ -153,28 +158,28 @@ def run_test (self): # size_on_disk should be > 0 assert_greater_than(bci['size_on_disk'], 0) - assert_equal(bci['consensus']['chaintip'], '5ba81b19') - assert_equal(bci['consensus']['nextblock'], '5ba81b19') - assert_equal(bci['upgrades']['5ba81b19']['status'], 'active') + assert_equal(bci['consensus']['chaintip'], '2bb40e60') + assert_equal(bci['consensus']['nextblock'], '2bb40e60') + assert_equal(bci['upgrades']['2bb40e60']['status'], 'active') # Verify balance assert_equal(self.nodes[1].z_getbalance(taddr1), Decimal('1.0')) assert_equal(self.nodes[3].getbalance(), Decimal('0.4999')) assert_equal(self.nodes[3].z_getbalance(zaddr3), zsendamount) - # Verify transaction version is 3 (intended for Overwinter) + # Verify transaction version is 4 (intended for Sapling+) result = self.nodes[0].getrawtransaction(txid_transparent, 1) - assert_equal(result["version"], 3) + assert_equal(result["version"], 4) assert_equal(result["overwintered"], True) - assert_equal(result["versiongroupid"], "03c48270") + assert_equal(result["versiongroupid"], "892f2085") result = self.nodes[0].getrawtransaction(txid_zsendmany, 1) - assert_equal(result["version"], 3) + assert_equal(result["version"], 4) assert_equal(result["overwintered"], True) - assert_equal(result["versiongroupid"], "03c48270") + assert_equal(result["versiongroupid"], "892f2085") result = self.nodes[0].getrawtransaction(txid_shielded, 1) - assert_equal(result["version"], 3) + assert_equal(result["version"], 4) assert_equal(result["overwintered"], True) - assert_equal(result["versiongroupid"], "03c48270") + assert_equal(result["versiongroupid"], "892f2085") if __name__ == '__main__': WalletOverwinterTxTest().main() diff --git a/qa/rpc-tests/wallet_persistence.py b/qa/rpc-tests/wallet_persistence.py index 2d6bc5b46..16b49a130 100755 --- a/qa/rpc-tests/wallet_persistence.py +++ b/qa/rpc-tests/wallet_persistence.py @@ -22,11 +22,7 @@ def setup_chain(self): initialize_chain_clean(self.options.tmpdir, 4) def setup_network(self, split=False): - self.nodes = start_nodes(4, self.options.tmpdir, - extra_args=[[ - '-nuparams=5ba81b19:100', # Overwinter - '-nuparams=76b809bb:201', # Sapling - ]] * 3) + self.nodes = start_nodes(3, self.options.tmpdir) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) self.is_network_split=False @@ -38,10 +34,10 @@ def run_test(self): assert_equal(self.nodes[0].getblockcount(), 200) self.sync_all() - # Verify Sapling address is persisted in wallet (even when Sapling is not yet active) + # Verify Sapling address is persisted in wallet sapling_addr = self.nodes[0].z_getnewaddress('sapling') - # Make sure the node has the addresss + # Make sure the node has the address addresses = self.nodes[0].z_listaddresses() assert_true(sapling_addr in addresses, "Should contain address before restart") @@ -54,10 +50,6 @@ def run_test(self): addresses = self.nodes[0].z_listaddresses() assert_true(sapling_addr in addresses, "Should contain address after restart") - # Activate Sapling - self.nodes[0].generate(1) - self.sync_all() - # Node 0 shields funds to Sapling address taddr0 = get_coinbase_address(self.nodes[0]) recipients = [] diff --git a/qa/rpc-tests/wallet_sapling.py b/qa/rpc-tests/wallet_sapling.py index 3ac4d02d8..161676800 100755 --- a/qa/rpc-tests/wallet_sapling.py +++ b/qa/rpc-tests/wallet_sapling.py @@ -20,62 +20,12 @@ class WalletSaplingTest(BitcoinTestFramework): def setup_nodes(self): - return start_nodes(4, self.options.tmpdir, [[ - '-nuparams=5ba81b19:201', # Overwinter - '-nuparams=76b809bb:203', # Sapling - '-experimentalfeatures', '-zmergetoaddress', - ]] * 4) + return start_nodes(4, self.options.tmpdir) def run_test(self): # Sanity-check the test harness assert_equal(self.nodes[0].getblockcount(), 200) - # Activate Overwinter - self.nodes[2].generate(1) - self.sync_all() - - # Verify RPCs disallow Sapling value transfer if Sapling is not active - tmp_taddr = get_coinbase_address(self.nodes[3]) - tmp_zaddr = self.nodes[3].z_getnewaddress('sapling') - try: - recipients = [] - recipients.append({"address": tmp_zaddr, "amount": Decimal('10')}) - self.nodes[3].z_sendmany(tmp_taddr, recipients, 1, 0) - raise AssertionError("Should have thrown an exception") - except JSONRPCException as e: - assert_equal("Invalid parameter, Sapling has not activated", e.error['message']) - try: - recipients = [] - recipients.append({"address": tmp_taddr, "amount": Decimal('10')}) - self.nodes[3].z_sendmany(tmp_zaddr, recipients, 1, 0) - raise AssertionError("Should have thrown an exception") - except JSONRPCException as e: - assert_equal("Invalid parameter, Sapling has not activated", e.error['message']) - try: - self.nodes[3].z_shieldcoinbase(tmp_taddr, tmp_zaddr) - raise AssertionError("Should have thrown an exception") - except JSONRPCException as e: - assert_equal("Invalid parameter, Sapling has not activated", e.error['message']) - - # Verify z_mergetoaddress RPC does not support Sapling yet - try: - self.nodes[3].z_mergetoaddress([tmp_taddr], tmp_zaddr) - raise AssertionError("Should have thrown an exception") - except JSONRPCException as e: - assert_equal("Invalid parameter, Sapling has not activated", e.error['message']) - try: - self.nodes[3].z_mergetoaddress([tmp_zaddr], tmp_taddr) - raise AssertionError("Should have thrown an exception") - except JSONRPCException as e: - # When sending from a zaddr we check for sapling activation only if - # we find notes belonging to that address. Since sapling is not active - # none can be generated and none will be found. - assert_equal("Could not find any funds to merge.", e.error['message']) - - # Activate Sapling - self.nodes[2].generate(2) - self.sync_all() - taddr1 = self.nodes[1].getnewaddress() saplingAddr0 = self.nodes[0].z_getnewaddress('sapling') saplingAddr1 = self.nodes[1].z_getnewaddress('sapling') @@ -188,19 +138,25 @@ def run_test(self): sk0 = self.nodes[0].z_exportkey(saplingAddr0) saplingAddrInfo0 = self.nodes[2].z_importkey(sk0, "yes") assert_equal(saplingAddrInfo0["type"], "sapling") + assert_equal(saplingAddrInfo0["address"], saplingAddr0) assert_equal(self.nodes[2].z_getbalance(saplingAddrInfo0["address"]), Decimal('10')) sk1 = self.nodes[1].z_exportkey(saplingAddr1) saplingAddrInfo1 = self.nodes[2].z_importkey(sk1, "yes") assert_equal(saplingAddrInfo1["type"], "sapling") + assert_equal(saplingAddrInfo1["address"], saplingAddr1) assert_equal(self.nodes[2].z_getbalance(saplingAddrInfo1["address"]), Decimal('5')) # Verify importing a viewing key will update the nullifiers and witnesses correctly extfvk0 = self.nodes[0].z_exportviewingkey(saplingAddr0) - self.nodes[3].z_importviewingkey(extfvk0, "yes") - assert_equal(self.nodes[3].z_getbalance(saplingAddr0), Decimal('10')) + saplingAddrInfo0 = self.nodes[3].z_importviewingkey(extfvk0, "yes") + assert_equal(saplingAddrInfo0["type"], "sapling") + assert_equal(saplingAddrInfo0["address"], saplingAddr0) + assert_equal(self.nodes[3].z_getbalance(saplingAddrInfo0["address"]), Decimal('10')) extfvk1 = self.nodes[1].z_exportviewingkey(saplingAddr1) - self.nodes[3].z_importviewingkey(extfvk1, "yes") - assert_equal(self.nodes[3].z_getbalance(saplingAddr1), Decimal('5')) + saplingAddrInfo1 = self.nodes[3].z_importviewingkey(extfvk1, "yes") + assert_equal(saplingAddrInfo1["type"], "sapling") + assert_equal(saplingAddrInfo1["address"], saplingAddr1) + assert_equal(self.nodes[3].z_getbalance(saplingAddrInfo1["address"]), Decimal('5')) # Verify that z_gettotalbalance only includes watch-only addresses when requested assert_equal(self.nodes[3].z_gettotalbalance()['private'], '0.00') diff --git a/qa/rpc-tests/wallet_shieldcoinbase.py b/qa/rpc-tests/wallet_shieldcoinbase.py index 69e02f8a2..2045f201e 100755 --- a/qa/rpc-tests/wallet_shieldcoinbase.py +++ b/qa/rpc-tests/wallet_shieldcoinbase.py @@ -24,18 +24,10 @@ def setup_chain(self): def setup_network(self, split=False): args = ['-regtestprotectcoinbase', '-debug=zrpcunsafe'] - args2 = ['-regtestprotectcoinbase', '-debug=zrpcunsafe', "-mempooltxinputlimit=7"] - if self.addr_type != 'sprout': - nu = [ - '-nuparams=5ba81b19:0', # Overwinter - '-nuparams=76b809bb:1', # Sapling - ] - args.extend(nu) - args2 = args self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir, args)) self.nodes.append(start_node(1, self.options.tmpdir, args)) - self.nodes.append(start_node(2, self.options.tmpdir, args2)) + self.nodes.append(start_node(2, self.options.tmpdir, args)) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -161,18 +153,12 @@ def verify_locking(first, second, limit): assert_equal(result["remainingUTXOs"], Decimal('0')) opid2 = result['opid'] - # wait for both aysnc operations to complete + # wait for both async operations to complete wait_and_assert_operationid_status(self.nodes[0], opid1) wait_and_assert_operationid_status(self.nodes[0], opid2) - if self.addr_type == 'sprout': - # Shielding the 800 utxos will occur over two transactions, since max tx size is 100,000 bytes. - # We don't verify shieldingValue as utxos are not selected in any specific order, so value can change on each test run. - # We set an unrealistically high limit parameter of 99999, to verify that max tx size will constrain the number of utxos. - verify_locking('662', '138', 99999) - else: - # Shield the 800 utxos over two transactions - verify_locking('500', '300', 500) + # Shield the 800 utxos over two transactions + verify_locking('500', '300', 500) # sync_all() invokes sync_mempool() but node 2's mempool limit will cause tx1 and tx2 to be rejected. # So instead, we sync on blocks and mempool for node 0 and node 1, and after a new block is generated @@ -182,18 +168,6 @@ def verify_locking(first, second, limit): self.nodes[1].generate(1) self.sync_all() - if self.addr_type == 'sprout': - # Verify maximum number of utxos which node 2 can shield is limited by option -mempooltxinputlimit - # This option is used when the limit parameter is set to 0. - mytaddr = get_coinbase_address(self.nodes[2], 20) - result = self.nodes[2].z_shieldcoinbase(mytaddr, myzaddr, Decimal('0.0001'), 0) - assert_equal(result["shieldingUTXOs"], Decimal('7')) - assert_equal(result["remainingUTXOs"], Decimal('13')) - wait_and_assert_operationid_status(self.nodes[2], result['opid']) - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() - # Verify maximum number of utxos which node 0 can shield is set by default limit parameter of 50 self.nodes[0].generate(200) self.sync_all() diff --git a/qa/rpc-tests/wallet_protectcoinbase.py b/qa/rpc-tests/wallet_shieldingcoinbase.py similarity index 98% rename from qa/rpc-tests/wallet_protectcoinbase.py rename to qa/rpc-tests/wallet_shieldingcoinbase.py index e7acb0acf..3d6a0e6e4 100755 --- a/qa/rpc-tests/wallet_protectcoinbase.py +++ b/qa/rpc-tests/wallet_shieldingcoinbase.py @@ -25,15 +25,15 @@ def check_value_pool(node, name, total): assert_equal(pool['chainValue'], total) assert(found) -class WalletProtectCoinbaseTest (BitcoinTestFramework): +class WalletShieldingCoinbaseTest (BitcoinTestFramework): def setup_chain(self): print("Initializing test directory "+self.options.tmpdir) initialize_chain_clean(self.options.tmpdir, 4) - # Start nodes with -regtestprotectcoinbase to set fCoinbaseMustBeProtected to true. + # Start nodes with -regtestshieldcoinbase to set fCoinbaseMustBeShielded to true. def setup_network(self, split=False): - self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[['-regtestprotectcoinbase', '-debug=zrpcunsafe']] * 4 ) + self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[['-regtestshieldcoinbase', '-debug=zrpcunsafe']] * 4 ) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -45,6 +45,7 @@ def run_test (self): print "Mining blocks..." self.nodes[0].generate(4) + self.sync_all() walletinfo = self.nodes[0].getwalletinfo() assert_equal(walletinfo['immature_balance'], 50000) @@ -84,7 +85,7 @@ def run_test (self): wait_and_assert_operationid_status(self.nodes[3], myopid, "failed", "Insufficient funds, no UTXOs found for taddr from address.", 10) - # This send will fail because our wallet does not allow any change when protecting a coinbase utxo, + # This send will fail because our wallet does not allow any change when shielding a coinbase utxo, # as it's currently not possible to specify a change address in z_sendmany. recipients = [] recipients.append({"address":myzaddr, "amount":Decimal('1.23456789')}) @@ -363,4 +364,4 @@ def run_test (self): assert_equal(Decimal(resp), sum_of_notes) if __name__ == '__main__': - WalletProtectCoinbaseTest().main() + WalletShieldingCoinbaseTest().main() diff --git a/qa/rpc-tests/wallet_treestate.py b/qa/rpc-tests/wallet_treestate.py index c3d81df22..a21da4f64 100755 --- a/qa/rpc-tests/wallet_treestate.py +++ b/qa/rpc-tests/wallet_treestate.py @@ -19,9 +19,9 @@ def setup_chain(self): print("Initializing test directory "+self.options.tmpdir) initialize_chain_clean(self.options.tmpdir, 4) - # Start nodes with -regtestprotectcoinbase to set fCoinbaseMustBeProtected to true. + # Start nodes with -regtestshieldcoinbase to set fCoinbaseMustBeShielded to true. def setup_network(self, split=False): - self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[['-regtestprotectcoinbase','-debug=zrpc']] * 3 ) + self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[['-regtestshieldcoinbase','-debug=zrpc']] * 3 ) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) diff --git a/qa/rpc-tests/zapwallettxes.py b/qa/rpc-tests/zapwallettxes.py index e9acb51c0..fb5e6a04d 100755 --- a/qa/rpc-tests/zapwallettxes.py +++ b/qa/rpc-tests/zapwallettxes.py @@ -76,7 +76,7 @@ def run_test (self): print e aException = True - assert_equal(aException, True) # there must be a expection because the unconfirmed wallettx0 must be gone by now + assert_equal(aException, True) # there must be an expection because the unconfirmed wallet tx0 must be gone by now tx0 = self.nodes[0].gettransaction(txid0) assert_equal(tx0['txid'], txid0) # tx0 (confirmed) must still be available because it was confirmed diff --git a/qa/rpc-tests/zcjoinsplit.py b/qa/rpc-tests/zcjoinsplit.py index ae42d9d1a..bc0363db5 100755 --- a/qa/rpc-tests/zcjoinsplit.py +++ b/qa/rpc-tests/zcjoinsplit.py @@ -23,14 +23,14 @@ def run_test(self): zcaddress = zckeypair["zcaddress"] (total_in, inputs) = gather_inputs(self.nodes[0], 50000) - protect_tx = self.nodes[0].createrawtransaction(inputs, {}) - joinsplit_result = self.nodes[0].zcrawjoinsplit(protect_tx, {}, {zcaddress:49999.99}, 49999.99, 0) + shield_tx = self.nodes[0].createrawtransaction(inputs, {}) + joinsplit_result = self.nodes[0].zcrawjoinsplit(shield_tx, {}, {zcaddress:39.99}, 39.99, 0) receive_result = self.nodes[0].zcrawreceive(zcsecretkey, joinsplit_result["encryptednote1"]) assert_equal(receive_result["exists"], False) - protect_tx = self.nodes[0].signrawtransaction(joinsplit_result["rawtxn"]) - self.nodes[0].sendrawtransaction(protect_tx["hex"]) + shield_tx = self.nodes[0].signrawtransaction(joinsplit_result["rawtxn"]) + self.nodes[0].sendrawtransaction(shield_tx["hex"]) self.nodes[0].generate(1) self.sync_all() diff --git a/share/genbuild.sh b/share/genbuild.sh index 5dde844c2..7fc7588fa 100755 --- a/share/genbuild.sh +++ b/share/genbuild.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Copyright (c) 2017-2020 The BitcoinZ Community +# Copyright (c) 2017-2024 The BitcoinZ Community # Copyright (c) 2016-2019 The Zcash developers # Copyright (c) 2012-2019 The Bitcoin Core developers # Copyright (c) 2012-2019 Bitcoin Developers diff --git a/share/rpcuser/README.md b/share/rpcuser/README.md new file mode 100644 index 000000000..12a8e6fb0 --- /dev/null +++ b/share/rpcuser/README.md @@ -0,0 +1,10 @@ +RPC Tools +--------------------- + +### [RPCUser](/share/rpcuser) ### + +Create an RPC user login credential. + +Usage: + + ./rpcuser.py diff --git a/share/rpcuser/rpcuser.py b/share/rpcuser/rpcuser.py new file mode 100755 index 000000000..384a4ee5b --- /dev/null +++ b/share/rpcuser/rpcuser.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python2 +# Copyright (c) 2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . + +import hashlib +import sys +import os +from random import SystemRandom +import base64 +import hmac + +if len(sys.argv) < 2: + sys.stderr.write('Please include username as an argument.\n') + sys.exit(0) + +username = sys.argv[1] + +#This uses os.urandom() underneath +cryptogen = SystemRandom() + +#Create 16 byte hex salt +salt_sequence = [cryptogen.randrange(256) for i in range(16)] +hexseq = list(map(hex, salt_sequence)) +salt = "".join([x[2:] for x in hexseq]) + +#Create 32 byte b64 password +password = base64.urlsafe_b64encode(os.urandom(32)) + +digestmod = hashlib.sha256 + +if sys.version_info.major >= 3: + password = password.decode('utf-8') + digestmod = 'SHA256' + +m = hmac.new(bytearray(salt, 'utf-8'), bytearray(password, 'utf-8'), digestmod) +result = m.hexdigest() + +print("String to be appended to zcash.conf:") +print("rpcauth="+username+":"+salt+"$"+result) +print("Your password:\n"+password) diff --git a/src/.clang-format b/src/.clang-format index 6314e210f..401a4272e 100644 --- a/src/.clang-format +++ b/src/.clang-format @@ -21,7 +21,6 @@ ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DerivePointerAlignment: false DisableFormat: false -ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, BOOST_REVERSE_FOREACH ] IndentCaseLabels: false IndentFunctionDeclarationAfterType: false IndentWidth: 4 diff --git a/src/Makefile.am b/src/Makefile.am index 1d0c7ccc2..9dfbf81fd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2020 The BitcoinZ community +# Copyright (c) 2017-2024 The BitcoinZ community # Copyright (c) 2016-2019 The Zcash developers # Copyright (c) 2013-2019 The Bitcoin Core developers # Copyright (c) 2013-2019 Bitcoin Developers @@ -7,9 +7,9 @@ DIST_SUBDIRS = secp256k1 univalue -AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(SAN_LDFLAGS) $(HARDENED_LDFLAGS) -AM_CXXFLAGS = $(SAN_CXXFLAGS) $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) -AM_CPPFLAGS = $(HARDENED_CPPFLAGS) +AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS) $(GPROF_LDFLAGS) $(SANITIZER_LDFLAGS) +AM_CXXFLAGS = $(DEBUG_CXXFLAGS) $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) $(GPROF_CXXFLAGS) $(SANITIZER_CXXFLAGS) +AM_CPPFLAGS = $(DEBUG_CPPFLAGS) $(HARDENED_CPPFLAGS) EXTRA_LIBRARIES = if EMBEDDED_LEVELDB @@ -28,11 +28,9 @@ $(LIBLEVELDB) $(LIBMEMENV): endif BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config -BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) +BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include -BITCOIN_INCLUDES += -I$(srcdir)/snark -BITCOIN_INCLUDES += -I$(srcdir)/snark/libsnark BITCOIN_INCLUDES += -I$(srcdir)/univalue/include LIBBITCOIN_SERVER=libbitcoin_server.a @@ -41,7 +39,6 @@ LIBBITCOIN_CLI=libbitcoin_cli.a LIBBITCOIN_UTIL=libbitcoin_util.a LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a LIBSECP256K1=secp256k1/libsecp256k1.la -LIBSNARK=snark/libsnark.a LIBUNIVALUE=univalue/libunivalue.la LIBZCASH=libzcash.a @@ -61,21 +58,6 @@ endif $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) -LIBSNARK_CXXFLAGS = $(AM_CXXFLAGS) $(PIC_FLAGS) -DBINARY_OUTPUT -DNO_PT_COMPRESSION=1 -fstack-protector-all -LIBSNARK_CONFIG_FLAGS = CURVE=ALT_BN128 NO_PROCPS=1 NO_DOCS=1 STATIC=1 NO_SUPERCOP=1 FEATUREFLAGS=-DMONTGOMERY_OUTPUT NO_COPY_DEPINST=1 NO_COMPILE_LIBGTEST=1 -if HAVE_OPENMP -LIBSNARK_CONFIG_FLAGS += MULTICORE=1 -endif -if TARGET_DARWIN -LIBSNARK_CONFIG_FLAGS += PLATFORM=darwin -endif - -$(LIBSNARK): $(wildcard snark/src/*) - $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" - -libsnark-tests: $(wildcard snark/src/*) - $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" - $(LIBUNIVALUE): $(wildcard univalue/lib/*) $(wildcard univalue/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) @@ -97,6 +79,7 @@ lib_LTLIBRARIES = $(LIBZCASH_CONSENSUS) bin_PROGRAMS = noinst_PROGRAMS = TESTS = +BENCHMARKS = if BUILD_BITCOIND bin_PROGRAMS += bitcoinzd @@ -110,9 +93,9 @@ LIBZCASH_H = \ zcash/IncrementalMerkleTree.hpp \ zcash/NoteEncryption.hpp \ zcash/Address.hpp \ - zcash/address/sapling.hpp \ - zcash/address/sprout.hpp \ - zcash/address/zip32.h \ + zcash/address/sapling.hpp \ + zcash/address/sprout.hpp \ + zcash/address/zip32.h \ zcash/JoinSplit.hpp \ zcash/Note.hpp \ zcash/prf.h \ @@ -120,7 +103,7 @@ LIBZCASH_H = \ zcash/util.h \ zcash/Zcash.h -.PHONY: FORCE collate-libsnark check-symbols check-security +.PHONY: FORCE check-symbols check-security # bitcoin core # BITCOIN_CORE_H = \ addressindex.h \ @@ -153,12 +136,14 @@ BITCOIN_CORE_H = \ compat/sanity.h \ compressor.h \ consensus/consensus.h \ + consensus/merkle.h \ consensus/params.h \ consensus/upgrades.h \ consensus/validation.h \ core_io.h \ core_memusage.h \ deprecation.h \ + experimental_features.h \ hash.h \ httprpc.h \ httpserver.h \ @@ -178,6 +163,7 @@ BITCOIN_CORE_H = \ netbase.h \ noui.h \ policy/fees.h \ + policy/policy.h \ pow.h \ prevector.h \ primitives/block.h \ @@ -185,6 +171,7 @@ BITCOIN_CORE_H = \ protocol.h \ pubkey.h \ random.h \ + reverse_iterator.h \ reverselock.h \ rpc/client.h \ rpc/protocol.h \ @@ -197,6 +184,7 @@ BITCOIN_CORE_H = \ script/sigcache.h \ script/sign.h \ script/standard.h \ + script/ismine.h \ serialize.h \ spentindex.h \ streams.h \ @@ -213,6 +201,7 @@ BITCOIN_CORE_H = \ torcontrol.h \ transaction_builder.h \ txdb.h \ + mempool_limit.h \ txmempool.h \ ui_interface.h \ uint256.h \ @@ -225,7 +214,7 @@ BITCOIN_CORE_H = \ utiltime.h \ validationinterface.h \ version.h \ - wallet/asyncrpcoperation_common.h \ + wallet/asyncrpcoperation_common.h \ wallet/asyncrpcoperation_mergetoaddress.h \ wallet/asyncrpcoperation_saplingmigration.h \ wallet/asyncrpcoperation_sendmany.h \ @@ -236,9 +225,8 @@ BITCOIN_CORE_H = \ wallet/paymentdisclosuredb.h \ wallet/rpcwallet.h \ wallet/wallet.h \ - wallet/wallet_ismine.h \ wallet/walletdb.h \ - warnings.h \ + warnings.h \ zmq/zmqabstractnotifier.h \ zmq/zmqconfig.h\ zmq/zmqnotificationinterface.h \ @@ -265,6 +253,7 @@ libbitcoin_server_a_SOURCES = \ chain.cpp \ checkpoints.cpp \ deprecation.cpp \ + experimental_features.cpp \ httprpc.cpp \ httpserver.cpp \ init.cpp \ @@ -276,6 +265,7 @@ libbitcoin_server_a_SOURCES = \ net.cpp \ noui.cpp \ policy/fees.cpp \ + policy/policy.cpp \ pow.cpp \ rest.cpp \ rpc/blockchain.cpp \ @@ -285,9 +275,11 @@ libbitcoin_server_a_SOURCES = \ rpc/rawtransaction.cpp \ rpc/server.cpp \ script/sigcache.cpp \ + script/ismine.cpp \ timedata.cpp \ torcontrol.cpp \ txdb.cpp \ + mempool_limit.cpp \ txmempool.cpp \ validationinterface.cpp \ $(BITCOIN_CORE_H) \ @@ -317,7 +309,7 @@ libbitcoin_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_wallet_a_SOURCES = \ zcbenchmarks.cpp \ zcbenchmarks.h \ - wallet/asyncrpcoperation_common.cpp \ + wallet/asyncrpcoperation_common.cpp \ wallet/asyncrpcoperation_mergetoaddress.cpp \ wallet/asyncrpcoperation_saplingmigration.cpp \ wallet/asyncrpcoperation_sendmany.cpp \ @@ -330,7 +322,6 @@ libbitcoin_wallet_a_SOURCES = \ wallet/rpcdump.cpp \ wallet/rpcwallet.cpp \ wallet/wallet.cpp \ - wallet/wallet_ismine.cpp \ wallet/walletdb.cpp \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) @@ -339,6 +330,8 @@ libbitcoin_wallet_a_SOURCES = \ crypto_libbitcoin_crypto_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_CONFIG_INCLUDES) crypto_libbitcoin_crypto_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) crypto_libbitcoin_crypto_a_SOURCES = \ + crypto/aes.cpp \ + crypto/aes.h \ crypto/common.h \ crypto/equihash.cpp \ crypto/equihash.h \ @@ -379,7 +372,8 @@ libbitcoin_common_a_SOURCES = \ chainparams.cpp \ coins.cpp \ compressor.cpp \ - consensus/params.cpp \ + consensus/merkle.cpp \ + consensus/params.cpp \ consensus/upgrades.cpp \ core_read.cpp \ core_write.cpp \ @@ -400,7 +394,7 @@ libbitcoin_common_a_SOURCES = \ script/standard.cpp \ transaction_builder.cpp \ utiltest.cpp \ - warnings.cpp \ + warnings.cpp \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) @@ -463,7 +457,6 @@ bitcoinzd_LDADD = \ $(LIBBITCOIN_PROTON) \ $(LIBBITCOIN_CRYPTO) \ $(LIBZCASH) \ - $(LIBSNARK) \ $(LIBLEVELDB) \ $(LIBMEMENV) \ $(LIBSECP256K1) @@ -471,8 +464,6 @@ bitcoinzd_LDADD = \ bitcoinzd_LDADD += \ $(BOOST_LIBS) \ $(BDB_LIBS) \ - $(SSL_LIBS) \ - $(CRYPTO_LIBS) \ $(EVENT_PTHREADS_LIBS) \ $(EVENT_LIBS) \ $(ZMQ_LIBS) \ @@ -495,11 +486,8 @@ bitcoinz_cli_LDADD = \ $(LIBUNIVALUE) \ $(LIBBITCOIN_UTIL) \ $(BOOST_LIBS) \ - $(SSL_LIBS) \ - $(CRYPTO_LIBS) \ $(EVENT_LIBS) \ $(LIBZCASH) \ - $(LIBSNARK) \ $(LIBBITCOIN_CRYPTO) \ $(LIBZCASH_LIBS) # @@ -521,11 +509,10 @@ bitcoinz_tx_LDADD = \ $(LIBBITCOIN_UTIL) \ $(LIBSECP256K1) \ $(LIBZCASH) \ - $(LIBSNARK) \ $(LIBBITCOIN_CRYPTO) \ $(LIBZCASH_LIBS) -bitcoinz_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) +bitcoinz_tx_LDADD += $(BOOST_LIBS) # # zcash protocol primitives # @@ -533,27 +520,19 @@ libzcash_a_SOURCES = \ zcash/IncrementalMerkleTree.cpp \ zcash/NoteEncryption.cpp \ zcash/Address.cpp \ - zcash/address/sapling.cpp \ + zcash/address/sapling.cpp \ zcash/address/sprout.cpp \ zcash/address/zip32.cpp \ zcash/JoinSplit.cpp \ zcash/Proof.cpp \ zcash/Note.cpp \ zcash/prf.cpp \ - zcash/util.cpp \ - zcash/circuit/commitment.tcc \ - zcash/circuit/gadget.tcc \ - zcash/circuit/merkle.tcc \ - zcash/circuit/note.tcc \ - zcash/circuit/prfs.tcc \ - zcash/circuit/utils.tcc - -libzcash_a_CPPFLAGS = $(AM_CPPFLAGS) $(PIC_FLAGS) -DBINARY_OUTPUT -DCURVE_ALT_BN128 -DBOOST_SPIRIT_THREADSAFE -fvisibility=hidden -DSTATIC $(BITCOIN_INCLUDES) + zcash/util.cpp + +libzcash_a_CPPFLAGS = $(AM_CPPFLAGS) $(PIC_FLAGS) $(BITCOIN_INCLUDES) libzcash_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libzcash_a_LDFLAGS = $(AM_LDFLAGS) -libzcash_a_CPPFLAGS += -DMONTGOMERY_OUTPUT - # zcashconsensus library # if BUILD_BITCOIN_LIBS include_HEADERS = script/zcashconsensus.h @@ -585,18 +564,25 @@ libzcashconsensus_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) endif # +CTAES_DIST = crypto/ctaes/bench.c +CTAES_DIST += crypto/ctaes/ctaes.c +CTAES_DIST += crypto/ctaes/ctaes.h +CTAES_DIST += crypto/ctaes/README.md +CTAES_DIST += crypto/ctaes/test.c + CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno */*.gcno wallet/*/*.gcno DISTCLEANFILES = obj/build.h -EXTRA_DIST = leveldb snark +EXTRA_DIST = leveldb $(CTAES_DIST) clean-local: -$(MAKE) -C leveldb clean -$(MAKE) -C secp256k1 clean - -$(MAKE) -C snark clean -$(MAKE) -C univalue clean rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno + rm -f fuzz.cpp + rm -rf fuzzing/*/output -rm -f config.h .rc.o: @@ -627,3 +613,7 @@ if ENABLE_TESTS include Makefile.test.include include Makefile.gtest.include endif + +if ENABLE_BENCH +include Makefile.bench.include +endif diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include new file mode 100644 index 000000000..c7de346d7 --- /dev/null +++ b/src/Makefile.bench.include @@ -0,0 +1,55 @@ +bin_PROGRAMS += bench/bench_bitcoinz +BENCH_SRCDIR = bench +BENCH_BINARY = bench/bench_bitcoinz$(EXEEXT) + + +bench_bench_bitcoinz_SOURCES = \ + bench/bench_bitcoin.cpp \ + bench/bench.cpp \ + bench/bench.h \ + bench/checkqueue.cpp \ + bench/Examples.cpp \ + bench/rollingbloom.cpp \ + bench/verification.cpp \ + bench/crypto_hash.cpp \ + bench/base58.cpp \ + bench/perf.cpp \ + bench/perf.h \ + bench/prevector_destructor.cpp + +bench_bench_bitcoinz_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/ +bench_bench_bitcoinz_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +bench_bench_bitcoinz_LDADD = \ + $(LIBBITCOIN_SERVER) \ + $(LIBBITCOIN_COMMON) \ + $(LIBBITCOIN_UNIVALUE) \ + $(LIBBITCOIN_UTIL) \ + $(LIBBITCOIN_CRYPTO) \ + $(LIBLEVELDB) \ + $(LIBMEMENV) \ + $(LIBSECP256K1) \ + $(LIBZCASH) \ + $(LIBSNARK) + +if ENABLE_ZMQ +bench_bench_bitcoinz_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) +endif + +if ENABLE_WALLET +bench_bench_bitcoinz_LDADD += $(LIBBITCOIN_WALLET) +endif + +bench_bench_bitcoinz_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(LIBZCASH_LIBS) +bench_bench_bitcoinz_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) + +CLEAN_BITCOINZ_BENCH = bench/*.gcda bench/*.gcno + +CLEANFILES += $(CLEAN_BITCOINZ_BENCH) + +bitcoinz_bench: $(BENCH_BINARY) + +bench: $(BENCH_BINARY) FORCE + $(BENCH_BINARY) + +bitcoinz_bench_clean : FORCE + rm -f $(CLEAN_BITCOIN_BENCH) $(bench_bench_bitcoinz_OBJECTS) $(BENCH_BINARY) diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include index c25cb4136..37711468d 100644 --- a/src/Makefile.gtest.include +++ b/src/Makefile.gtest.include @@ -5,28 +5,30 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . -TESTS += zcash-gtest -noinst_PROGRAMS += zcash-gtest +TESTS += bitcoinz-gtest +noinst_PROGRAMS += bitcoinz-gtest # tool for generating our public parameters. # test_checktransaction.cpp MUST be before # any test that calls SelectParams(). -zcash_gtest_SOURCES = \ +bitcoinz_gtest_SOURCES = \ gtest/main.cpp \ gtest/utils.cpp \ gtest/test_checktransaction.cpp \ + gtest/test_consensus.cpp \ gtest/json_test_vectors.cpp \ gtest/json_test_vectors.h \ gtest/test_foundersreward.cpp # These tests are order-dependent, because they # depend on global state (see #1539) if ENABLE_WALLET -zcash_gtest_SOURCES += \ +bitcoinz_gtest_SOURCES += \ wallet/gtest/test_wallet_zkeys.cpp endif -zcash_gtest_SOURCES += \ +bitcoinz_gtest_SOURCES += \ gtest/test_tautology.cpp \ gtest/test_deprecation.cpp \ + gtest/test_dynamicusage.cpp \ gtest/test_equihash.cpp \ gtest/test_httprpc.cpp \ gtest/test_joinsplit.cpp \ @@ -34,6 +36,7 @@ zcash_gtest_SOURCES += \ gtest/test_keystore.cpp \ gtest/test_noteencryption.cpp \ gtest/test_mempool.cpp \ + gtest/test_mempoollimit.cpp \ gtest/test_merkletree.cpp \ gtest/test_metrics.cpp \ gtest/test_miner.cpp \ @@ -45,42 +48,53 @@ zcash_gtest_SOURCES += \ gtest/test_transaction_builder.cpp \ gtest/test_upgrades.cpp \ gtest/test_validation.cpp \ - gtest/test_circuit.cpp \ gtest/test_txid.cpp \ gtest/test_libzcash_utils.cpp \ - gtest/test_proofs.cpp \ gtest/test_pedersen_hash.cpp \ gtest/test_checkblock.cpp \ gtest/test_zip32.cpp if ENABLE_WALLET -zcash_gtest_SOURCES += \ +bitcoinz_gtest_SOURCES += \ wallet/gtest/test_paymentdisclosure.cpp \ wallet/gtest/test_wallet.cpp endif -zcash_gtest_CPPFLAGS = $(AM_CPPFLAGS) -DBINARY_OUTPUT -DCURVE_ALT_BN128 -DSTATIC $(BITCOIN_INCLUDES) -zcash_gtest_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +bitcoinz_gtest_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +bitcoinz_gtest_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -zcash_gtest_LDADD = -lgtest -lgmock $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \ - $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) -if ENABLE_ZMQ -zcash_gtest_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) -endif -if ENABLE_WALLET -zcash_gtest_LDADD += $(LIBBITCOIN_WALLET) -endif +bitcoinz_gtest_LDADD = \ + -lgtest -lgmock \ + $(LIBBITCOIN_SERVER) \ + $(LIBBITCOIN_CLI) \ + $(LIBBITCOIN_WALLET) \ + $(LIBBITCOIN_COMMON) \ + $(LIBBITCOIN_UTIL) \ + $(LIBBITCOIN_ZMQ) \ + $(LIBBITCOIN_PROTON) \ + $(LIBBITCOIN_CRYPTO) \ + $(LIBUNIVALUE) \ + $(LIBLEVELDB) \ + $(LIBMEMENV) \ + $(LIBSECP256K1) -zcash_gtest_LDADD += $(LIBZCASH_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(LIBZCASH) $(LIBSNARK) $(LIBZCASH_LIBS) - -if ENABLE_PROTON -zcash_gtest_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) -endif +bitcoinz_gtest_LDADD += \ + $(LIBZCASH_CONSENSUS) \ + $(BOOST_LIBS) \ + $(BOOST_UNIT_TEST_FRAMEWORK_LIB) \ + $(BDB_LIBS) \ + $(EVENT_PTHREADS_LIBS) \ + $(EVENT_LIBS) \ + $(ZMQ_LIBS) \ + $(PROTON_LIBS) \ + $(LIBZCASH) \ + $(LIBRUSTZCASH) \ + $(LIBZCASH_LIBS) -zcash_gtest_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static +bitcoinz_gtest_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static -zcash-gtest_check: zcash-gtest FORCE - ./zcash-gtest +bitcoinz-gtest_check: bitcoinz-gtest FORCE + ./bitcoinz-gtest -zcash-gtest-expected-failures: zcash-gtest FORCE - ./zcash-gtest --gtest_filter=*DISABLED_* --gtest_also_run_disabled_tests +bitcoinz-gtest-expected-failures: bitcoinz-gtest FORCE + ./bitcoinz-gtest --gtest_filter=*DISABLED_* --gtest_also_run_disabled_tests diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 1eb6b262e..b79ac362c 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -1,7 +1,14 @@ -TESTS += test/test_bitcoin -noinst_PROGRAMS += test/test_bitcoin +# Copyright (c) 2017-2024 The BitcoinZ community +# Copyright (c) 2016-2019 The Zcash developers +# Copyright (c) 2013-2019 The Bitcoin Core developers +# Copyright (c) 2013-2019 Bitcoin Developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://www.opensource.org/licenses/mit-license.php . + +TESTS += test/test_bitcoinz +noinst_PROGRAMS += test/test_bitcoinz TEST_SRCDIR = test -TEST_BINARY=test/test_bitcoin$(EXEEXT) +TEST_BINARY=test/test_bitcoinz$(EXEEXT) EXTRA_DIST += \ @@ -27,19 +34,15 @@ JSON_TEST_FILES = \ test/data/tx_valid.json \ test/data/sighash.json \ test/data/merkle_roots.json \ - test/data/merkle_roots_empty.json \ test/data/merkle_serialization.json \ test/data/merkle_witness_serialization.json \ test/data/merkle_path.json \ test/data/merkle_commitments.json \ test/data/merkle_roots_sapling.json \ - test/data/merkle_roots_empty_sapling.json \ test/data/merkle_serialization_sapling.json \ test/data/merkle_witness_serialization_sapling.json \ test/data/merkle_path_sapling.json \ test/data/merkle_commitments_sapling.json \ - test/data/g1_compressed.json \ - test/data/g2_compressed.json \ test/data/sapling_key_components.json RAW_TEST_FILES = test/data/alertTests.raw @@ -48,7 +51,7 @@ GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.r BITCOIN_TESTS =\ test/arith_uint256_tests.cpp \ - test/bignum.h \ + test/scriptnum10.h \ test/addrman_tests.cpp \ test/alert_tests.cpp \ test/allocator_tests.cpp \ @@ -72,6 +75,7 @@ BITCOIN_TESTS =\ test/dbwrapper_tests.cpp \ test/main_tests.cpp \ test/mempool_tests.cpp \ + test/merkle_tests.cpp \ test/miner_tests.cpp \ test/mruset_tests.cpp \ test/multisig_tests.cpp \ @@ -88,16 +92,19 @@ BITCOIN_TESTS =\ test/script_P2SH_tests.cpp \ test/script_P2PKH_tests.cpp \ test/script_tests.cpp \ + test/script_standard_tests.cpp \ test/scriptnum_tests.cpp \ test/serialize_tests.cpp \ test/sighash_tests.cpp \ test/sigopcount_tests.cpp \ test/skiplist_tests.cpp \ + test/streams_tests.cpp \ test/test_bitcoin.cpp \ test/test_bitcoin.h \ test/timedata_tests.cpp \ test/torcontrol_tests.cpp \ test/transaction_tests.cpp \ + test/txvalidationcache_tests.cpp \ test/uint256_tests.cpp \ test/univalue_tests.cpp \ test/util_tests.cpp \ @@ -105,33 +112,36 @@ BITCOIN_TESTS =\ if ENABLE_WALLET BITCOIN_TESTS += \ - test/accounting_tests.cpp \ + wallet/test/wallet_test_fixture.cpp \ + wallet/test/wallet_test_fixture.h \ + wallet/test/accounting_tests.cpp \ + wallet/test/crypto_tests.cpp \ wallet/test/wallet_tests.cpp \ - test/rpc_wallet_tests.cpp + wallet/test/rpc_wallet_tests.cpp endif -test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) -test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) $(EVENT_CFLAGS) -test_test_bitcoin_LDADD = +test_test_bitcoinz_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) +test_test_bitcoinz_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) $(EVENT_CFLAGS) +test_test_bitcoinz_LDADD = if ENABLE_WALLET -test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET) +test_test_bitcoinz_LDADD += $(LIBBITCOIN_WALLET) endif -test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \ +test_test_bitcoinz_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \ $(LIBLEVELDB) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) -test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_test_bitcoinz_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -test_test_bitcoin_LDADD += $(LIBZCASH_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(LIBZCASH) $(LIBSNARK) $(LIBZCASH_LIBS) -test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static +test_test_bitcoinz_LDADD += $(LIBZCASH_CONSENSUS) $(BDB_LIBS) $(LIBZCASH) $(LIBSNARK) $(LIBZCASH_LIBS) +test_test_bitcoinz_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static if ENABLE_ZMQ -test_test_bitcoin_LDADD += $(ZMQ_LIBS) +test_test_bitcoinz_LDADD += $(ZMQ_LIBS) endif if ENABLE_PROTON -test_test_bitcoin_LDADD += $(PROTON_LIBS) +test_test_bitcoinz_LDADD += $(PROTON_LIBS) endif -nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES) +nodist_test_test_bitcoinz_SOURCES = $(GENERATED_TEST_FILES) $(BITCOIN_TESTS): $(GENERATED_TEST_FILES) @@ -139,13 +149,13 @@ CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES) CLEANFILES += $(CLEAN_BITCOIN_TEST) -bitcoin_test: $(TEST_BINARY) +bitcoinz_test: $(TEST_BINARY) -bitcoin_test_check: $(TEST_BINARY) FORCE +bitcoinz_test_check: $(TEST_BINARY) FORCE $(MAKE) check-TESTS TESTS=$^ -bitcoin_test_clean : FORCE - rm -f $(CLEAN_BITCOIN_TEST) $(test_test_bitcoin_OBJECTS) $(TEST_BINARY) +bitcoinz_test_clean : FORCE + rm -f $(CLEAN_BITCOIN_TEST) $(test_test_bitcoinz_OBJECTS) $(TEST_BINARY) check-local: @echo "Running test/bitcoin-util-test.py..." diff --git a/src/addrman.cpp b/src/addrman.cpp index 5ae0f1734..33b0c5481 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -352,8 +352,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly) int nKBucket = RandomInt(ADDRMAN_TRIED_BUCKET_COUNT); int nKBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE); while (vvTried[nKBucket][nKBucketPos] == -1) { - nKBucket = (nKBucket + insecure_rand()) % ADDRMAN_TRIED_BUCKET_COUNT; - nKBucketPos = (nKBucketPos + insecure_rand()) % ADDRMAN_BUCKET_SIZE; + nKBucket = (nKBucket + insecure_rand.rand32()) % ADDRMAN_TRIED_BUCKET_COUNT; + nKBucketPos = (nKBucketPos + insecure_rand.rand32()) % ADDRMAN_BUCKET_SIZE; if (i++ > kMaxRetries) return CAddrInfo(); if (i % kRetriesBetweenSleep == 0 && !nKey.IsNull()) @@ -374,8 +374,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly) int nUBucket = RandomInt(ADDRMAN_NEW_BUCKET_COUNT); int nUBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE); while (vvNew[nUBucket][nUBucketPos] == -1) { - nUBucket = (nUBucket + insecure_rand()) % ADDRMAN_NEW_BUCKET_COUNT; - nUBucketPos = (nUBucketPos + insecure_rand()) % ADDRMAN_BUCKET_SIZE; + nUBucket = (nUBucket + insecure_rand.rand32()) % ADDRMAN_NEW_BUCKET_COUNT; + nUBucketPos = (nUBucketPos + insecure_rand.rand32()) % ADDRMAN_BUCKET_SIZE; if (i++ > kMaxRetries) return CAddrInfo(); if (i % kRetriesBetweenSleep == 0 && !nKey.IsNull()) diff --git a/src/addrman.h b/src/addrman.h index bee1bd9f5..2fd80e9f4 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -203,6 +203,9 @@ class CAddrMan //! secret key to randomize bucket select with uint256 nKey; + //! Source of random numbers for randomization in inner loops + FastRandomContext insecure_rand; + //! Find an entry. CAddrInfo* Find(const CNetAddr& addr, int *pnId = NULL); diff --git a/src/alert.cpp b/src/alert.cpp index d7668453d..10d81a500 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -18,7 +18,6 @@ #include #include -#include #include using namespace std; @@ -47,10 +46,10 @@ void CUnsignedAlert::SetNull() std::string CUnsignedAlert::ToString() const { std::string strSetCancel; - BOOST_FOREACH(int n, setCancel) + for (int n : setCancel) strSetCancel += strprintf("%d ", n); std::string strSetSubVer; - BOOST_FOREACH(const std::string& str, setSubVer) + for (const std::string& str : setSubVer) strSetSubVer += "\"" + str + "\" "; return strprintf( "CAlert(\n" @@ -114,10 +113,28 @@ bool CAlert::Cancels(const CAlert& alert) const bool CAlert::AppliesTo(int nVersion, const std::string& strSubVerIn) const { + // Get a subversion without comments + std::string strSubVer = ""; + auto start = 0; + auto end = 0; + while (start < strSubVerIn.length() && end < strSubVerIn.length()) { + end = strSubVerIn.find('(', start); + if (end == std::string::npos) { + // Ensure we get the section of strSubVerIn after the final comment + end = strSubVerIn.length(); + } + strSubVer.append(strSubVerIn.substr(start, end - start)); + start = strSubVerIn.find(')', end); + if (start != std::string::npos) { + // Finish with start pointing at the next character we want + start += 1; + } + } + // Check against both the commented and uncommented subversion // TODO: rework for client-version-embedded-in-strSubVer ? return (IsInEffect() && nMinVer <= nVersion && nVersion <= nMaxVer && - (setSubVer.empty() || setSubVer.count(strSubVerIn))); + (setSubVer.empty() || setSubVer.count(strSubVerIn) || setSubVer.count(strSubVer))); } bool CAlert::AppliesToMe() const @@ -222,7 +239,7 @@ bool CAlert::ProcessAlert(const std::vector& alertKey, bool fThre } // Check if this alert has been cancelled - BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) + for (std::pair& item : mapAlerts) { const CAlert& alert = item.second; if (alert.Cancels(*this)) diff --git a/src/amqp/amqppublishnotifier.h b/src/amqp/amqppublishnotifier.h index 1d89829b6..2eca74444 100644 --- a/src/amqp/amqppublishnotifier.h +++ b/src/amqp/amqppublishnotifier.h @@ -1,6 +1,6 @@ // Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying -// file COPYING or https://www.opensource.org/licenses/mit-license.php . +// file COPYING or https://www.opensource.org/licenses/mit-license.php . #ifndef ZCASH_AMQP_AMQPPUBLISHNOTIFIER_H #define ZCASH_AMQP_AMQPPUBLISHNOTIFIER_H diff --git a/src/bench/.gitignore b/src/bench/.gitignore new file mode 100644 index 000000000..7d911d7bc --- /dev/null +++ b/src/bench/.gitignore @@ -0,0 +1 @@ +bench_bitcoinz diff --git a/src/bench/Examples.cpp b/src/bench/Examples.cpp new file mode 100644 index 000000000..ec7367bd6 --- /dev/null +++ b/src/bench/Examples.cpp @@ -0,0 +1,34 @@ +// Copyright (c) 2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https ://www.opensource.org/licenses/mit-license.php . + +#include "bench.h" +#include "main.h" +#include "utiltime.h" + +// Sanity test: this should loop ten times, and +// min/max/average should be close to 100ms. +static void Sleep100ms(benchmark::State& state) +{ + while (state.KeepRunning()) { + MilliSleep(100); + } +} + +BENCHMARK(Sleep100ms); + +// Extremely fast-running benchmark: +#include + +volatile double sum = 0.0; // volatile, global so not optimized away + +static void Trig(benchmark::State& state) +{ + double d = 0.01; + while (state.KeepRunning()) { + sum += sin(d); + d += 0.000001; + } +} + +BENCHMARK(Trig); diff --git a/src/bench/base58.cpp b/src/bench/base58.cpp new file mode 100644 index 000000000..53df0b88e --- /dev/null +++ b/src/bench/base58.cpp @@ -0,0 +1,59 @@ +// Copyright (c) 2016 the Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#include "bench.h" + +#include "main.h" +#include "base58.h" + +#include +#include +#include + + +static void Base58Encode(benchmark::State& state) +{ + static const std::array buff = { + { + 17, 79, 8, 99, 150, 189, 208, 162, 22, 23, 203, 163, 36, 58, 147, + 227, 139, 2, 215, 100, 91, 38, 11, 141, 253, 40, 117, 21, 16, 90, + 200, 24 + } + }; + while (state.KeepRunning()) { + EncodeBase58(buff.begin(), buff.end()); + } +} + + +static void Base58CheckEncode(benchmark::State& state) +{ + static const std::array buff = { + { + 17, 79, 8, 99, 150, 189, 208, 162, 22, 23, 203, 163, 36, 58, 147, + 227, 139, 2, 215, 100, 91, 38, 11, 141, 253, 40, 117, 21, 16, 90, + 200, 24 + } + }; + std::vector vch; + vch.assign(buff.begin(), buff.end()); + while (state.KeepRunning()) { + EncodeBase58Check(vch); + } +} + + +static void Base58Decode(benchmark::State& state) +{ + const char* addr = "17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem"; + std::vector vch; + while (state.KeepRunning()) { + DecodeBase58(addr, vch); + } +} + + +BENCHMARK(Base58Encode); +BENCHMARK(Base58CheckEncode); +BENCHMARK(Base58Decode); diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp new file mode 100644 index 000000000..7c5f0bc39 --- /dev/null +++ b/src/bench/bench.cpp @@ -0,0 +1,105 @@ +// Copyright (c) 2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#include "bench.h" +#include "perf.h" + +#include +#include +#include + +benchmark::BenchRunner::BenchmarkMap &benchmark::BenchRunner::benchmarks() { + static std::map benchmarks_map; + return benchmarks_map; +} + +benchmark::BenchRunner::BenchRunner(std::string name, benchmark::BenchFunction func) +{ + benchmarks().insert(std::make_pair(name, func)); +} + +void +benchmark::BenchRunner::RunAll(benchmark::duration elapsedTimeForOne) +{ + perf_init(); + if (std::ratio_less_equal::value) { + std::cerr << "WARNING: Clock precision is worse than microsecond - benchmarks may be less accurate!\n"; + } + std::cout << "#Benchmark" << "," << "count" << "," << "min(ns)" << "," << "max(ns)" << "," << "average(ns)" << "," + << "min_cycles" << "," << "max_cycles" << "," << "average_cycles" << "\n"; + + for (const auto &p: benchmarks()) { + State state(p.first, elapsedTimeForOne); + p.second(state); + } + perf_fini(); +} + +bool benchmark::State::KeepRunning() +{ + if (count & countMask) { + ++count; + return true; + } + time_point now; + + uint64_t nowCycles; + if (count == 0) { + lastTime = beginTime = now = clock::now(); + lastCycles = beginCycles = nowCycles = perf_cpucycles(); + } + else { + now = clock::now(); + auto elapsed = now - lastTime; + auto elapsedOne = elapsed / (countMask + 1); + if (elapsedOne < minTime) minTime = elapsedOne; + if (elapsedOne > maxTime) maxTime = elapsedOne; + + // We only use relative values, so don't have to handle 64-bit wrap-around specially + nowCycles = perf_cpucycles(); + uint64_t elapsedOneCycles = (nowCycles - lastCycles) / (countMask + 1); + if (elapsedOneCycles < minCycles) minCycles = elapsedOneCycles; + if (elapsedOneCycles > maxCycles) maxCycles = elapsedOneCycles; + + if (elapsed*128 < maxElapsed) { + // If the execution was much too fast (1/128th of maxElapsed), increase the count mask by 8x and restart timing. + // The restart avoids including the overhead of this code in the measurement. + countMask = ((countMask<<3)|7) & ((1LL<<60)-1); + count = 0; + minTime = duration::max(); + maxTime = duration::zero(); + minCycles = std::numeric_limits::max(); + maxCycles = std::numeric_limits::min(); + return true; + } + if (elapsed*16 < maxElapsed) { + uint64_t newCountMask = ((countMask<<1)|1) & ((1LL<<60)-1); + if ((count & newCountMask)==0) { + countMask = newCountMask; + } + } + } + lastTime = now; + lastCycles = nowCycles; + ++count; + + if (now - beginTime < maxElapsed) return true; // Keep going + + --count; + + assert(count != 0 && "count == 0 => (now == 0 && beginTime == 0) => return above"); + + // Output results + // Duration casts are only necessary here because hardware with sub-nanosecond clocks + // will lose precision. + int64_t min_elapsed = std::chrono::duration_cast(minTime).count(); + int64_t max_elapsed = std::chrono::duration_cast(maxTime).count(); + int64_t avg_elapsed = std::chrono::duration_cast((now-beginTime)/count).count(); + int64_t averageCycles = (nowCycles-beginCycles)/count; + std::cout << std::fixed << std::setprecision(15) << name << "," << count << "," << min_elapsed << "," << max_elapsed << "," << avg_elapsed << "," + << minCycles << "," << maxCycles << "," << averageCycles << "\n"; + std::cout.copyfmt(std::ios(nullptr)); + + return false; +} diff --git a/src/bench/bench.h b/src/bench/bench.h new file mode 100644 index 000000000..fcdcdb9e3 --- /dev/null +++ b/src/bench/bench.h @@ -0,0 +1,92 @@ +// Copyright (c) 2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#ifndef BITCOIN_BENCH_BENCH_H +#define BITCOIN_BENCH_BENCH_H + +#include +#include +#include +#include +#include + +#include +#include + +// Simple micro-benchmarking framework; API mostly matches a subset of the Google Benchmark +// framework (see https://github.com/google/benchmark) +// Why not use the Google Benchmark framework? Because adding Yet Another Dependency +// (that uses cmake as its build system and has lots of features we don't need) isn't +// worth it. + +/* + * Usage: +static void CODE_TO_TIME(benchmark::State& state) +{ + ... do any setup needed... + while (state.KeepRunning()) { + ... do stuff you want to time... + } + ... do any cleanup needed... +} +BENCHMARK(CODE_TO_TIME); + */ + +namespace benchmark { + // In case high_resolution_clock is steady, prefer that, otherwise use steady_clock. + struct best_clock { + using hi_res_clock = std::chrono::high_resolution_clock; + using steady_clock = std::chrono::steady_clock; + using type = std::conditional::type; + }; + using clock = best_clock::type; + using time_point = clock::time_point; + using duration = clock::duration; + + class State { + std::string name; + duration maxElapsed; + time_point beginTime, lastTime; + duration minTime, maxTime; + uint64_t count; + uint64_t countMask; + uint64_t beginCycles; + uint64_t lastCycles; + uint64_t minCycles; + uint64_t maxCycles; + public: + State(std::string _name, duration _maxElapsed) : + name(_name), + maxElapsed(_maxElapsed), + minTime(duration::max()), + maxTime(duration::zero()), + count(0), + countMask(1), + beginCycles(0), + lastCycles(0), + minCycles(std::numeric_limits::max()), + maxCycles(std::numeric_limits::min()) { + } + bool KeepRunning(); + }; + + typedef std::function BenchFunction; + + class BenchRunner + { + typedef std::map BenchmarkMap; + static BenchmarkMap &benchmarks(); + + public: + BenchRunner(std::string name, BenchFunction func); + + static void RunAll(duration elapsedTimeForOne = std::chrono::seconds(1)); + }; +} + +// BENCHMARK(foo) expands to: benchmark::BenchRunner bench_11foo("foo", foo); +#define BENCHMARK(n) \ + benchmark::BenchRunner BOOST_PP_CAT(bench_, BOOST_PP_CAT(__LINE__, n))(BOOST_PP_STRINGIZE(n), n); + +#endif // BITCOIN_BENCH_BENCH_H diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp new file mode 100644 index 000000000..0e5c5d88f --- /dev/null +++ b/src/bench/bench_bitcoin.cpp @@ -0,0 +1,52 @@ +// Copyright (c) 2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#include "bench.h" + +#include "key.h" +#include "main.h" +#include "util.h" +#include "zcash/JoinSplit.hpp" + +#include + +#include "librustzcash.h" + +const std::function G_TRANSLATION_FUN = nullptr; + +int +main(int argc, char** argv) +{ + ECC_Start(); + auto globalVerifyHandle = new ECCVerifyHandle(); + SetupEnvironment(); + fPrintToDebugLog = false; // don't want to write to debug.log file + + boost::filesystem::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params"; + boost::filesystem::path sapling_output = ZC_GetParamsDir() / "sapling-output.params"; + boost::filesystem::path sprout_groth16 = ZC_GetParamsDir() / "sprout-groth16.params"; + + static_assert( + sizeof(boost::filesystem::path::value_type) == sizeof(codeunit), + "librustzcash not configured correctly"); + auto sapling_spend_str = sapling_spend.native(); + auto sapling_output_str = sapling_output.native(); + auto sprout_groth16_str = sprout_groth16.native(); + + librustzcash_init_zksnark_params( + reinterpret_cast(sapling_spend_str.c_str()), + sapling_spend_str.length(), + "8270785a1a0d0bc77196f000ee6d221c9c9894f55307bd9357c3f0105d31ca63991ab91324160d8f53e2bbd3c2633a6eb8bdf5205d822e7f3f73edac51b2b70c", + reinterpret_cast(sapling_output_str.c_str()), + sapling_output_str.length(), + "657e3d38dbb5cb5e7dd2970e8b03d69b4787dd907285b5a7f0790dcc8072f60bf593b32cc2d1c030e00ff5ae64bf84c5c3beb84ddc841d48264b4a171744d028", + reinterpret_cast(sprout_groth16_str.c_str()), + sprout_groth16_str.length(), + "e9b238411bd6c0ec4791e9d04245ec350c9c5744f5610dfcce4365d5ca49dfefd5054e371842b3f88fa1b9d7e8e075249b3ebabd167fa8b0f3161292d36c180a" + ); + + benchmark::BenchRunner::RunAll(); + + ECC_Stop(); +} diff --git a/src/bench/checkqueue.cpp b/src/bench/checkqueue.cpp new file mode 100644 index 000000000..204062900 --- /dev/null +++ b/src/bench/checkqueue.cpp @@ -0,0 +1,103 @@ +// Copyright (c) 2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#include "bench.h" +#include "util.h" +#include "main.h" +#include "checkqueue.h" +#include "prevector.h" +#include +#include +#include "random.h" + + +// This Benchmark tests the CheckQueue with the lightest +// weight Checks, so it should make any lock contention +// particularly visible +static const int MIN_CORES = 2; +static const size_t BATCHES = 101; +static const size_t BATCH_SIZE = 30; +static const int PREVECTOR_SIZE = 28; +static const int QUEUE_BATCH_SIZE = 128; +static void CCheckQueueSpeed(benchmark::State& state) +{ + struct FakeJobNoWork { + bool operator()() + { + return true; + } + void swap(FakeJobNoWork& x){}; + }; + CCheckQueue queue {QUEUE_BATCH_SIZE}; + boost::thread_group tg; + for (auto x = 0; x < std::max(MIN_CORES, GetNumCores()); ++x) { + tg.create_thread([&]{queue.Thread();}); + } + while (state.KeepRunning()) { + CCheckQueueControl control(&queue); + + // We call Add a number of times to simulate the behavior of adding + // a block of transactions at once. + + std::vector> vBatches(BATCHES); + for (auto& vChecks : vBatches) { + vChecks.resize(BATCH_SIZE); + } + for (auto& vChecks : vBatches) { + // We can't make vChecks in the inner loop because we want to measure + // the cost of getting the memory to each thread and we might get the same + // memory + control.Add(vChecks); + } + // control waits for completion by RAII, but + // it is done explicitly here for clarity + control.Wait(); + } + tg.interrupt_all(); + tg.join_all(); +} + +// This Benchmark tests the CheckQueue with a slightly realistic workload, +// where checks all contain a prevector that is indirect 50% of the time +// and there is a little bit of work done between calls to Add. +static void CCheckQueueSpeedPrevectorJob(benchmark::State& state) +{ + struct PrevectorJob { + prevector p; + PrevectorJob(){ + } + PrevectorJob(FastRandomContext& insecure_rand){ + p.resize(insecure_rand.rand32() % (PREVECTOR_SIZE*2)); + } + bool operator()() + { + return true; + } + void swap(PrevectorJob& x){p.swap(x.p);}; + }; + CCheckQueue queue {QUEUE_BATCH_SIZE}; + boost::thread_group tg; + for (auto x = 0; x < std::max(MIN_CORES, GetNumCores()); ++x) { + tg.create_thread([&]{queue.Thread();}); + } + while (state.KeepRunning()) { + // Make insecure_rand here so that each iteration is identical. + FastRandomContext insecure_rand(true); + CCheckQueueControl control(&queue); + std::vector> vBatches(BATCHES); + for (auto& vChecks : vBatches) { + vChecks.reserve(BATCH_SIZE); + for (size_t x = 0; x < BATCH_SIZE; ++x) + vChecks.emplace_back(insecure_rand); + control.Add(vChecks); + } + // control waits for completion by RAII, but + // it is done explicitly here for clarity + control.Wait(); + } + tg.interrupt_all(); + tg.join_all(); +} +BENCHMARK(CCheckQueueSpeed); +BENCHMARK(CCheckQueueSpeedPrevectorJob); diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp new file mode 100644 index 000000000..2f70580f0 --- /dev/null +++ b/src/bench/crypto_hash.cpp @@ -0,0 +1,79 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#include + +#include "bench.h" +#include "bloom.h" +#include "random.h" +#include "utiltime.h" +#include "crypto/ripemd160.h" +#include "crypto/sha1.h" +#include "crypto/sha256.h" +#include "crypto/sha512.h" + +/* Number of bytes to hash per iteration */ +static const uint64_t BUFFER_SIZE = 1000*1000; + +static void RIPEMD160(benchmark::State& state) +{ + uint8_t hash[CRIPEMD160::OUTPUT_SIZE]; + std::vector in(BUFFER_SIZE,0); + while (state.KeepRunning()) + CRIPEMD160().Write(begin_ptr(in), in.size()).Finalize(hash); +} + +static void SHA1(benchmark::State& state) +{ + uint8_t hash[CSHA1::OUTPUT_SIZE]; + std::vector in(BUFFER_SIZE,0); + while (state.KeepRunning()) + CSHA1().Write(begin_ptr(in), in.size()).Finalize(hash); +} + +static void SHA256(benchmark::State& state) +{ + uint8_t hash[CSHA256::OUTPUT_SIZE]; + std::vector in(BUFFER_SIZE,0); + while (state.KeepRunning()) + CSHA256().Write(begin_ptr(in), in.size()).Finalize(hash); +} + +static void SHA512(benchmark::State& state) +{ + uint8_t hash[CSHA512::OUTPUT_SIZE]; + std::vector in(BUFFER_SIZE,0); + while (state.KeepRunning()) + CSHA512().Write(begin_ptr(in), in.size()).Finalize(hash); +} + +static void FastRandom_32bit(benchmark::State& state) +{ + FastRandomContext rng(true); + uint32_t x = 0; + while (state.KeepRunning()) { + for (int i = 0; i < 1000000; i++) { + x += rng.rand32(); + } + } +} + +static void FastRandom_1bit(benchmark::State& state) +{ + FastRandomContext rng(true); + uint32_t x = 0; + while (state.KeepRunning()) { + for (int i = 0; i < 1000000; i++) { + x += rng.randbool(); + } + } +} + +BENCHMARK(RIPEMD160); +BENCHMARK(SHA1); +BENCHMARK(SHA256); +BENCHMARK(SHA512); + +BENCHMARK(FastRandom_32bit); +BENCHMARK(FastRandom_1bit); diff --git a/src/bench/perf.cpp b/src/bench/perf.cpp new file mode 100644 index 000000000..fdc2cb692 --- /dev/null +++ b/src/bench/perf.cpp @@ -0,0 +1,53 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#include "perf.h" + +#if defined(__i386__) || defined(__x86_64__) + +/* These architectures support querying the cycle counter + * from user space, no need for any syscall overhead. + */ +void perf_init(void) { } +void perf_fini(void) { } + +#elif defined(__linux__) + +#include +#include +#include + +static int fd = -1; +static struct perf_event_attr attr; + +void perf_init(void) +{ + attr.type = PERF_TYPE_HARDWARE; + attr.config = PERF_COUNT_HW_CPU_CYCLES; + fd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0); +} + +void perf_fini(void) +{ + if (fd != -1) { + close(fd); + } +} + +uint64_t perf_cpucycles(void) +{ + uint64_t result = 0; + if (fd == -1 || read(fd, &result, sizeof(result)) < (ssize_t)sizeof(result)) { + return 0; + } + return result; +} + +#else /* Unhandled platform */ + +void perf_init(void) { } +void perf_fini(void) { } +uint64_t perf_cpucycles(void) { return 0; } + +#endif diff --git a/src/bench/perf.h b/src/bench/perf.h new file mode 100644 index 000000000..a8538e397 --- /dev/null +++ b/src/bench/perf.h @@ -0,0 +1,37 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +/** Functions for measurement of CPU cycles */ +#ifndef H_PERF +#define H_PERF + +#include + +#if defined(__i386__) + +static inline uint64_t perf_cpucycles(void) +{ + uint64_t x; + __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); + return x; +} + +#elif defined(__x86_64__) + +static inline uint64_t perf_cpucycles(void) +{ + uint32_t hi, lo; + __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); + return ((uint64_t)lo)|(((uint64_t)hi)<<32); +} +#else + +uint64_t perf_cpucycles(void); + +#endif + +void perf_init(void); +void perf_fini(void); + +#endif // H_PERF diff --git a/src/bench/prevector_destructor.cpp b/src/bench/prevector_destructor.cpp new file mode 100644 index 000000000..7f2881615 --- /dev/null +++ b/src/bench/prevector_destructor.cpp @@ -0,0 +1,36 @@ +// Copyright (c) 2015-2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#include "bench.h" +#include "prevector.h" + +static void PrevectorDestructor(benchmark::State& state) +{ + while (state.KeepRunning()) { + for (auto x = 0; x < 1000; ++x) { + prevector<28, unsigned char> t0; + prevector<28, unsigned char> t1; + t0.resize(28); + t1.resize(29); + } + } +} + +static void PrevectorClear(benchmark::State& state) +{ + + while (state.KeepRunning()) { + for (auto x = 0; x < 1000; ++x) { + prevector<28, unsigned char> t0; + prevector<28, unsigned char> t1; + t0.resize(28); + t0.clear(); + t1.resize(29); + t0.clear(); + } + } +} + +BENCHMARK(PrevectorDestructor); +BENCHMARK(PrevectorClear); diff --git a/src/bench/rollingbloom.cpp b/src/bench/rollingbloom.cpp new file mode 100644 index 000000000..e9fa2ebe5 --- /dev/null +++ b/src/bench/rollingbloom.cpp @@ -0,0 +1,42 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#include + +#include "bench.h" +#include "bloom.h" + +static void RollingBloom(benchmark::State& state) +{ + CRollingBloomFilter filter(120000, 0.000001); + std::vector data(32); + uint32_t count = 0; + uint32_t nEntriesPerGeneration = (120000 + 1) / 2; + uint32_t countnow = 0; + uint64_t match = 0; + while (state.KeepRunning()) { + count++; + data[0] = count; + data[1] = count >> 8; + data[2] = count >> 16; + data[3] = count >> 24; + if (countnow == nEntriesPerGeneration) { + auto b = benchmark::clock::now(); + filter.insert(data); + auto total = std::chrono::duration_cast(benchmark::clock::now() - b).count(); + std::cout << "RollingBloom-refresh,1," << total << "," << total << "," << total << "\n"; + countnow = 0; + } else { + filter.insert(data); + } + countnow++; + data[0] = count >> 24; + data[1] = count >> 16; + data[2] = count >> 8; + data[3] = count; + match += filter.contains(data); + } +} + +BENCHMARK(RollingBloom); diff --git a/src/bench/verification.cpp b/src/bench/verification.cpp new file mode 100644 index 000000000..fd2cd915e --- /dev/null +++ b/src/bench/verification.cpp @@ -0,0 +1,148 @@ +// Copyright (c) 2019 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#include "bench.h" +#include "coins.h" +#include "consensus/upgrades.h" +#include "keystore.h" +#include "primitives/transaction.h" +#include "script/interpreter.h" +#include "script/sign.h" +#include "streams.h" +#include "uint256.h" +#include "utilstrencodings.h" +#include "version.h" + +#include "librustzcash.h" +#include "sodium.h" + +static void ECDSA(benchmark::State& state) +{ + uint32_t consensusBranchId = NetworkUpgradeInfo[Consensus::UPGRADE_OVERWINTER].nBranchId; + CMutableTransaction mtx; + mtx.fOverwintered = true; + mtx.nVersion = SAPLING_TX_VERSION; + mtx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; + + CKey key; + key.MakeNewKey(false); + CBasicKeyStore keystore; + keystore.AddKeyPubKey(key, key.GetPubKey()); + CKeyID hash = key.GetPubKey().GetID(); + CScript scriptPubKey = GetScriptForDestination(hash); + + // Benchmark a transaction containing a single input and output. + auto nInputs = 1; + for(uint32_t ij = 0; ij < nInputs; ij++) { + uint32_t i = mtx.vin.size(); + uint256 prevId; + prevId.SetHex("0000000000000000000000000000000000000000000000000000000000000100"); + COutPoint outpoint(prevId, i); + + mtx.vin.resize(mtx.vin.size() + 1); + mtx.vin[i].prevout = outpoint; + mtx.vin[i].scriptSig = CScript(); + + mtx.vout.resize(mtx.vout.size() + 1); + mtx.vout[i].nValue = 1000; + mtx.vout[i].scriptPubKey = CScript() << OP_1; + } + + // sign all inputs + for(uint32_t i = 0; i < mtx.vin.size(); i++) { + bool hashSigned = SignSignature(keystore, scriptPubKey, mtx, i, 1000, SIGHASH_ALL, consensusBranchId); + assert(hashSigned); + } + + CTransaction tx; + CDataStream ssout(SER_NETWORK, PROTOCOL_VERSION); + ssout << mtx; + ssout >> tx; + + ScriptError error; + + while (state.KeepRunning()) { + VerifyScript( + tx.vin[0].scriptSig, + scriptPubKey, + SCRIPT_VERIFY_P2SH, + TransactionSignatureChecker(&tx, 0, 1000), + consensusBranchId, + &error); + } +} + +static void JoinSplitSig(benchmark::State& state) +{ + uint256 joinSplitPubKey; + unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; + uint256 dataToBeSigned; + std::array joinSplitSig; + + crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey); + crypto_sign_detached(&joinSplitSig[0], nullptr, dataToBeSigned.begin(), 32, joinSplitPrivKey); + + while (state.KeepRunning()) { + // Declared with warn_unused_result. + auto res = crypto_sign_verify_detached( + &joinSplitSig[0], + dataToBeSigned.begin(), 32, + joinSplitPubKey.begin()); + } +} + +static void SaplingSpend(benchmark::State& state) +{ + SpendDescription spend; + CDataStream ss( + ParseHex("8c6cf86bbb83bf0d075e5bd9bb4b5cd56141577be69f032880b11e26aa32aa5ef09fd00899e4b469fb11f38e9d09dc0379f0b11c23b5fe541765f76695120a03f0261d32af5d2a2b1e5c9a04200cd87d574dc42349de9790012ce560406a8a876a1e54cfcdc0eb74998abec2a9778330eeb2a0ac0e41d0c9ed5824fbd0dbf7da930ab299966ce333fd7bc1321dada0817aac5444e02c754069e218746bf879d5f2a20a8b028324fb2c73171e63336686aa5ec2e6e9a08eb18b87c14758c572f4531ccf6b55d09f44beb8b47563be4eff7a52598d80959dd9c9fee5ac4783d8370cb7d55d460053d3e067b5f9fe75ff2722623fb1825fcba5e9593d4205b38d1f502ff03035463043bd393a5ee039ce75a5d54f21b395255df6627ef96751566326f7d4a77d828aa21b1827282829fcbc42aad59cdb521e1a3aaa08b99ea8fe7fff0a04da31a52260fc6daeccd79bb877bdd8506614282258e15b3fe74bf71a93f4be3b770119edf99a317b205eea7d5ab800362b97384273888106c77d633600"), + SER_NETWORK, + PROTOCOL_VERSION); + ss >> spend; + uint256 dataToBeSigned = uint256S("0x2dbf83fe7b88a7cbd80fac0c719483906bb9a0c4fc69071e4780d5f2c76e592c"); + + auto ctx = librustzcash_sapling_verification_ctx_init(); + + while (state.KeepRunning()) { + librustzcash_sapling_check_spend( + ctx, + spend.cv.begin(), + spend.anchor.begin(), + spend.nullifier.begin(), + spend.rk.begin(), + spend.zkproof.begin(), + spend.spendAuthSig.begin(), + dataToBeSigned.begin()); + } + + librustzcash_sapling_verification_ctx_free(ctx); +} + +static void SaplingOutput(benchmark::State& state) +{ + OutputDescription output; + CDataStream ss( + ParseHex("edd742af18857e5ec2d71d346a7fe2ac97c137339bd5268eea86d32e0ff4f38f76213fa8cfed3347ac4e8572dd88aff395c0c10a59f8b3f49d2bc539ed6c726667e29d4763f914ddd0abf1cdfa84e44de87c233434c7e69b8b5b8f4623c8aa444163425bae5cef842972fed66046c1c6ce65c866ad894d02e6e6dcaae7a962d9f2ef95757a09c486928e61f0f7aed90ad0a542b0d3dc5fe140dfa7626b9315c77e03b055f19cbacd21a866e46f06c00e0c7792b2a590a611439b510a9aaffcf1073bad23e712a9268b36888e3727033eee2ab4d869f54a843f93b36ef489fb177bf74b41a9644e5d2a0a417c6ac1c8869bc9b83273d453f878ed6fd96b82a5939903f7b64ecaf68ea16e255a7fb7cc0b6d8b5608a1c6b0ed3024cc62c2f0f9c5cfc7b431ae6e9d40815557aa1d010523f9e1960de77b2274cb6710d229d475c87ae900183206ba90cb5bbc8ec0df98341b82726c705e0308ca5dc08db4db609993a1046dfb43dfd8c760be506c0bed799bb2205fc29dc2e654dce731034a23b0aaf6da0199248702ee0523c159f41f4cbfff6c35ace4dd9ae834e44e09c76a0cbdda1d3f6a2c75ad71212daf9575ab5f09ca148718e667f29ddf18c8a330a86ace18a86e89454653902aa393c84c6b694f27d0d42e24e7ac9fe34733de5ec15f5066081ce912c62c1a804a2bb4dedcef7cc80274f6bb9e89e2fce91dc50d6a73c8aefb9872f1cf3524a92626a0b8f39bbf7bf7d96ca2f770fc04d7f457021c536a506a187a93b2245471ddbfb254a71bc4a0d72c8d639a31c7b1920087ffca05c24214157e2e7b28184e91989ef0b14f9b34c3dc3cc0ac64226b9e337095870cb0885737992e120346e630a416a9b217679ce5a778fb15779c136bcecca5efe79012013d77d90b4e99dd22c8f35bc77121716e160d05bd30d288ee8886390ee436f85bdc9029df888a3a3326d9d4ddba5cb5318b3274928829d662e96fea1d601f7a306251ed8c6cc4e5a3a7a98c35a3650482a0eee08f3b4c2da9b22947c96138f1505c2f081f8972d429f3871f32bef4aaa51aa6945df8e9c9760531ac6f627d17c1518202818a91ca304fb4037875c666060597976144fcbbc48a776a2c61beb9515fa8f3ae6d3a041d320a38a8ac75cb47bb9c866ee497fc3cd13299970c4b369c1c2ceb4220af082fbecdd8114492a8e4d713b5a73396fd224b36c1185bd5e20d683e6c8db35346c47ae7401988255da7cfffdced5801067d4d296688ee8fe424b4a8a69309ce257eefb9345ebfda3f6de46bb11ec94133e1f72cd7ac54934d6cf17b3440800e70b80ebc7c7bfc6fb0fc2c"), + SER_NETWORK, + PROTOCOL_VERSION); + ss >> output; + + auto ctx = librustzcash_sapling_verification_ctx_init(); + + while (state.KeepRunning()) { + librustzcash_sapling_check_output( + ctx, + output.cv.begin(), + output.cmu.begin(), + output.ephemeralKey.begin(), + output.zkproof.begin()); + } + + librustzcash_sapling_verification_ctx_free(ctx); +} + +BENCHMARK(ECDSA); +BENCHMARK(JoinSplitSig); +BENCHMARK(SaplingSpend); +BENCHMARK(SaplingOutput); diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 4336da3e9..c6cc5682b 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -19,6 +19,9 @@ #include +const std::function G_TRANSLATION_FUN = nullptr; + +static const char DEFAULT_RPCCONNECT[] = "127.0.0.1"; static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900; static const int CONTINUE_EXECUTION=-1; @@ -27,12 +30,10 @@ std::string HelpMessageCli() std::string strUsage; strUsage += HelpMessageGroup(_("Options:")); strUsage += HelpMessageOpt("-?", _("This help message")); - strUsage += HelpMessageOpt("-conf=", strprintf(_("Specify configuration file (default: %s)"), "bitcoinz.conf")); + strUsage += HelpMessageOpt("-conf=", strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME)); strUsage += HelpMessageOpt("-datadir=", _("Specify data directory")); - strUsage += HelpMessageOpt("-testnet", _("Use the test network")); - strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be " - "solved instantly. This is intended for regression testing tools and app development.")); - strUsage += HelpMessageOpt("-rpcconnect=", strprintf(_("Send commands to node running on (default: %s)"), "127.0.0.1")); + AppendParamsHelpMessages(strUsage); + strUsage += HelpMessageOpt("-rpcconnect=", strprintf(_("Send commands to node running on (default: %s)"), DEFAULT_RPCCONNECT)); strUsage += HelpMessageOpt("-rpcport=", strprintf(_("Connect to JSON-RPC on (default: %u or testnet: %u)"), 1979, 11979)); strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start")); strUsage += HelpMessageOpt("-rpcuser=", _("Username for JSON-RPC connections")); @@ -101,14 +102,16 @@ static int AppInitRPC(int argc, char* argv[]) return EXIT_FAILURE; } try { - ReadConfigFile(mapArgs, mapMultiArgs); + ReadConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME), mapArgs, mapMultiArgs); } catch (const std::exception& e) { fprintf(stderr,"Error reading configuration file: %s\n", e.what()); return EXIT_FAILURE; } // Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause) - if (!SelectBaseParamsFromCommandLine()) { - fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n"); + try { + SelectBaseParams(ChainNameFromCommandLine()); + } catch(std::exception &e) { + fprintf(stderr, "Error: %s\n", e.what()); return EXIT_FAILURE; } if (GetBoolArg("-rpcssl", false)) @@ -187,7 +190,7 @@ static void http_error_cb(enum evhttp_request_error err, void *ctx) UniValue CallRPC(const std::string& strMethod, const UniValue& params) { - std::string host = GetArg("-rpcconnect", "127.0.0.1"); + std::string host = GetArg("-rpcconnect", DEFAULT_RPCCONNECT); int port = GetArg("-rpcport", BaseParams().RPCPort()); // Obtain event base @@ -213,7 +216,7 @@ UniValue CallRPC(const std::string& strMethod, const UniValue& params) throw std::runtime_error(strprintf( _("Could not locate RPC credentials. No authentication cookie could be found,\n" "and no rpcpassword is set in the configuration file (%s)."), - GetConfigFile().string().c_str())); + GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)).string().c_str())); } } else { @@ -244,6 +247,8 @@ UniValue CallRPC(const std::string& strMethod, const UniValue& params) throw CConnectionFailed(strprintf("couldn't connect to server: %s (code %d)\n(make sure server is running and you are connecting to the correct RPC port)", http_errorstring(response.error), response.error)); else if (response.status == HTTP_UNAUTHORIZED) throw std::runtime_error("incorrect rpcuser or rpcpassword (authorization failed)"); + else if (response.status == HTTP_SERVICE_UNAVAILABLE) + throw std::runtime_error(strprintf("Server response: %s", response.body)); else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR) throw std::runtime_error(strprintf("server returned HTTP error %d", response.status)); else if (response.body.empty()) @@ -328,9 +333,6 @@ int CommandLineRPC(int argc, char *argv[]) } } while (fWait); } - catch (const boost::thread_interrupted&) { - throw; - } catch (const std::exception& e) { strPrint = std::string("error: ") + e.what(); nRet = EXIT_FAILURE; diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 73f8f4bd7..163c51fab 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -9,6 +9,7 @@ #include "core_io.h" #include "key_io.h" #include "keystore.h" +#include "policy/policy.h" #include "primitives/transaction.h" #include "script/script.h" #include "script/sign.h" @@ -26,6 +27,8 @@ static bool fCreateBlank; static std::map registers; static const int CONTINUE_EXECUTION=-1; +const std::function G_TRANSLATION_FUN = nullptr; + // // This function returns either one of EXIT_ codes when it's expected to stop the process or // CONTINUE_EXECUTION when it's expected to continue further. @@ -38,8 +41,10 @@ static int AppInitRawTx(int argc, char* argv[]) ParseParameters(argc, argv); // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause) - if (!SelectParamsFromCommandLine()) { - fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n"); + try { + SelectParams(ChainNameFromCommandLine()); + } catch(std::exception &e) { + fprintf(stderr, "Error: %s\n", e.what()); return false; } @@ -61,8 +66,7 @@ static int AppInitRawTx(int argc, char* argv[]) strUsage += HelpMessageOpt("-create", _("Create new, empty TX.")); strUsage += HelpMessageOpt("-json", _("Select JSON output")); strUsage += HelpMessageOpt("-txid", _("Output only the hex-encoded transaction id of the resultant transaction.")); - strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.")); - strUsage += HelpMessageOpt("-testnet", _("Use the test network")); + AppendParamsHelpMessages(strUsage); fprintf(stdout, "%s", strUsage.c_str()); @@ -174,7 +178,7 @@ static void MutateTxVersion(CMutableTransaction& tx, const std::string& cmdVal) static void MutateTxExpiry(CMutableTransaction& tx, const std::string& cmdVal) { int64_t newExpiry = atoi64(cmdVal); - if (newExpiry >= TX_EXPIRY_HEIGHT_THRESHOLD) { + if (newExpiry <= 0 || newExpiry >= TX_EXPIRY_HEIGHT_THRESHOLD) { throw std::runtime_error("Invalid TX expiry requested"); } tx.nExpiryHeight = (int) newExpiry; @@ -483,7 +487,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& strInput) ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata, consensusBranchId); // ... and merge in other signatures: - BOOST_FOREACH(const CTransaction& txv, txVariants) + for (const CTransaction& txv : txVariants) sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i), consensusBranchId); UpdateTransaction(mergedTx, i, sigdata); @@ -654,10 +658,6 @@ static int CommandLineRawTx(int argc, char* argv[]) OutputTx(tx); } - - catch (const boost::thread_interrupted&) { - throw; - } catch (const std::exception& e) { strPrint = std::string("error: ") + e.what(); nRet = EXIT_FAILURE; diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index c89256da0..7ab05171d 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -19,6 +19,8 @@ #include +const std::function G_TRANSLATION_FUN = nullptr; + /* Introduction text for doxygen: */ /*! \mainpage Developer documentation @@ -99,8 +101,9 @@ bool AppInit(int argc, char* argv[]) } try { - ReadConfigFile(mapArgs, mapMultiArgs); + ReadConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME), mapArgs, mapMultiArgs); } catch (const missing_zcash_conf& e) { + auto confFilename = GetArg("-conf", BITCOIN_CONF_FILENAME); fprintf(stderr, (_("Before starting bitcoinzd, you need to create a configuration file:\n" "%s\n" @@ -112,19 +115,21 @@ bool AppInit(int argc, char* argv[]) "You can look at the example configuration file for suggestions of default\n" "options that you may want to change. It should be in one of these locations,\n" "depending on how you installed BitcoinZ:\n") + - _("- Source code: %s\n" - "- .deb package: %s\n")).c_str(), - GetConfigFile().string().c_str(), - "contrib/debian/examples/bitcoinz.conf", - "/usr/share/doc/bitcoinz/examples/bitcoinz.conf"); + _("- Source code: %s%s\n" + "- .deb package: %s%s\n")).c_str(), + GetConfigFile(confFilename).string().c_str(), + "contrib/debian/examples/", confFilename.c_str(), + "/usr/share/doc/bitcoinz/examples/", confFilename.c_str()); return false; } catch (const std::exception& e) { fprintf(stderr,"Error reading configuration file: %s\n", e.what()); return false; } // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause) - if (!SelectParamsFromCommandLine()) { - fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n"); + try { + SelectParams(ChainNameFromCommandLine()); + } catch(std::exception &e) { + fprintf(stderr, "Error: %s\n", e.what()); return false; } @@ -165,6 +170,9 @@ bool AppInit(int argc, char* argv[]) #endif SoftSetBoolArg("-server", true); + // Set this early so that parameter interactions go to console + InitLogging(); + InitParameterInteraction(); fRet = AppInit2(threadGroup, scheduler); } catch (const std::exception& e) { @@ -187,6 +195,10 @@ bool AppInit(int argc, char* argv[]) return fRet; } +#ifdef ZCASH_FUZZ +#warning BUILDING A FUZZER, NOT THE REAL MAIN +#include "fuzz.cpp" +#else int main(int argc, char* argv[]) { SetupEnvironment(); @@ -196,3 +208,4 @@ int main(int argc, char* argv[]) return (AppInit(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE); } +#endif diff --git a/src/bloom.cpp b/src/bloom.cpp index 49dc5da69..1de10526f 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -14,8 +14,6 @@ #include #include -#include - #define LN2SQUARED 0.4804530139182014246671025263266649717305529515945455 #define LN2 0.6931471805599453094172321214581765680755001343602552 @@ -181,7 +179,7 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx) if (fFound) return true; - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) { // Match if the filter contains an outpoint tx spends if (contains(txin.prevout)) diff --git a/src/chain.cpp b/src/chain.cpp index 35013969f..ced12d3b8 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -5,6 +5,9 @@ #include "chain.h" +#include "main.h" +#include "txdb.h" + using namespace std; /** @@ -58,6 +61,48 @@ const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const { return pindex; } +void CBlockIndex::TrimSolution() +{ + AssertLockHeld(cs_main); + + // We can correctly trim a solution as soon as the block index entry has been added + // to leveldb. Updates to the block index entry (to update validity status) will be + // handled by re-reading the solution from the existing db entry. It does not help to + // try to avoid these reads by gating trimming on the validity status: the re-reads are + // efficient anyway because of caching in leveldb, and most of them are unavoidable. + if (HasSolution()) { + std::vector empty; + nSolution.swap(empty); + } +} + +CBlockHeader CBlockIndex::GetBlockHeader() const +{ + AssertLockHeld(cs_main); + + CBlockHeader header; + header.nVersion = nVersion; + if (pprev) { + header.hashPrevBlock = pprev->GetBlockHash(); + } + header.hashMerkleRoot = hashMerkleRoot; + header.hashFinalSaplingRoot = hashFinalSaplingRoot; + header.nTime = nTime; + header.nBits = nBits; + header.nNonce = nNonce; + if (HasSolution()) { + header.nSolution = nSolution; + } else { + CDiskBlockIndex dbindex; + if (!pblocktree->ReadDiskBlockIndex(GetBlockHash(), dbindex)) { + LogPrintf("%s: Failed to read index entry", __func__); + throw std::runtime_error("Failed to read index entry"); + } + header.nSolution = dbindex.GetSolution(); + } + return header; +} + /** Turn the lowest '1' bit in the binary representation of a number into a '0'. */ int static inline InvertLowestOne(int n) { return n & (n - 1); } diff --git a/src/chain.h b/src/chain.h index 7512b06b4..3cdb8494d 100644 --- a/src/chain.h +++ b/src/chain.h @@ -11,12 +11,28 @@ #include "pow.h" #include "tinyformat.h" #include "uint256.h" +#include "utilstrencodings.h" +#include #include static const int SPROUT_VALUE_VERSION = 1001400; static const int SAPLING_VALUE_VERSION = 1010100; +/** + * Maximum amount of time that a block timestamp is allowed to exceed the + * current network-adjusted time before the block will be accepted. + */ +static const int64_t MAX_FUTURE_BLOCK_TIME = 2 * 60 * 60; + +/** + * Timestamp window used as a grace period by code that compares external + * timestamps (such as timestamps passed to RPCs, or wallet key creation times) + * to block timestamps. This should be set at least as high as + * MAX_FUTURE_BLOCK_TIME. + */ +static const int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME; + class CBlockFileInfo { public: @@ -202,7 +218,7 @@ class CBlockIndex //! Branch ID corresponding to the consensus rules used to validate this block. //! Only cached if block validity is BLOCK_VALID_CONSENSUS. //! Persisted at each activation height, memory-only for intervening blocks. - boost::optional nCachedBranchId; + std::optional nCachedBranchId; //! The anchor for the tree state up to the start of this block uint256 hashSproutAnchor; @@ -211,22 +227,22 @@ class CBlockIndex uint256 hashFinalSproutRoot; //! Change in value held by the Sprout circuit over this block. - //! Will be boost::none for older blocks on old nodes until a reindex has taken place. - boost::optional nSproutValue; + //! Will be std::nullopt for older blocks on old nodes until a reindex has taken place. + std::optional nSproutValue; //! (memory only) Total value held by the Sprout circuit up to and including this block. - //! Will be boost::none for on old nodes until a reindex has taken place. - //! Will be boost::none if nChainTx is zero. - boost::optional nChainSproutValue; + //! Will be std::nullopt for on old nodes until a reindex has taken place. + //! Will be std::nullopt if nChainTx is zero. + std::optional nChainSproutValue; //! Change in value held by the Sapling circuit over this block. - //! Not a boost::optional because this was added before Sapling activated, so we can + //! Not a std::optional because this was added before Sapling activated, so we can //! rely on the invariant that every block before this was added had nSaplingValue = 0. CAmount nSaplingValue; //! (memory only) Total value held by the Sapling circuit up to and including this block. - //! Will be boost::none if nChainTx is zero. - boost::optional nChainSaplingValue; + //! Will be std::nullopt if nChainTx is zero. + std::optional nChainSaplingValue; //! block header int nVersion; @@ -235,8 +251,13 @@ class CBlockIndex unsigned int nTime; unsigned int nBits; uint256 nNonce; +protected: + // The Equihash solution, if it is stored. Once we know that the block index + // entry is present in leveldb, this field can be cleared via the TrimSolution + // method to save memory. std::vector nSolution; +public: //! (memory only) Sequential id assigned to distinguish order in which blocks are received. uint32_t nSequenceId; @@ -253,14 +274,14 @@ class CBlockIndex nTx = 0; nChainTx = 0; nStatus = 0; - nCachedBranchId = boost::none; + nCachedBranchId = std::nullopt; hashSproutAnchor = uint256(); hashFinalSproutRoot = uint256(); nSequenceId = 0; - nSproutValue = boost::none; - nChainSproutValue = boost::none; + nSproutValue = std::nullopt; + nChainSproutValue = std::nullopt; nSaplingValue = 0; - nChainSaplingValue = boost::none; + nChainSaplingValue = std::nullopt; nVersion = 0; hashMerkleRoot = uint256(); @@ -307,23 +328,15 @@ class CBlockIndex return ret; } - CBlockHeader GetBlockHeader() const - { - CBlockHeader block; - block.nVersion = nVersion; - if (pprev) - block.hashPrevBlock = pprev->GetBlockHash(); - block.hashMerkleRoot = hashMerkleRoot; - block.hashFinalSaplingRoot = hashFinalSaplingRoot; - block.nTime = nTime; - block.nBits = nBits; - block.nNonce = nNonce; - block.nSolution = nSolution; - return block; - } + //! Get the block header for this block index. Requires cs_main. + CBlockHeader GetBlockHeader() const; + + //! Clear the Equihash solution to save memory. Requires cs_main. + void TrimSolution(); uint256 GetBlockHash() const { + assert(phashBlock); return *phashBlock; } @@ -350,10 +363,10 @@ class CBlockIndex std::string ToString() const { - return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", + return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s, HasSolution=%s)", pprev, nHeight, hashMerkleRoot.ToString(), - GetBlockHash().ToString()); + phashBlock ? GetBlockHash().ToString() : "(nil)", HasSolution()); } //! Check whether this block index entry is valid up to the passed validity level. @@ -365,6 +378,13 @@ class CBlockIndex return ((nStatus & BLOCK_VALID_MASK) >= nUpTo); } + //! Is the Equihash solution stored? + bool HasSolution() const + { + if (nHeight == 0) return true; // BitcoinZ has empty nSolution inside the genesis block + return !nSolution.empty(); + } + //! Raise the validity level of this block index entry. //! Returns true if the validity was changed. bool RaiseValidity(enum BlockStatus nUpTo) @@ -397,8 +417,11 @@ class CDiskBlockIndex : public CBlockIndex hashPrev = uint256(); } - explicit CDiskBlockIndex(const CBlockIndex* pindex) : CBlockIndex(*pindex) { + explicit CDiskBlockIndex(const CBlockIndex* pindex, std::function()> getSolution) : CBlockIndex(*pindex) { hashPrev = (pprev ? pprev->GetBlockHash() : uint256()); + if (!HasSolution()) { + nSolution = getSolution(); + } } ADD_SERIALIZE_METHODS; @@ -458,20 +481,31 @@ class CDiskBlockIndex : public CBlockIndex // them to CBlockTreeDB::LoadBlockIndexGuts() in txdb.cpp :) } + //! Get the block header for this block index. + CBlockHeader GetBlockHeader() const + { + CBlockHeader header; + header.nVersion = nVersion; + header.hashPrevBlock = hashPrev; + header.hashMerkleRoot = hashMerkleRoot; + header.hashFinalSaplingRoot = hashFinalSaplingRoot; + header.nTime = nTime; + header.nBits = nBits; + header.nNonce = nNonce; + header.nSolution = nSolution; + return header; + } + uint256 GetBlockHash() const { - CBlockHeader block; - block.nVersion = nVersion; - block.hashPrevBlock = hashPrev; - block.hashMerkleRoot = hashMerkleRoot; - block.hashFinalSaplingRoot = hashFinalSaplingRoot; - block.nTime = nTime; - block.nBits = nBits; - block.nNonce = nNonce; - block.nSolution = nSolution; - return block.GetHash(); + return GetBlockHeader().GetHash(); } + std::vector GetSolution() const + { + assert(HasSolution()); + return nSolution; + } std::string ToString() const { @@ -482,6 +516,13 @@ class CDiskBlockIndex : public CBlockIndex hashPrev.ToString()); return str; } + +private: + //! This method should not be called on a CDiskBlockIndex. + void TrimSolution() + { + assert(!"called CDiskBlockIndex::TrimSolution"); + } }; /** An in-memory indexed chain of blocks. */ diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 6dfd29373..92c9d72d6 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -4,14 +4,20 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or https://www.opensource.org/licenses/mit-license.php . +#include "chainparams.h" +#include "consensus/merkle.h" #include "key_io.h" #include "main.h" #include "crypto/equihash.h" +#include "reverse_iterator.h" +#include "tinyformat.h" #include "util.h" #include "utilstrencodings.h" #include +#include +#include #include @@ -40,7 +46,7 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi genesis.nVersion = nVersion; genesis.vtx.push_back(txNew); genesis.hashPrevBlock.SetNull(); - genesis.hashMerkleRoot = genesis.BuildMerkleTree(); + genesis.hashMerkleRoot = BlockMerkleRoot(genesis); return genesis; } @@ -79,11 +85,10 @@ class CMainParams : public CChainParams { strNetworkID = "main"; strCurrencyUnits = "BTCZ"; bip44CoinType = 177; // As registered in https://github.com/satoshilabs/slips/blob/master/slip-0044.md - consensus.fCoinbaseMustBeProtected = true; + consensus.fCoinbaseMustBeShielded = true; consensus.nSubsidySlowStartInterval = 0; consensus.nPreBlossomSubsidyHalvingInterval = Consensus::PRE_BLOSSOM_HALVING_INTERVAL; consensus.nPostBlossomSubsidyHalvingInterval = Consensus::POST_BLOSSOM_HALVING_INTERVAL; - //consensus.nSubsidyHalvingInterval = 840000; consensus.nMajorityEnforceBlockUpgrade = 750; consensus.nMajorityRejectBlockOutdated = 950; consensus.nMajorityWindow = 4000; @@ -94,8 +99,7 @@ class CMainParams : public CChainParams { consensus.nPowMaxAdjustUp = 34; consensus.nPreBlossomPowTargetSpacing = Consensus::PRE_BLOSSOM_POW_TARGET_SPACING; consensus.nPostBlossomPowTargetSpacing = Consensus::POST_BLOSSOM_POW_TARGET_SPACING; - //consensus.nPowTargetSpacing = 2.5 * 60; - consensus.nPowAllowMinDifficultyBlocksAfterHeight = boost::none; + consensus.nPowAllowMinDifficultyBlocksAfterHeight = std::nullopt; consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002; consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = Consensus::NetworkUpgrade::ALWAYS_ACTIVE; @@ -120,9 +124,8 @@ class CMainParams : public CChainParams { pchMessageStart[1] = 0xe9; pchMessageStart[2] = 0x27; pchMessageStart[3] = 0x64; - vAlertPubKey = ParseHex("04d5212ed0303c64db1840e799d31953eb362fd71d8e742dccd9aa78c4713d6d26b44974b44e2ac71aa38b06ef60c020207b85d270e4bdf8c797f3216f969960dc"); + vAlertPubKey = ParseHex("0408f4f463e4018498cfdfc68e44ec92559be4202e2b342bddcab958cd16cdbc9f161a75002088de70e911672a42ffd89ad2024523f14da4bac8950db11b12c2f0"); nDefaultPort = 1989; - nMaxTipAge = 24 * 60 * 60; nPruneAfterHeight = 100000; eh_epoch_1 = eh200_9; eh_epoch_2 = eh144_5; @@ -166,7 +169,7 @@ class CMainParams : public CChainParams { base58Prefixes[EXT_PUBLIC_KEY] = {0x04,0x88,0xB2,0x1E}; base58Prefixes[EXT_SECRET_KEY] = {0x04,0x88,0xAD,0xE4}; // guarantees the first 2 characters, when base58 encoded, are "zc" - base58Prefixes[ZCPAYMENT_ADDRRESS] = {0x16,0x9A}; + base58Prefixes[ZCPAYMENT_ADDRESS] = {0x16,0x9A}; // guarantees the first 4 characters, when base58 encoded, are "ZiVK" base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAB,0xD3}; // guarantees the first 2 characters, when base58 encoded, are "SK" @@ -208,7 +211,6 @@ class CMainParams : public CChainParams { 1530166456, // * UNIX timestamp of last checkpoint block 662217, // * total number of transactions between genesis and last checkpoint - // (the tx=... number in the SetBestChain debug.log lines) 2290.912865 // * estimated number of transactions per day after checkpoint // total number of tx / (checkpoint block height / (24 * 24)) }; @@ -340,11 +342,10 @@ class CTestNetParams : public CChainParams { strNetworkID = "test"; strCurrencyUnits = "TZB"; bip44CoinType = 1; - consensus.fCoinbaseMustBeProtected = true; + consensus.fCoinbaseMustBeShielded = true; consensus.nSubsidySlowStartInterval = 0; consensus.nPreBlossomSubsidyHalvingInterval = Consensus::PRE_BLOSSOM_HALVING_INTERVAL; consensus.nPostBlossomSubsidyHalvingInterval = Consensus::POST_BLOSSOM_HALVING_INTERVAL; - //consensus.nSubsidyHalvingInterval = 840000; consensus.nMajorityEnforceBlockUpgrade = 51; consensus.nMajorityRejectBlockOutdated = 75; consensus.nMajorityWindow = 400; @@ -355,8 +356,7 @@ class CTestNetParams : public CChainParams { consensus.nPowMaxAdjustUp = 34; consensus.nPreBlossomPowTargetSpacing = Consensus::PRE_BLOSSOM_POW_TARGET_SPACING; consensus.nPostBlossomPowTargetSpacing = Consensus::POST_BLOSSOM_POW_TARGET_SPACING; - //consensus.nPowTargetSpacing = 2.5 * 60; - consensus.nPowAllowMinDifficultyBlocksAfterHeight = boost::none; + consensus.nPowAllowMinDifficultyBlocksAfterHeight = 299187; consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002; consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = Consensus::NetworkUpgrade::ALWAYS_ACTIVE; @@ -378,9 +378,8 @@ class CTestNetParams : public CChainParams { pchMessageStart[1] = 0x1a; pchMessageStart[2] = 0xf9; pchMessageStart[3] = 0xbf; - vAlertPubKey = ParseHex("048679fb891b15d0cada9692047fd0ae26ad8bfb83fabddbb50334ee5bc0683294deb410be20513c5af6e7b9cec717ade82b27080ee6ef9a245c36a795ab044bb3"); + vAlertPubKey = ParseHex("04736ee9ddbbede6420b0cff0db9d95a98b89b4e9669a97801f66a2e43ea9a0b46ee3380c41d8270ab649f6fb64f5a3e79c87dce5b62824f2588f01893c91466ee"); nDefaultPort = 11989; - nMaxTipAge = 24 * 60 * 60; nPruneAfterHeight = 1000; eh_epoch_1 = eh200_9; eh_epoch_2 = eh144_5; @@ -418,7 +417,7 @@ class CTestNetParams : public CChainParams { base58Prefixes[EXT_PUBLIC_KEY] = {0x04,0x35,0x87,0xCF}; base58Prefixes[EXT_SECRET_KEY] = {0x04,0x35,0x83,0x94}; // guarantees the first 2 characters, when base58 encoded, are "zt" - base58Prefixes[ZCPAYMENT_ADDRRESS] = {0x16,0xB6}; + base58Prefixes[ZCPAYMENT_ADDRESS] = {0x16,0xB6}; // guarantees the first 4 characters, when base58 encoded, are "ZiVt" base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAC,0x0C}; // guarantees the first 2 characters, when base58 encoded, are "ST" @@ -574,11 +573,10 @@ class CRegTestParams : public CChainParams { strNetworkID = "regtest"; strCurrencyUnits = "REG"; bip44CoinType = 1; - consensus.fCoinbaseMustBeProtected = false; + consensus.fCoinbaseMustBeShielded = false; consensus.nSubsidySlowStartInterval = 0; consensus.nPreBlossomSubsidyHalvingInterval = Consensus::PRE_BLOSSOM_REGTEST_HALVING_INTERVAL; consensus.nPostBlossomSubsidyHalvingInterval = Consensus::POST_BLOSSOM_REGTEST_HALVING_INTERVAL; - //consensus.nSubsidyHalvingInterval = 150; consensus.nMajorityEnforceBlockUpgrade = 750; consensus.nMajorityRejectBlockOutdated = 950; consensus.nMajorityWindow = 1000; @@ -589,7 +587,6 @@ class CRegTestParams : public CChainParams { consensus.nPowMaxAdjustUp = 0; // Turn off adjustment up consensus.nPreBlossomPowTargetSpacing = Consensus::PRE_BLOSSOM_POW_TARGET_SPACING; consensus.nPostBlossomPowTargetSpacing = Consensus::POST_BLOSSOM_POW_TARGET_SPACING; - //consensus.nPowTargetSpacing = 2.5 * 60; consensus.nPowAllowMinDifficultyBlocksAfterHeight = 0; consensus.vUpgrades[Consensus::BASE_SPROUT].nProtocolVersion = 170002; consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = @@ -615,7 +612,6 @@ class CRegTestParams : public CChainParams { pchMessageStart[2] = 0x3f; pchMessageStart[3] = 0x5f; nDefaultPort = 11989; - nMaxTipAge = 24 * 60 * 60; //assert(consensus.hashGenesisBlock == uint256S("0x0575f78ee8dc057deee78ef691876e3be29833aaee5e189bb0459c087451305a")); nPruneAfterHeight = 1000; eh_epoch_1 = eh48_5; @@ -665,7 +661,7 @@ class CRegTestParams : public CChainParams { // do not rely on these BIP32 prefixes; they are not specified and may change base58Prefixes[EXT_PUBLIC_KEY] = {0x04,0x35,0x87,0xCF}; base58Prefixes[EXT_SECRET_KEY] = {0x04,0x35,0x83,0x94}; - base58Prefixes[ZCPAYMENT_ADDRRESS] = {0x16,0xB6}; + base58Prefixes[ZCPAYMENT_ADDRESS] = {0x16,0xB6}; base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAC,0x0C}; base58Prefixes[ZCSPENDING_KEY] = {0xAC,0x08}; @@ -677,109 +673,10 @@ class CRegTestParams : public CChainParams { // Founders reward script expects a vector of 2-of-3 multisig addresses vCommunityFeeAddress = { - "t2FpKCWt95LAPVRed61YbBny9yz5nqexLGN", - "t2RqJNenxiDjC5NiVo84xgfHcYuwsPcpCie", - "t2MsHkAug2oEiqj4L5ZGZH1vHmdogTSb9km", - "t2EwBFfC96DCiCAcJuEqGUbUes8rTNmaD6Q", - "t2JqYXRoTsKb9r1rTLLwDs5jMXzsRBV317k", - "t2RocidGU4ReKPK2uTPYfNFgeZEWDCd3jsj", - "t2Mu8ToNiVow92PfETBk5Z6HWuAEG7RVXVD", - "t2MSLT1n4eQ87QC2FAxMvuTZ84zDzEj7FhQ", - "t2JZNFrWv1c4RqkCmDN9iRkPsG8xAZFdyGS", - "t2AyjEVUCf5jthGHZjwfbztDBHQbztkJB5v", - "t2Gs6dTYCzaFdHSeT91zaFLKmYzyqYY3NnP", - "t2FXfNK7iQhTdMFcGUyrizqXQE5qbmPK6zc", - "t2UqLwQ85pR1fdFMoUzXadXRB97JxP6vTWY", - "t2BocGBq7iBXQP8UQiousNVwU8M6AqUtaRx", - "t2VGGdXhspjF3iQvbWZW2zPNSDRSYauBcM3", - "t2HTNHicoeEXxsX1wVhsqsX3LgzRq2pYgWH", - "t2UiVSyM1vuvs6xP3157ytuYMKN6MuqmgJE", - "t2UmPyNoWSVUgyPzEXzFGN5GS96jMH2kreW", - "t2MQWZJHxZF5zSw6LbZ3S7jqoLX1y6SWLHQ", - "t2VUR1c1aFaTUo93uhi7rfFVRRZaT1aQYbv", - "t2NgLU6QCJhCKgBsR5uX6R4ds82jymzMoMJ", - "t2RorFwMUEb7NamvXFi3jCXitAdRoQtU1Hs", - "t2FFtmwePBnYaRVRVg1wsoBPxDzGMLrz3Jv", - "t2GH3734fKEhPo3NvvAZQazsFf3V51oR4c2", - "t2Ev3twAmUmono3gM2Q6RsfhRiryy7TnX5E", - "t2EmhhAjh6cLpyw6Yc9QEXvsjm7qdKpgFQP", - "t2Gy5N7DYbEZmiHqm3m8Re25a8Bxu7e36ju", - "t2LVSaxizciFWfc5gr1xccHXT115RSnQ13r", - "t28zy3Qiq3FtMeB2PCEysF7R5TgW5UfZN1N", - "t2FcN7o26gRCc8ZuSZcc7X7APPRqWQ5a3W2", - "t27QTHP9qoi5HkiTqx4JV86MGG37aikK51s", - "t2CwQ6H9GPT77nqRwkHCuVcyGvtbhxWHfAk", - "t2HLUDaoimaaSpQhHnvbqpKg6Fi37rAo6cx", - "t2Ebuq1FX7Qzi3ur1FnwsDMvfNBFjqVqDGX", - "t2Bca3HbSbwgQp1ZhzheNvGfpwBoU6Syt8G", - "t2EurfAqyJMsCyx6ujYecQSxrPPY7xxTqcB", - "t2R1kJGeNhLpKx1dKNCnBUq1BkxBVJjQdcp", - "t2M3x9koBJWJS1F9bGtWXTsVfr5pesWSTbR", - "t2La4mEMruVTtBqhndS7zRvmi2WsqWUjPQz", - "t29GwTHLXxYgF5k7SSj7XFaHB7JsocM9bDU", - "t2Awpdv7yG2QFeHeq17J1qCSXRw1AM3mfmz", - "t2BfotpLdNhhewRp9nXpBBYViBaq4y1Lnj5", - "t2F4CH89prySyGZHUiPYJUjnZk9UPXgLBbf", - "t2DNx1KzP8a2S3kZgAPngso9ptva5gE7Jbn", - "t2Eb7orwhjGcu4wYwHBzN5BoXzroPGq3CoM", - "t2BXYmM21WCdHiC1KiwQVHxaTvLQJpqXTvH", - "t27Y6774dwAcCFvYrhDKTXgaxtUewAdZdtz", - "t2JvmRjZnViBZXJJBekDygdvGTCRNWgFEK2", - "t2PL5W7qy1DKNRPWECbaZ6gV9GEzMn8h97Z", - "t2S1JaefdSNwaUexdr6ZtNJhqZS8uDGSNFg", - "t2BTunj4VB44Q22crWpT1ykoBvNGFKMnD7N", - "t2G7DkSoEUJGaEBH6erKsXemoHFqqTRaSiZ", - "t2Ldg8Bc6AWDuESqPgUoumWfCYw3zqKF8s9", - "t2Ft4QMMiJfKXVbhyGBrkwjnfn5ua73VuLo", - "t26xLxd4Fabbotkc9gfFwpCVHoZG1W9rmN7", - "t2DyghJMpK6rRKPEAL3DBKmCntUcj8bUiHg", - "t2RSYhCsgw2AdBiUUyXBCkFf2xE9ddwyESD", - "t26fv5NLiFYXMmfQnvqcJXcYnt5NY41eqrv", - "t2Ppht55eXKC1BX7pfusJxZqbHnkp9oWbBW", - "t2P4AWJ5C4ySU3KzfehAeppH2BV4Y87w34z", - "t28zjDUH2Gkvt8Ytb8UrW7L6G5U1QMwJFM3", - "t2JXDd9pumryTAXqDD98vDLS2ZLSQCNQrYZ", - "t2BNuNGnGq49MZzr7SH8WtEE7sSwZ9n3bsz", - "t2QumKdHZhkFD6ntrzJ9zJAga2QemEgqc9r", - "t2UKz2L7V3C6GTeBPDXmQnwMyqKEbgMpuXg", - "t2CyVugoafiDYpeSNd9DGZEng6Bpr4tqa3d", - "t2GR9eEen8KUDjhQG1opC1aFt27zxdtufnF", - "t2JKYuSRNupdHdTR91tqR4xsaU6friVJJgv", - "t2D2yMZEM3K8ap6iLo3FX2g1Ch9coPSVq2R", - "t2SeFu34eiE2rCPFpxrN8im6ZvcwMpdKnit", - "t2KH46EXQy5wnZHDGVDA7Q13FdRkdQ3LUou", - "t2UsTpuVqP6ZubtN8tQGPnh7Cqjjf1hoefd", - "t2Dd119xiqDbF9QzWwYfnYWUPfqgnL1CNFu", - "t29PjecMhv6EygD8W6smcMHAB8MSHQY3YnQ", - "t2BDZpxgcMRzqgKbDBiXRXrvL3VwD7G8cLc", - "t2MwiKqfCMdy7o96bXvbZ5aGCrRmVfVWVfA", - "t2Vhkny4jNjy6ZD53jeQzsdgZiZyejwRsgY", - "t2K3ouBrLAbYwZv6beoHjzfsE1AbYVa6PuE", - "t2DskMSpWs8i9vK2PhNpi9Mu2qJSvEDi8UZ", - "t2JB2Uz3eVWrxFhas1B1cSXLP22JHbRNYtL", - "t2ArYKW1L8hRoCDK9odNmD4piRwFheErWL1", - "t2K1zKGHrkibiFoYJ5GtfHe5xJecJPEvFwQ", - "t2VnABknMprtMk8y5AdDCBr2R9QZnMhfqSm", - "t2FbjEsP9eeQr5PmP7yC3fopPTuYS9E9VgN", - "t2Sn2XUPZEnFcggB77jvxBqX6LcjdCzcJUs", - "t2SEK3Tw5FYYUaeZcF5QemfeG3tiorrxNKp", - "t2D78THpHVodnhiREjF22A3KRznor5pPnR1", - "t2GyqFdkf6FoQTShEhLGsNrTxAWqmeq4pui", - "t2HnNgFLznEqaokYq8PBV44uzRwAmJXQeKd", - "t2PpHVStdHvWkzXsyuyPYQQq96ZRQu7ALpE", - "t2FHbHM9rKKHZe74HRBNozwNdRsExug8tCw", - "t29tM6DkMPSVp9R3g7UjZjvsobKhsbsRqFL", - "t2K2KixLVJo19phPJMv9ApSiFmxQCSQUvc9", - "t2AWJcGVUMWFC8A9KC3PL7qoCb1vxSzxbJP", - "t26p8FyjHmhqZ6duzhRFLCQcExh1TuCD1sC", - "t27x5n41uRNF3tJkb3Lg1CMomUjTNZwtUfm", - "t2VhRQJ9xeVkVVk7ic21CtDePKmHnrDyF8Z", - "t27hL1iAsTHBPWrdc1qYGSSTc3pTyBqohd4", - "t2RqLYWG8Eo4hopDsn1m8GUoAWtjZQEPE9s", "t2V1osVDkcwYFL4PF9qG8t9Ez1XRVMAkAb6" }; - vCommunityFeeStartHeight = 200; - vCommunityFeeLastHeight = 1400000; + vCommunityFeeStartHeight = 0; + vCommunityFeeLastHeight = 150; assert(vCommunityFeeAddress.size() <= GetLastCommunityFeeBlockHeight()); } @@ -809,27 +706,26 @@ const CChainParams &Params() { return *pCurrentParams; } -CChainParams &Params(CBaseChainParams::Network network) { - switch (network) { - case CBaseChainParams::MAIN: - return mainParams; - case CBaseChainParams::TESTNET: - return testNetParams; - case CBaseChainParams::REGTEST: +CChainParams& Params(const std::string& chain) +{ + if (chain == CBaseChainParams::MAIN) + return mainParams; + else if (chain == CBaseChainParams::TESTNET) + return testNetParams; + else if (chain == CBaseChainParams::REGTEST) return regTestParams; - default: - assert(false && "Unimplemented network"); - return mainParams; - } + else + throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain)); } -void SelectParams(CBaseChainParams::Network network) { +void SelectParams(const std::string& network) +{ SelectBaseParams(network); pCurrentParams = &Params(network); // Some python qa rpc tests need to enforce the coinbase consensus rule - if (network == CBaseChainParams::REGTEST && mapArgs.count("-regtestprotectcoinbase")) { - regTestParams.SetRegTestCoinbaseMustBeProtected(); + if (network == CBaseChainParams::REGTEST && mapArgs.count("-regtestshieldcoinbase")) { + regTestParams.SetRegTestCoinbaseMustBeShielded(); } // When a developer is debugging turnstile violations in regtest mode, enable ZIP209 @@ -838,22 +734,11 @@ void SelectParams(CBaseChainParams::Network network) { } } -bool SelectParamsFromCommandLine() -{ - CBaseChainParams::Network network = NetworkIdFromCommandLine(); - if (network == CBaseChainParams::MAX_NETWORK_TYPES) - return false; - - SelectParams(network); - return true; -} - -// Block height must be >0 and <=last founders reward block height // Block height must be >0 and <=last founders reward block height +// Block height must be >0 and <=last founders reward block height // Index variable i ranges from 0 - (vCommunityFeeAddress.size()-1) std::string CChainParams::GetCommunityFeeAddressAtHeight(int nHeight) const { int preBlossomMaxHeight = GetLastCommunityFeeBlockHeight(); // zip208 - // FounderAddressAdjustedHeight(height) := // height, if not IsBlossomActivated(height) // BlossomActivationHeight + floor((height - BlossomActivationHeight) / BlossomPoWTargetSpacingRatio), otherwise @@ -875,8 +760,8 @@ CScript CChainParams::GetCommunityFeeScriptAtHeight(int nHeight) const { CTxDestination address = DecodeDestination(GetCommunityFeeAddressAtHeight(nHeight).c_str()); assert(IsValidDestination(address)); - assert(boost::get(&address) != nullptr); - CScriptID scriptID = boost::get(address); // address is a boost variant + assert(IsScriptDestination(address)); + CScriptID scriptID = std::get(address); CScript script = CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL; return script; } @@ -933,11 +818,11 @@ bool checkEHParamaters(int solSize, int height, const CChainParams& params) { } int CChainParams::GetFutureBlockTimeWindow(int height) const { - BOOST_REVERSE_FOREACH(const MapFutureBlockTimeWindows::value_type& i, futureBlockTimeWindows) + for (const MapFutureBlockTimeWindows::value_type& i : reverse_iterate(futureBlockTimeWindows)) { if (i.first <= height) { return i.second * 60; } } - return 2 * 60 * 60; + return MAX_FUTURE_BLOCK_TIME; } diff --git a/src/chainparams.h b/src/chainparams.h index 3e81298d0..eaacb138c 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -67,7 +67,7 @@ class CChainParams EXT_PUBLIC_KEY, EXT_SECRET_KEY, - ZCPAYMENT_ADDRRESS, + ZCPAYMENT_ADDRESS, ZCSPENDING_KEY, ZCVIEWING_KEY, @@ -101,7 +101,6 @@ class CChainParams bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; } /** Policy: Filter transactions that do not match well-defined patterns */ bool RequireStandard() const { return fRequireStandard; } - int64_t MaxTipAge() const { return nMaxTipAge; } int64_t PruneAfterHeight() const { return nPruneAfterHeight; } EHparameters eh_epoch_1_params() const { return eh_epoch_1; } @@ -129,7 +128,7 @@ class CChainParams int GetCommunityFeeStartHeight() const { return vCommunityFeeStartHeight; }; int GetLastCommunityFeeBlockHeight() const { return vCommunityFeeLastHeight; } /** Enforce coinbase consensus rule in regtest mode */ - void SetRegTestCoinbaseMustBeProtected() { consensus.fCoinbaseMustBeProtected = true; } + void SetRegTestCoinbaseMustBeShielded() { consensus.fCoinbaseMustBeShielded = true; } int GetFutureBlockTimeWindow(int height) const; int GetRollingCheckpointStartHeight() const { return vRollingCheckpointStartHeight; } protected: @@ -140,7 +139,6 @@ class CChainParams //! Raw pub key bytes for the broadcast alert signing key. std::vector vAlertPubKey; int nDefaultPort = 0; - long nMaxTipAge = 0; uint64_t nPruneAfterHeight = 0; EHparameters eh_epoch_1 = eh200_9; EHparameters eh_epoch_2 = eh144_5; @@ -177,17 +175,16 @@ class CChainParams */ const CChainParams &Params(); -/** Return parameters for the given network. */ -CChainParams &Params(CBaseChainParams::Network network); - -/** Sets the params returned by Params() to those for the given network. */ -void SelectParams(CBaseChainParams::Network network); +/** + * @returns CChainParams for the given BIP70 chain name. + */ +CChainParams& Params(const std::string& chain); /** - * Looks for -regtest or -testnet and then calls SelectParams as appropriate. - * Returns false if an invalid combination is given. + * Sets the params returned by Params() to those for the given BIP70 chain name. + * @throws std::runtime_error when the chain is not supported. */ -bool SelectParamsFromCommandLine(); +void SelectParams(const std::string& chain); /** * Allows modifying the network upgrade regtest parameters. diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 3ed7fa893..84a1f5625 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -5,10 +5,25 @@ #include "chainparamsbase.h" +#include "tinyformat.h" #include "util.h" #include +const std::string CBaseChainParams::MAIN = "main"; +const std::string CBaseChainParams::TESTNET = "test"; +const std::string CBaseChainParams::REGTEST = "regtest"; + +void AppendParamsHelpMessages(std::string& strUsage, bool debugHelp) +{ + strUsage += HelpMessageGroup(_("Chain selection options:")); + strUsage += HelpMessageOpt("-testnet", _("Use the test chain")); + if (debugHelp) { + strUsage += HelpMessageOpt("-regtest", "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. " + "This is intended for regression testing tools and app development."); + } +} + /** * Main network */ @@ -71,31 +86,25 @@ const CBaseChainParams& BaseParams() return *pCurrentBaseParams; } -void SelectBaseParams(CBaseChainParams::Network network) +void SelectBaseParams(const std::string& chain) { - switch (network) { - case CBaseChainParams::MAIN: + if (chain == CBaseChainParams::MAIN) pCurrentBaseParams = &mainParams; - break; - case CBaseChainParams::TESTNET: + else if (chain == CBaseChainParams::TESTNET) pCurrentBaseParams = &testNetParams; - break; - case CBaseChainParams::REGTEST: + else if (chain == CBaseChainParams::REGTEST) pCurrentBaseParams = ®TestParams; - break; - default: - assert(false && "Unimplemented network"); - return; - } + else + throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain)); } -CBaseChainParams::Network NetworkIdFromCommandLine() +std::string ChainNameFromCommandLine() { bool fRegTest = GetBoolArg("-regtest", false); bool fTestNet = GetBoolArg("-testnet", false); if (fTestNet && fRegTest) - return CBaseChainParams::MAX_NETWORK_TYPES; + throw std::runtime_error("Invalid combination of -regtest and -testnet."); if (fRegTest) return CBaseChainParams::REGTEST; if (fTestNet) @@ -103,16 +112,6 @@ CBaseChainParams::Network NetworkIdFromCommandLine() return CBaseChainParams::MAIN; } -bool SelectBaseParamsFromCommandLine() -{ - CBaseChainParams::Network network = NetworkIdFromCommandLine(); - if (network == CBaseChainParams::MAX_NETWORK_TYPES) - return false; - - SelectBaseParams(network); - return true; -} - bool AreBaseParamsConfigured() { return pCurrentBaseParams != NULL; diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index d17e98e01..edb1fa4ca 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -15,13 +15,10 @@ class CBaseChainParams { public: - enum Network { - MAIN, - TESTNET, - REGTEST, - - MAX_NETWORK_TYPES - }; + /** BIP70 chain name strings (main, test or regtest) */ + static const std::string MAIN; + static const std::string TESTNET; + static const std::string REGTEST; const std::string& DataDir() const { return strDataDir; } int RPCPort() const { return nRPCPort; } @@ -33,6 +30,12 @@ class CBaseChainParams std::string strDataDir; }; +/** + * Append the help messages for the chainparams options to the + * parameter string. + */ +void AppendParamsHelpMessages(std::string& strUsage, bool debugHelp=true); + /** * Return the currently selected parameters. This won't change after app * startup, except for unit tests. @@ -40,19 +43,13 @@ class CBaseChainParams const CBaseChainParams& BaseParams(); /** Sets the params returned by Params() to those for the given network. */ -void SelectBaseParams(CBaseChainParams::Network network); - -/** - * Looks for -regtest or -testnet and returns the appropriate Network ID. - * Returns MAX_NETWORK_TYPES if an invalid combination is given. - */ -CBaseChainParams::Network NetworkIdFromCommandLine(); +void SelectBaseParams(const std::string& chain); /** - * Calls NetworkIdFromCommandLine() and then calls SelectParams as appropriate. - * Returns false if an invalid combination is given. + * Looks for -regtest, -testnet and returns the appropriate BIP70 chain name. + * @return CBaseChainParams::MAIN by default; raises runtime error if an invalid combination is given. */ -bool SelectBaseParamsFromCommandLine(); +std::string ChainNameFromCommandLine(); /** * Return true if SelectBaseParamsFromCommandLine() has been called to select diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 3cb619db6..e78a00201 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -6,12 +6,11 @@ #include "chainparams.h" #include "main.h" +#include "reverse_iterator.h" #include "uint256.h" #include -#include - namespace Checkpoints { /** @@ -51,7 +50,7 @@ namespace Checkpoints { fWorkAfter = nExpensiveAfter*fSigcheckVerificationFactor; } - return fWorkBefore / (fWorkBefore + fWorkAfter); + return std::min(fWorkBefore / (fWorkBefore + fWorkAfter), 1.0); } int GetTotalBlocksEstimate(const CCheckpointData& data) @@ -68,7 +67,7 @@ namespace Checkpoints { { const MapCheckpoints& checkpoints = data.mapCheckpoints; - BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints) + for (const MapCheckpoints::value_type& i : reverse_iterate(checkpoints)) { const uint256& hash = i.second; BlockMap::const_iterator t = mapBlockIndex.find(hash); diff --git a/src/checkqueue.h b/src/checkqueue.h index 157b72c3a..e700c1774 100644 --- a/src/checkqueue.h +++ b/src/checkqueue.h @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -119,7 +118,7 @@ class CCheckQueue fOk = fAllOk; } // execute work - BOOST_FOREACH (T& check, vChecks) + for (T& check : vChecks) if (fOk) fOk = check(); vChecks.clear(); @@ -146,7 +145,7 @@ class CCheckQueue void Add(std::vector& vChecks) { boost::unique_lock lock(mutex); - BOOST_FOREACH (T& check, vChecks) { + for (T& check : vChecks) { queue.push_back(T()); check.swap(queue.back()); } diff --git a/src/clientversion.cpp b/src/clientversion.cpp index 6e91697d6..d3863bbaf 100644 --- a/src/clientversion.cpp +++ b/src/clientversion.cpp @@ -19,12 +19,12 @@ * for both bitcoind and bitcoin-core, to make it harder for attackers to * target servers or GUI users specifically. */ -const std::string CLIENT_NAME("YODA-EXT"); +const std::string CLIENT_NAME("BB-8"); /** * Client version number */ -#define CLIENT_VERSION_SUFFIX "1" +#define CLIENT_VERSION_SUFFIX "" /** diff --git a/src/clientversion.h b/src/clientversion.h index be5b3698b..16eb16192 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -18,8 +18,8 @@ //! These need to be macros, as clientversion.cpp's and bitcoin*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 2 #define CLIENT_VERSION_MINOR 0 -#define CLIENT_VERSION_REVISION 8 -#define CLIENT_VERSION_BUILD 50 +#define CLIENT_VERSION_REVISION 9 +#define CLIENT_VERSION_BUILD 26 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true @@ -28,7 +28,7 @@ * Copyright year (2009-this) * Todo: update this when changing our copyright comments in the source */ -#define COPYRIGHT_YEAR 2022 +#define COPYRIGHT_YEAR 2024 #endif //HAVE_CONFIG_H diff --git a/src/coins.cpp b/src/coins.cpp index 6194595e2..a4be3d6bd 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -566,9 +566,9 @@ bool CCoinsViewCache::HaveShieldedRequirements(const CTransaction& tx) const { boost::unordered_map intermediates; - BOOST_FOREACH(const JSDescription &joinsplit, tx.vJoinSplit) + for (const JSDescription &joinsplit : tx.vJoinSplit) { - BOOST_FOREACH(const uint256& nullifier, joinsplit.nullifiers) + for (const uint256& nullifier : joinsplit.nullifiers) { if (GetNullifier(nullifier, SPROUT)) { // If the nullifier is set, this transaction @@ -585,7 +585,7 @@ bool CCoinsViewCache::HaveShieldedRequirements(const CTransaction& tx) const return false; } - BOOST_FOREACH(const uint256& commitment, joinsplit.commitments) + for (const uint256& commitment : joinsplit.commitments) { tree.append(commitment); } @@ -636,7 +636,7 @@ double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const // FIXME: this logic is partially duplicated between here and CreateNewBlock in miner.cpp. double dResult = 0.0; - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) { const CCoins* coins = AccessCoins(txin.prevout.hash); assert(coins); diff --git a/src/coins.h b/src/coins.h index c29c13315..08efd020d 100644 --- a/src/coins.h +++ b/src/coins.h @@ -15,7 +15,6 @@ #include #include -#include #include #include "zcash/IncrementalMerkleTree.hpp" @@ -119,7 +118,7 @@ class CCoins } void ClearUnspendable() { - BOOST_FOREACH(CTxOut &txout, vout) { + for (CTxOut &txout : vout) { if (txout.scriptPubKey.IsUnspendable()) txout.SetNull(); } @@ -227,7 +226,7 @@ class CCoins //! check whether the entire CCoins is spent //! note that only !IsPruned() CCoins can be serialized bool IsPruned() const { - BOOST_FOREACH(const CTxOut &out, vout) + for (const CTxOut &out : vout) if (!out.IsNull()) return false; return true; @@ -235,7 +234,7 @@ class CCoins size_t DynamicMemoryUsage() const { size_t ret = memusage::DynamicUsage(vout); - BOOST_FOREACH(const CTxOut &out, vout) { + for (const CTxOut &out : vout) { ret += RecursiveDynamicUsage(out.scriptPubKey); } return ret; diff --git a/src/compat.h b/src/compat.h index b8c238f22..4d6027c67 100644 --- a/src/compat.h +++ b/src/compat.h @@ -31,6 +31,7 @@ #include #include #include +#include #else #include #include @@ -72,6 +73,15 @@ typedef u_int SOCKET; #else #define MAX_PATH 1024 #endif +#ifdef _MSC_VER +#if !defined(ssize_t) +#ifdef _WIN64 +typedef int64_t ssize_t; +#else +typedef int32_t ssize_t; +#endif +#endif +#endif // As Solaris does not have the MSG_NOSIGNAL flag for send(2) syscall, it is defined as 0 #if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL) diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index 865b280e7..847e5d53a 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -6,6 +6,8 @@ #ifndef BITCOIN_CONSENSUS_CONSENSUS_H #define BITCOIN_CONSENSUS_CONSENSUS_H +#include + /** The minimum allowed block version (network rule) */ static const int32_t MIN_BLOCK_VERSION = 4; /** The minimum allowed transaction version (network rule) */ diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp new file mode 100644 index 000000000..24609131c --- /dev/null +++ b/src/consensus/merkle.cpp @@ -0,0 +1,168 @@ +#include "merkle.h" +#include "hash.h" +#include "utilstrencodings.h" + +/* WARNING! If you're reading this because you're learning about crypto + and/or designing a new system that will use merkle trees, keep in mind + that the following merkle tree algorithm has a serious flaw related to + duplicate txids, resulting in a vulnerability (CVE-2012-2459). + The reason is that if the number of hashes in the list at a given time + is odd, the last one is duplicated before computing the next level (which + is unusual in Merkle trees). This results in certain sequences of + transactions leading to the same merkle root. For example, these two + trees: + A A + / \ / \ + B C B C + / \ | / \ / \ + D E F D E F F + / \ / \ / \ / \ / \ / \ / \ + 1 2 3 4 5 6 1 2 3 4 5 6 5 6 + for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and + 6 are repeated) result in the same root hash A (because the hash of both + of (F) and (F,F) is C). + The vulnerability results from being able to send a block with such a + transaction list, with the same merkle root, and the same block hash as + the original without duplication, resulting in failed validation. If the + receiving node proceeds to mark that block as permanently invalid + however, it will fail to accept further unmodified (and thus potentially + valid) versions of the same block. We defend against this by detecting + the case where we would hash two identical hashes at the end of the list + together, and treating that identically to the block having an invalid + merkle root. Assuming no double-SHA256 collisions, this will detect all + known ways of changing the transactions without affecting the merkle + root. +*/ + +/* This implements a constant-space merkle root/path calculator, limited to 2^32 leaves. */ +static void MerkleComputation(const std::vector& leaves, uint256* proot, bool* pmutated, uint32_t branchpos, std::vector* pbranch) { + if (pbranch) pbranch->clear(); + if (leaves.size() == 0) { + if (pmutated) *pmutated = false; + if (proot) *proot = uint256(); + return; + } + bool mutated = false; + // count is the number of leaves processed so far. + uint32_t count = 0; + // inner is an array of eagerly computed subtree hashes, indexed by tree + // level (0 being the leaves). + // For example, when count is 25 (11001 in binary), inner[4] is the hash of + // the first 16 leaves, inner[3] of the next 8 leaves, and inner[0] equal to + // the last leaf. The other inner entries are undefined. + uint256 inner[32]; + // Which position in inner is a hash that depends on the matching leaf. + int matchlevel = -1; + // First process all leaves into 'inner' values. + while (count < leaves.size()) { + uint256 h = leaves[count]; + bool matchh = count == branchpos; + count++; + int level; + // For each of the lower bits in count that are 0, do 1 step. Each + // corresponds to an inner value that existed before processing the + // current leaf, and each needs a hash to combine it. + for (level = 0; !(count & (((uint32_t)1) << level)); level++) { + if (pbranch) { + if (matchh) { + pbranch->push_back(inner[level]); + } else if (matchlevel == level) { + pbranch->push_back(h); + matchh = true; + } + } + mutated |= (inner[level] == h); + CHash256().Write(inner[level].begin(), 32).Write(h.begin(), 32).Finalize(h.begin()); + } + // Store the resulting hash at inner position level. + inner[level] = h; + if (matchh) { + matchlevel = level; + } + } + // Do a final 'sweep' over the rightmost branch of the tree to process + // odd levels, and reduce everything to a single top value. + // Level is the level (counted from the bottom) up to which we've sweeped. + int level = 0; + // As long as bit number level in count is zero, skip it. It means there + // is nothing left at this level. + while (!(count & (((uint32_t)1) << level))) { + level++; + } + uint256 h = inner[level]; + bool matchh = matchlevel == level; + while (count != (((uint32_t)1) << level)) { + // If we reach this point, h is an inner value that is not the top. + // We combine it with itself (Bitcoin's special rule for odd levels in + // the tree) to produce a higher level one. + if (pbranch && matchh) { + pbranch->push_back(h); + } + CHash256().Write(h.begin(), 32).Write(h.begin(), 32).Finalize(h.begin()); + // Increment count to the value it would have if two entries at this + // level had existed. + count += (((uint32_t)1) << level); + level++; + // And propagate the result upwards accordingly. + while (!(count & (((uint32_t)1) << level))) { + if (pbranch) { + if (matchh) { + pbranch->push_back(inner[level]); + } else if (matchlevel == level) { + pbranch->push_back(h); + matchh = true; + } + } + CHash256().Write(inner[level].begin(), 32).Write(h.begin(), 32).Finalize(h.begin()); + level++; + } + } + // Return result. + if (pmutated) *pmutated = mutated; + if (proot) *proot = h; +} + +uint256 ComputeMerkleRoot(const std::vector& leaves, bool* mutated) { + uint256 hash; + MerkleComputation(leaves, &hash, mutated, -1, NULL); + return hash; +} + +std::vector ComputeMerkleBranch(const std::vector& leaves, uint32_t position) { + std::vector ret; + MerkleComputation(leaves, NULL, NULL, position, &ret); + return ret; +} + +uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector& vMerkleBranch, uint32_t nIndex) { + uint256 hash = leaf; + for (std::vector::const_iterator it = vMerkleBranch.begin(); it != vMerkleBranch.end(); ++it) { + if (nIndex & 1) { + hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash)); + } else { + hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it)); + } + nIndex >>= 1; + } + return hash; +} + +uint256 BlockMerkleRoot(const CBlock& block, bool* mutated) +{ + std::vector leaves; + leaves.resize(block.vtx.size()); + for (size_t s = 0; s < block.vtx.size(); s++) { + leaves[s] = block.vtx[s].GetHash(); + } + return ComputeMerkleRoot(leaves, mutated); +} + +std::vector BlockMerkleBranch(const CBlock& block, uint32_t position) +{ + std::vector leaves; + leaves.resize(block.vtx.size()); + for (size_t s = 0; s < block.vtx.size(); s++) { + leaves[s] = block.vtx[s].GetHash(); + } + return ComputeMerkleBranch(leaves, position); +} diff --git a/src/consensus/merkle.h b/src/consensus/merkle.h new file mode 100644 index 000000000..f50d60ce1 --- /dev/null +++ b/src/consensus/merkle.h @@ -0,0 +1,32 @@ +// Copyright (c) 2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CONSENSUS_MERKLE_H +#define BITCOIN_CONSENSUS_MERKLE_H + +#include +#include + +#include "primitives/transaction.h" +#include "primitives/block.h" +#include "uint256.h" + +uint256 ComputeMerkleRoot(const std::vector& leaves, bool* mutated = NULL); +std::vector ComputeMerkleBranch(const std::vector& leaves, uint32_t position); +uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector& branch, uint32_t position); + +/* + * Compute the Merkle root of the transactions in a block. + * *mutated is set to true if a duplicated subtree was found. + */ +uint256 BlockMerkleRoot(const CBlock& block, bool* mutated = NULL); + +/* + * Compute the Merkle branch for the tree of transactions in a block, for a + * given position. + * This can be verified using ComputeMerkleRootFromBranch. + */ +std::vector BlockMerkleBranch(const CBlock& block, uint32_t position); + +#endif // BITCOIN_CONSENSUS_MERKLE_H diff --git a/src/consensus/params.cpp b/src/consensus/params.cpp index 2974930b3..647dd175c 100644 --- a/src/consensus/params.cpp +++ b/src/consensus/params.cpp @@ -33,32 +33,6 @@ namespace Consensus { } } - int Params::GetLastCommunityFeeBlockHeight(int nHeight) const { - // zip208 - // CommunityFeeLastBlockHeight := max({ height ⦂ N | Halving(height) < 1 }) - // Halving(h) is defined as floor(f(h)) where f is a strictly increasing rational - // function, so it's sufficient to solve for f(height) = 1 in the rationals and - // then take ceiling(height - 1). - // H := blossom activation height; SS := SubsidySlowStartShift(); R := BLOSSOM_POW_TARGET_SPACING_RATIO - // preBlossom: - // 1 = (height - SS) / preInterval - // height = preInterval + SS - // postBlossom: - // 1 = (H - SS) / preInterval + (height - H) / postInterval - // height = H + postInterval - (H - SS) * (postInterval / preInterval) - // height = H + postInterval - (H - SS) * R - // Note: This depends on R being an integer - bool blossomActive = NetworkUpgradeActive(nHeight, Consensus::UPGRADE_BLOSSOM); - if (blossomActive) { - int blossomActivationHeight = vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; - // The following calculation depends on BLOSSOM_POW_TARGET_SPACING_RATIO being an integer. - return blossomActivationHeight + nPostBlossomSubsidyHalvingInterval - - (blossomActivationHeight - SubsidySlowStartShift()) * BLOSSOM_POW_TARGET_SPACING_RATIO - 1; - } else { - return nPreBlossomSubsidyHalvingInterval + SubsidySlowStartShift() - 1; - } - } - int64_t Params::PoWTargetSpacing(int nHeight) const { // zip208 // PoWTargetSpacing(height) := diff --git a/src/consensus/params.h b/src/consensus/params.h index b34d3b72b..192b33c42 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -8,7 +8,8 @@ #include "uint256.h" -#include +#include +#include namespace Consensus { @@ -59,6 +60,18 @@ struct NetworkUpgrade { * should remain disabled on mainnet. */ static constexpr int NO_ACTIVATION_HEIGHT = -1; + + /** + * The hash of the block at height nActivationHeight, if known. This is set manually + * after a network upgrade activates. + * + * We use this in IsInitialBlockDownload to detect whether we are potentially being + * fed a fake alternate chain. We use NU activation blocks for this purpose instead of + * the checkpoint blocks, because network upgrades (should) have significantly more + * scrutiny than regular releases. nMinimumChainWork MUST be set to at least the chain + * work of this block, otherwise this detection will have false positives. + */ + std::optional hashActivationBlock; }; /** ZIP208 block target interval in seconds. */ @@ -85,7 +98,7 @@ struct Params { uint256 hashGenesisBlock; - bool fCoinbaseMustBeProtected; + bool fCoinbaseMustBeShielded; /** Needs to evenly divide MAX_SUBSIDY to avoid rounding errors. */ int nSubsidySlowStartInterval; @@ -97,18 +110,15 @@ struct Params { * * t_s = nSubsidySlowStartInterval * t_r = number of blocks between end of slow start and first halving - * t_h = nSubsidyHalvingInterval + * t_h = nPreBlossomSubsidyHalvingInterval * t_c = SubsidySlowStartShift() */ int SubsidySlowStartShift() const { return nSubsidySlowStartInterval / 2; } - int nSubsidyHalvingInterval; int nPreBlossomSubsidyHalvingInterval; int nPostBlossomSubsidyHalvingInterval; int Halving(int nHeight) const; - int GetLastCommunityFeeBlockHeight(int nHeight) const; - /** Used to check majorities for block version upgrade */ int nMajorityEnforceBlockUpgrade; int nMajorityRejectBlockOutdated; @@ -118,12 +128,13 @@ struct Params { unsigned int nEquihashN = 144; unsigned int nEquihashK = 5; uint256 powLimit; - boost::optional nPowAllowMinDifficultyBlocksAfterHeight; + std::optional nPowAllowMinDifficultyBlocksAfterHeight; int64_t nPowAveragingWindow; int64_t nPowMaxAdjustDown; int64_t nPowMaxAdjustUp; int64_t nPreBlossomPowTargetSpacing; int64_t nPostBlossomPowTargetSpacing; + int64_t PoWTargetSpacing(int nHeight) const; int64_t AveragingWindowTimespan(int nHeight) const; int64_t MinActualTimespan(int nHeight) const; diff --git a/src/consensus/upgrades.cpp b/src/consensus/upgrades.cpp index 9e11e14a8..d171a534a 100644 --- a/src/consensus/upgrades.cpp +++ b/src/consensus/upgrades.cpp @@ -121,9 +121,9 @@ bool IsActivationHeightForAnyUpgrade( return false; } -boost::optional NextEpoch(int nHeight, const Consensus::Params& params) { +std::optional NextEpoch(int nHeight, const Consensus::Params& params) { if (nHeight < 0) { - return boost::none; + return std::nullopt; } // Sprout is never pending @@ -133,16 +133,16 @@ boost::optional NextEpoch(int nHeight, const Consensus::Params& params) { } } - return boost::none; + return std::nullopt; } -boost::optional NextActivationHeight( +std::optional NextActivationHeight( int nHeight, const Consensus::Params& params) { auto idx = NextEpoch(nHeight, params); if (idx) { - return params.vUpgrades[idx.get()].nActivationHeight; + return params.vUpgrades[idx.value()].nActivationHeight; } - return boost::none; + return std::nullopt; } diff --git a/src/consensus/upgrades.h b/src/consensus/upgrades.h index d5bb70b6f..d6e981a0e 100644 --- a/src/consensus/upgrades.h +++ b/src/consensus/upgrades.h @@ -7,7 +7,7 @@ #include "consensus/params.h" -#include +#include enum UpgradeState { UPGRADE_DISABLED, @@ -77,15 +77,15 @@ bool IsActivationHeightForAnyUpgrade( /** * Returns the index of the next upgrade after the given block height, or - * boost::none if there are no more known upgrades. + * std::nullopt if there are no more known upgrades. */ -boost::optional NextEpoch(int nHeight, const Consensus::Params& params); +std::optional NextEpoch(int nHeight, const Consensus::Params& params); /** * Returns the activation height for the next upgrade after the given block height, - * or boost::none if there are no more known upgrades. + * or std::nullopt if there are no more known upgrades. */ -boost::optional NextActivationHeight( +std::optional NextActivationHeight( int nHeight, const Consensus::Params& params); diff --git a/src/core_memusage.h b/src/core_memusage.h index bf955ae4c..d907e6f21 100644 --- a/src/core_memusage.h +++ b/src/core_memusage.h @@ -33,6 +33,9 @@ static inline size_t RecursiveDynamicUsage(const CTransaction& tx) { for (std::vector::const_iterator it = tx.vout.begin(); it != tx.vout.end(); it++) { mem += RecursiveDynamicUsage(*it); } + mem += memusage::DynamicUsage(tx.vJoinSplit); + mem += memusage::DynamicUsage(tx.vShieldedSpend); + mem += memusage::DynamicUsage(tx.vShieldedOutput); return mem; } @@ -44,11 +47,14 @@ static inline size_t RecursiveDynamicUsage(const CMutableTransaction& tx) { for (std::vector::const_iterator it = tx.vout.begin(); it != tx.vout.end(); it++) { mem += RecursiveDynamicUsage(*it); } + mem += memusage::DynamicUsage(tx.vJoinSplit); + mem += memusage::DynamicUsage(tx.vShieldedSpend); + mem += memusage::DynamicUsage(tx.vShieldedOutput); return mem; } static inline size_t RecursiveDynamicUsage(const CBlock& block) { - size_t mem = memusage::DynamicUsage(block.vtx) + memusage::DynamicUsage(block.vMerkleTree); + size_t mem = memusage::DynamicUsage(block.vtx); for (std::vector::const_iterator it = block.vtx.begin(); it != block.vtx.end(); it++) { mem += RecursiveDynamicUsage(*it); } diff --git a/src/core_write.cpp b/src/core_write.cpp index 89a545a99..a94e64658 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -16,7 +16,6 @@ #include "utilstrencodings.h" #include -#include using namespace std; @@ -156,7 +155,7 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry) entry.pushKV("locktime", (int64_t)tx.nLockTime); UniValue vin(UniValue::VARR); - BOOST_FOREACH(const CTxIn& txin, tx.vin) { + for (const CTxIn& txin : tx.vin) { UniValue in(UniValue::VOBJ); if (tx.IsCoinBase()) in.pushKV("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())); diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp new file mode 100644 index 000000000..f8aa928df --- /dev/null +++ b/src/crypto/aes.cpp @@ -0,0 +1,153 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#include "aes.h" +#include "crypto/common.h" + +#include +#include + +extern "C" { +#include "crypto/ctaes/ctaes.c" +} + +AES256Encrypt::AES256Encrypt(const unsigned char key[32]) +{ + AES256_init(&ctx, key); +} + +AES256Encrypt::~AES256Encrypt() +{ + memset(&ctx, 0, sizeof(ctx)); +} + +void AES256Encrypt::Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const +{ + AES256_encrypt(&ctx, 1, ciphertext, plaintext); +} + +AES256Decrypt::AES256Decrypt(const unsigned char key[32]) +{ + AES256_init(&ctx, key); +} + +AES256Decrypt::~AES256Decrypt() +{ + memset(&ctx, 0, sizeof(ctx)); +} + +void AES256Decrypt::Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const +{ + AES256_decrypt(&ctx, 1, plaintext, ciphertext); +} + +template +static int CBCEncrypt(const T& enc, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out) +{ + int written = 0; + int padsize = size % AES_BLOCKSIZE; + unsigned char mixed[AES_BLOCKSIZE]; + + if (!data || !size || !out) + return 0; + + if (!pad && padsize != 0) + return 0; + + memcpy(mixed, iv, AES_BLOCKSIZE); + + // Write all but the last block + while (written + AES_BLOCKSIZE <= size) { + for (int i = 0; i != AES_BLOCKSIZE; i++) + mixed[i] ^= *data++; + enc.Encrypt(out + written, mixed); + memcpy(mixed, out + written, AES_BLOCKSIZE); + written += AES_BLOCKSIZE; + } + if (pad) { + // For all that remains, pad each byte with the value of the remaining + // space. If there is none, pad by a full block. + for (int i = 0; i != padsize; i++) + mixed[i] ^= *data++; + for (int i = padsize; i != AES_BLOCKSIZE; i++) + mixed[i] ^= AES_BLOCKSIZE - padsize; + enc.Encrypt(out + written, mixed); + written += AES_BLOCKSIZE; + } + return written; +} + +template +static int CBCDecrypt(const T& dec, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out) +{ + unsigned char padsize = 0; + int written = 0; + bool fail = false; + const unsigned char* prev = iv; + + if (!data || !size || !out) + return 0; + + if (size % AES_BLOCKSIZE != 0) + return 0; + + // Decrypt all data. Padding will be checked in the output. + while (written != size) { + dec.Decrypt(out, data + written); + for (int i = 0; i != AES_BLOCKSIZE; i++) + *out++ ^= prev[i]; + prev = data + written; + written += AES_BLOCKSIZE; + } + + // When decrypting padding, attempt to run in constant-time + if (pad) { + // If used, padding size is the value of the last decrypted byte. For + // it to be valid, It must be between 1 and AES_BLOCKSIZE. + padsize = *--out; + fail = !padsize | (padsize > AES_BLOCKSIZE); + + // If not well-formed, treat it as though there's no padding. + padsize *= !fail; + + // All padding must equal the last byte otherwise it's not well-formed + for (int i = AES_BLOCKSIZE; i != 0; i--) + fail |= ((i > AES_BLOCKSIZE - padsize) & (*out-- != padsize)); + + written -= padsize; + } + return written * !fail; +} + +AES256CBCEncrypt::AES256CBCEncrypt(const unsigned char key[AES256_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn) + : enc(key), pad(padIn) +{ + memcpy(iv, ivIn, AES_BLOCKSIZE); +} + +int AES256CBCEncrypt::Encrypt(const unsigned char* data, int size, unsigned char* out) const +{ + return CBCEncrypt(enc, iv, data, size, pad, out); +} + +AES256CBCEncrypt::~AES256CBCEncrypt() +{ + memset(iv, 0, sizeof(iv)); +} + +AES256CBCDecrypt::AES256CBCDecrypt(const unsigned char key[AES256_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn) + : dec(key), pad(padIn) +{ + memcpy(iv, ivIn, AES_BLOCKSIZE); +} + +int AES256CBCDecrypt::Decrypt(const unsigned char* data, int size, unsigned char* out) const +{ + return CBCDecrypt(dec, iv, data, size, pad, out); +} + +AES256CBCDecrypt::~AES256CBCDecrypt() +{ + memset(iv, 0, sizeof(iv)); +} diff --git a/src/crypto/aes.h b/src/crypto/aes.h new file mode 100644 index 000000000..d5638ca00 --- /dev/null +++ b/src/crypto/aes.h @@ -0,0 +1,67 @@ +// Copyright (c) 2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . +// +// C++ wrapper around ctaes, a constant-time AES implementation + +#ifndef BITCOIN_CRYPTO_AES_H +#define BITCOIN_CRYPTO_AES_H + +extern "C" { +#include "crypto/ctaes/ctaes.h" +} + +static const int AES_BLOCKSIZE = 16; +static const int AES256_KEYSIZE = 32; + +/** An encryption class for AES-256. */ +class AES256Encrypt +{ +private: + AES256_ctx ctx; + +public: + AES256Encrypt(const unsigned char key[32]); + ~AES256Encrypt(); + void Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const; +}; + +/** A decryption class for AES-256. */ +class AES256Decrypt +{ +private: + AES256_ctx ctx; + +public: + AES256Decrypt(const unsigned char key[32]); + ~AES256Decrypt(); + void Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const; +}; + +class AES256CBCEncrypt +{ +public: + AES256CBCEncrypt(const unsigned char key[AES256_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn); + ~AES256CBCEncrypt(); + int Encrypt(const unsigned char* data, int size, unsigned char* out) const; + +private: + const AES256Encrypt enc; + const bool pad; + unsigned char iv[AES_BLOCKSIZE]; +}; + +class AES256CBCDecrypt +{ +public: + AES256CBCDecrypt(const unsigned char key[AES256_KEYSIZE], const unsigned char ivIn[AES_BLOCKSIZE], bool padIn); + ~AES256CBCDecrypt(); + int Decrypt(const unsigned char* data, int size, unsigned char* out) const; + +private: + const AES256Decrypt dec; + const bool pad; + unsigned char iv[AES_BLOCKSIZE]; +}; + +#endif // BITCOIN_CRYPTO_AES_H diff --git a/src/crypto/common.h b/src/crypto/common.h index fd62087b7..5467c2a92 100644 --- a/src/crypto/common.h +++ b/src/crypto/common.h @@ -17,7 +17,7 @@ #include "compat/endian.h" #if defined(NDEBUG) -# error "Zcash cannot be compiled without assertions." +# error "BitcoinZ cannot be compiled without assertions." #endif uint16_t static inline ReadLE16(const unsigned char* ptr) diff --git a/src/crypto/ctaes/COPYING b/src/crypto/ctaes/COPYING new file mode 100644 index 000000000..415b202a2 --- /dev/null +++ b/src/crypto/ctaes/COPYING @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Pieter Wuille + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/crypto/ctaes/README.md b/src/crypto/ctaes/README.md new file mode 100644 index 000000000..0e7fe1775 --- /dev/null +++ b/src/crypto/ctaes/README.md @@ -0,0 +1,41 @@ +ctaes +===== + +Simple C module for constant-time AES encryption and decryption. + +Features: +* Simple, pure C code without any dependencies. +* No tables or data-dependent branches whatsoever, but using bit sliced approach from https://eprint.iacr.org/2009/129.pdf. +* Very small object code: slightly over 4k of executable code when compiled with -Os. +* Slower than implementations based on precomputed tables or specialized instructions, but can do ~15 MB/s on modern CPUs. + +Performance +----------- + +Compiled with GCC 5.3.1 with -O3, on an Intel(R) Core(TM) i7-4800MQ CPU, numbers in CPU cycles: + +| Algorithm | Key schedule | Encryption per byte | Decryption per byte | +| --------- | ------------:| -------------------:| -------------------:| +| AES-128 | 2.8k | 154 | 161 | +| AES-192 | 3.1k | 169 | 181 | +| AES-256 | 4.0k | 191 | 203 | + +Build steps +----------- + +Object code: + + $ gcc -O3 ctaes.c -c -o ctaes.o + +Tests: + + $ gcc -O3 ctaes.c test.c -o test + +Benchmark: + + $ gcc -O3 ctaes.c bench.c -o bench + +Review +------ + +Results of a formal review of the code can be found in http://bitcoin.sipa.be/ctaes/review.zip diff --git a/src/crypto/ctaes/bench.c b/src/crypto/ctaes/bench.c new file mode 100644 index 000000000..a86df496c --- /dev/null +++ b/src/crypto/ctaes/bench.c @@ -0,0 +1,170 @@ +#include +#include +#include "sys/time.h" + +#include "ctaes.h" + +static double gettimedouble(void) { + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_usec * 0.000001 + tv.tv_sec; +} + +static void print_number(double x) { + double y = x; + int c = 0; + if (y < 0.0) { + y = -y; + } + while (y < 100.0) { + y *= 10.0; + c++; + } + printf("%.*f", c, x); +} + +static void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) { + int i; + double min = HUGE_VAL; + double sum = 0.0; + double max = 0.0; + for (i = 0; i < count; i++) { + double begin, total; + if (setup != NULL) { + setup(data); + } + begin = gettimedouble(); + benchmark(data); + total = gettimedouble() - begin; + if (teardown != NULL) { + teardown(data); + } + if (total < min) { + min = total; + } + if (total > max) { + max = total; + } + sum += total; + } + printf("%s: min ", name); + print_number(min * 1000000000.0 / iter); + printf("ns / avg "); + print_number((sum / count) * 1000000000.0 / iter); + printf("ns / max "); + print_number(max * 1000000000.0 / iter); + printf("ns\n"); +} + +static void bench_AES128_init(void* data) { + AES128_ctx* ctx = (AES128_ctx*)data; + int i; + for (i = 0; i < 50000; i++) { + AES128_init(ctx, (unsigned char*)ctx); + } +} + +static void bench_AES128_encrypt_setup(void* data) { + AES128_ctx* ctx = (AES128_ctx*)data; + static const unsigned char key[16] = {0}; + AES128_init(ctx, key); +} + +static void bench_AES128_encrypt(void* data) { + const AES128_ctx* ctx = (const AES128_ctx*)data; + unsigned char scratch[16] = {0}; + int i; + for (i = 0; i < 4000000 / 16; i++) { + AES128_encrypt(ctx, 1, scratch, scratch); + } +} + +static void bench_AES128_decrypt(void* data) { + const AES128_ctx* ctx = (const AES128_ctx*)data; + unsigned char scratch[16] = {0}; + int i; + for (i = 0; i < 4000000 / 16; i++) { + AES128_decrypt(ctx, 1, scratch, scratch); + } +} + +static void bench_AES192_init(void* data) { + AES192_ctx* ctx = (AES192_ctx*)data; + int i; + for (i = 0; i < 50000; i++) { + AES192_init(ctx, (unsigned char*)ctx); + } +} + +static void bench_AES192_encrypt_setup(void* data) { + AES192_ctx* ctx = (AES192_ctx*)data; + static const unsigned char key[16] = {0}; + AES192_init(ctx, key); +} + +static void bench_AES192_encrypt(void* data) { + const AES192_ctx* ctx = (const AES192_ctx*)data; + unsigned char scratch[16] = {0}; + int i; + for (i = 0; i < 4000000 / 16; i++) { + AES192_encrypt(ctx, 1, scratch, scratch); + } +} + +static void bench_AES192_decrypt(void* data) { + const AES192_ctx* ctx = (const AES192_ctx*)data; + unsigned char scratch[16] = {0}; + int i; + for (i = 0; i < 4000000 / 16; i++) { + AES192_decrypt(ctx, 1, scratch, scratch); + } +} + +static void bench_AES256_init(void* data) { + AES256_ctx* ctx = (AES256_ctx*)data; + int i; + for (i = 0; i < 50000; i++) { + AES256_init(ctx, (unsigned char*)ctx); + } +} + + +static void bench_AES256_encrypt_setup(void* data) { + AES256_ctx* ctx = (AES256_ctx*)data; + static const unsigned char key[16] = {0}; + AES256_init(ctx, key); +} + +static void bench_AES256_encrypt(void* data) { + const AES256_ctx* ctx = (const AES256_ctx*)data; + unsigned char scratch[16] = {0}; + int i; + for (i = 0; i < 4000000 / 16; i++) { + AES256_encrypt(ctx, 1, scratch, scratch); + } +} + +static void bench_AES256_decrypt(void* data) { + const AES256_ctx* ctx = (const AES256_ctx*)data; + unsigned char scratch[16] = {0}; + int i; + for (i = 0; i < 4000000 / 16; i++) { + AES256_decrypt(ctx, 1, scratch, scratch); + } +} + +int main(void) { + AES128_ctx ctx128; + AES192_ctx ctx192; + AES256_ctx ctx256; + run_benchmark("aes128_init", bench_AES128_init, NULL, NULL, &ctx128, 20, 50000); + run_benchmark("aes128_encrypt_byte", bench_AES128_encrypt, bench_AES128_encrypt_setup, NULL, &ctx128, 20, 4000000); + run_benchmark("aes128_decrypt_byte", bench_AES128_decrypt, bench_AES128_encrypt_setup, NULL, &ctx128, 20, 4000000); + run_benchmark("aes192_init", bench_AES192_init, NULL, NULL, &ctx192, 20, 50000); + run_benchmark("aes192_encrypt_byte", bench_AES192_encrypt, bench_AES192_encrypt_setup, NULL, &ctx192, 20, 4000000); + run_benchmark("aes192_decrypt_byte", bench_AES192_decrypt, bench_AES192_encrypt_setup, NULL, &ctx192, 20, 4000000); + run_benchmark("aes256_init", bench_AES256_init, NULL, NULL, &ctx256, 20, 50000); + run_benchmark("aes256_encrypt_byte", bench_AES256_encrypt, bench_AES256_encrypt_setup, NULL, &ctx256, 20, 4000000); + run_benchmark("aes256_decrypt_byte", bench_AES256_decrypt, bench_AES256_encrypt_setup, NULL, &ctx256, 20, 4000000); + return 0; +} diff --git a/src/crypto/ctaes/ctaes.c b/src/crypto/ctaes/ctaes.c new file mode 100644 index 000000000..f20d4a96f --- /dev/null +++ b/src/crypto/ctaes/ctaes.c @@ -0,0 +1,556 @@ + /*********************************************************************** + * Copyright (c) 2016 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php .* + ************************************************************************/ + +/* Constant time, unoptimized, concise, plain C, AES implementation + * Based On: + * Emilia Kasper and Peter Schwabe, Faster and Timing-Attack Resistant AES-GCM + * http://www.iacr.org/archive/ches2009/57470001/57470001.pdf + * But using 8 16-bit integers representing a single AES state rather than 8 128-bit + * integers representing 8 AES states. + */ + +#include "ctaes.h" + +/* Slice variable slice_i contains the i'th bit of the 16 state variables in this order: + * 0 1 2 3 + * 4 5 6 7 + * 8 9 10 11 + * 12 13 14 15 + */ + +/** Convert a byte to sliced form, storing it corresponding to given row and column in s */ +static void LoadByte(AES_state* s, unsigned char byte, int r, int c) { + int i; + for (i = 0; i < 8; i++) { + s->slice[i] |= (byte & 1) << (r * 4 + c); + byte >>= 1; + } +} + +/** Load 16 bytes of data into 8 sliced integers */ +static void LoadBytes(AES_state *s, const unsigned char* data16) { + int c; + for (c = 0; c < 4; c++) { + int r; + for (r = 0; r < 4; r++) { + LoadByte(s, *(data16++), r, c); + } + } +} + +/** Convert 8 sliced integers into 16 bytes of data */ +static void SaveBytes(unsigned char* data16, const AES_state *s) { + int c; + for (c = 0; c < 4; c++) { + int r; + for (r = 0; r < 4; r++) { + int b; + uint8_t v = 0; + for (b = 0; b < 8; b++) { + v |= ((s->slice[b] >> (r * 4 + c)) & 1) << b; + } + *(data16++) = v; + } + } +} + +/* S-box implementation based on the gate logic from: + * Joan Boyar and Rene Peralta, A depth-16 circuit for the AES S-box. + * https://eprint.iacr.org/2011/332.pdf +*/ +static void SubBytes(AES_state *s, int inv) { + /* Load the bit slices */ + uint16_t U0 = s->slice[7], U1 = s->slice[6], U2 = s->slice[5], U3 = s->slice[4]; + uint16_t U4 = s->slice[3], U5 = s->slice[2], U6 = s->slice[1], U7 = s->slice[0]; + + uint16_t T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16; + uint16_t T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, D; + uint16_t M1, M6, M11, M13, M15, M20, M21, M22, M23, M25, M37, M38, M39, M40; + uint16_t M41, M42, M43, M44, M45, M46, M47, M48, M49, M50, M51, M52, M53, M54; + uint16_t M55, M56, M57, M58, M59, M60, M61, M62, M63; + + if (inv) { + uint16_t R5, R13, R17, R18, R19; + /* Undo linear postprocessing */ + T23 = U0 ^ U3; + T22 = ~(U1 ^ U3); + T2 = ~(U0 ^ U1); + T1 = U3 ^ U4; + T24 = ~(U4 ^ U7); + R5 = U6 ^ U7; + T8 = ~(U1 ^ T23); + T19 = T22 ^ R5; + T9 = ~(U7 ^ T1); + T10 = T2 ^ T24; + T13 = T2 ^ R5; + T3 = T1 ^ R5; + T25 = ~(U2 ^ T1); + R13 = U1 ^ U6; + T17 = ~(U2 ^ T19); + T20 = T24 ^ R13; + T4 = U4 ^ T8; + R17 = ~(U2 ^ U5); + R18 = ~(U5 ^ U6); + R19 = ~(U2 ^ U4); + D = U0 ^ R17; + T6 = T22 ^ R17; + T16 = R13 ^ R19; + T27 = T1 ^ R18; + T15 = T10 ^ T27; + T14 = T10 ^ R18; + T26 = T3 ^ T16; + } else { + /* Linear preprocessing. */ + T1 = U0 ^ U3; + T2 = U0 ^ U5; + T3 = U0 ^ U6; + T4 = U3 ^ U5; + T5 = U4 ^ U6; + T6 = T1 ^ T5; + T7 = U1 ^ U2; + T8 = U7 ^ T6; + T9 = U7 ^ T7; + T10 = T6 ^ T7; + T11 = U1 ^ U5; + T12 = U2 ^ U5; + T13 = T3 ^ T4; + T14 = T6 ^ T11; + T15 = T5 ^ T11; + T16 = T5 ^ T12; + T17 = T9 ^ T16; + T18 = U3 ^ U7; + T19 = T7 ^ T18; + T20 = T1 ^ T19; + T21 = U6 ^ U7; + T22 = T7 ^ T21; + T23 = T2 ^ T22; + T24 = T2 ^ T10; + T25 = T20 ^ T17; + T26 = T3 ^ T16; + T27 = T1 ^ T12; + D = U7; + } + + /* Non-linear transformation (shared between the forward and backward case) */ + M1 = T13 & T6; + M6 = T3 & T16; + M11 = T1 & T15; + M13 = (T4 & T27) ^ M11; + M15 = (T2 & T10) ^ M11; + M20 = T14 ^ M1 ^ (T23 & T8) ^ M13; + M21 = (T19 & D) ^ M1 ^ T24 ^ M15; + M22 = T26 ^ M6 ^ (T22 & T9) ^ M13; + M23 = (T20 & T17) ^ M6 ^ M15 ^ T25; + M25 = M22 & M20; + M37 = M21 ^ ((M20 ^ M21) & (M23 ^ M25)); + M38 = M20 ^ M25 ^ (M21 | (M20 & M23)); + M39 = M23 ^ ((M22 ^ M23) & (M21 ^ M25)); + M40 = M22 ^ M25 ^ (M23 | (M21 & M22)); + M41 = M38 ^ M40; + M42 = M37 ^ M39; + M43 = M37 ^ M38; + M44 = M39 ^ M40; + M45 = M42 ^ M41; + M46 = M44 & T6; + M47 = M40 & T8; + M48 = M39 & D; + M49 = M43 & T16; + M50 = M38 & T9; + M51 = M37 & T17; + M52 = M42 & T15; + M53 = M45 & T27; + M54 = M41 & T10; + M55 = M44 & T13; + M56 = M40 & T23; + M57 = M39 & T19; + M58 = M43 & T3; + M59 = M38 & T22; + M60 = M37 & T20; + M61 = M42 & T1; + M62 = M45 & T4; + M63 = M41 & T2; + + if (inv){ + /* Undo linear preprocessing */ + uint16_t P0 = M52 ^ M61; + uint16_t P1 = M58 ^ M59; + uint16_t P2 = M54 ^ M62; + uint16_t P3 = M47 ^ M50; + uint16_t P4 = M48 ^ M56; + uint16_t P5 = M46 ^ M51; + uint16_t P6 = M49 ^ M60; + uint16_t P7 = P0 ^ P1; + uint16_t P8 = M50 ^ M53; + uint16_t P9 = M55 ^ M63; + uint16_t P10 = M57 ^ P4; + uint16_t P11 = P0 ^ P3; + uint16_t P12 = M46 ^ M48; + uint16_t P13 = M49 ^ M51; + uint16_t P14 = M49 ^ M62; + uint16_t P15 = M54 ^ M59; + uint16_t P16 = M57 ^ M61; + uint16_t P17 = M58 ^ P2; + uint16_t P18 = M63 ^ P5; + uint16_t P19 = P2 ^ P3; + uint16_t P20 = P4 ^ P6; + uint16_t P22 = P2 ^ P7; + uint16_t P23 = P7 ^ P8; + uint16_t P24 = P5 ^ P7; + uint16_t P25 = P6 ^ P10; + uint16_t P26 = P9 ^ P11; + uint16_t P27 = P10 ^ P18; + uint16_t P28 = P11 ^ P25; + uint16_t P29 = P15 ^ P20; + s->slice[7] = P13 ^ P22; + s->slice[6] = P26 ^ P29; + s->slice[5] = P17 ^ P28; + s->slice[4] = P12 ^ P22; + s->slice[3] = P23 ^ P27; + s->slice[2] = P19 ^ P24; + s->slice[1] = P14 ^ P23; + s->slice[0] = P9 ^ P16; + } else { + /* Linear postprocessing */ + uint16_t L0 = M61 ^ M62; + uint16_t L1 = M50 ^ M56; + uint16_t L2 = M46 ^ M48; + uint16_t L3 = M47 ^ M55; + uint16_t L4 = M54 ^ M58; + uint16_t L5 = M49 ^ M61; + uint16_t L6 = M62 ^ L5; + uint16_t L7 = M46 ^ L3; + uint16_t L8 = M51 ^ M59; + uint16_t L9 = M52 ^ M53; + uint16_t L10 = M53 ^ L4; + uint16_t L11 = M60 ^ L2; + uint16_t L12 = M48 ^ M51; + uint16_t L13 = M50 ^ L0; + uint16_t L14 = M52 ^ M61; + uint16_t L15 = M55 ^ L1; + uint16_t L16 = M56 ^ L0; + uint16_t L17 = M57 ^ L1; + uint16_t L18 = M58 ^ L8; + uint16_t L19 = M63 ^ L4; + uint16_t L20 = L0 ^ L1; + uint16_t L21 = L1 ^ L7; + uint16_t L22 = L3 ^ L12; + uint16_t L23 = L18 ^ L2; + uint16_t L24 = L15 ^ L9; + uint16_t L25 = L6 ^ L10; + uint16_t L26 = L7 ^ L9; + uint16_t L27 = L8 ^ L10; + uint16_t L28 = L11 ^ L14; + uint16_t L29 = L11 ^ L17; + s->slice[7] = L6 ^ L24; + s->slice[6] = ~(L16 ^ L26); + s->slice[5] = ~(L19 ^ L28); + s->slice[4] = L6 ^ L21; + s->slice[3] = L20 ^ L22; + s->slice[2] = L25 ^ L29; + s->slice[1] = ~(L13 ^ L27); + s->slice[0] = ~(L6 ^ L23); + } +} + +#define BIT_RANGE(from,to) (((1 << ((to) - (from))) - 1) << (from)) + +#define BIT_RANGE_LEFT(x,from,to,shift) (((x) & BIT_RANGE((from), (to))) << (shift)) +#define BIT_RANGE_RIGHT(x,from,to,shift) (((x) & BIT_RANGE((from), (to))) >> (shift)) + +static void ShiftRows(AES_state* s) { + int i; + for (i = 0; i < 8; i++) { + uint16_t v = s->slice[i]; + s->slice[i] = + (v & BIT_RANGE(0, 4)) | + BIT_RANGE_LEFT(v, 4, 5, 3) | BIT_RANGE_RIGHT(v, 5, 8, 1) | + BIT_RANGE_LEFT(v, 8, 10, 2) | BIT_RANGE_RIGHT(v, 10, 12, 2) | + BIT_RANGE_LEFT(v, 12, 15, 1) | BIT_RANGE_RIGHT(v, 15, 16, 3); + } +} + +static void InvShiftRows(AES_state* s) { + int i; + for (i = 0; i < 8; i++) { + uint16_t v = s->slice[i]; + s->slice[i] = + (v & BIT_RANGE(0, 4)) | + BIT_RANGE_LEFT(v, 4, 7, 1) | BIT_RANGE_RIGHT(v, 7, 8, 3) | + BIT_RANGE_LEFT(v, 8, 10, 2) | BIT_RANGE_RIGHT(v, 10, 12, 2) | + BIT_RANGE_LEFT(v, 12, 13, 3) | BIT_RANGE_RIGHT(v, 13, 16, 1); + } +} + +#define ROT(x,b) (((x) >> ((b) * 4)) | ((x) << ((4-(b)) * 4))) + +static void MixColumns(AES_state* s, int inv) { + /* The MixColumns transform treats the bytes of the columns of the state as + * coefficients of a 3rd degree polynomial over GF(2^8) and multiplies them + * by the fixed polynomial a(x) = {03}x^3 + {01}x^2 + {01}x + {02}, modulo + * x^4 + {01}. + * + * In the inverse transform, we multiply by the inverse of a(x), + * a^-1(x) = {0b}x^3 + {0d}x^2 + {09}x + {0e}. This is equal to + * a(x) * ({04}x^2 + {05}), so we can reuse the forward transform's code + * (found in OpenSSL's bsaes-x86_64.pl, attributed to Jussi Kivilinna) + * + * In the bitsliced representation, a multiplication of every column by x + * mod x^4 + 1 is simply a right rotation. + */ + + /* Shared for both directions is a multiplication by a(x), which can be + * rewritten as (x^3 + x^2 + x) + {02}*(x^3 + {01}). + * + * First compute s into the s? variables, (x^3 + {01}) * s into the s?_01 + * variables and (x^3 + x^2 + x)*s into the s?_123 variables. + */ + uint16_t s0 = s->slice[0], s1 = s->slice[1], s2 = s->slice[2], s3 = s->slice[3]; + uint16_t s4 = s->slice[4], s5 = s->slice[5], s6 = s->slice[6], s7 = s->slice[7]; + uint16_t s0_01 = s0 ^ ROT(s0, 1), s0_123 = ROT(s0_01, 1) ^ ROT(s0, 3); + uint16_t s1_01 = s1 ^ ROT(s1, 1), s1_123 = ROT(s1_01, 1) ^ ROT(s1, 3); + uint16_t s2_01 = s2 ^ ROT(s2, 1), s2_123 = ROT(s2_01, 1) ^ ROT(s2, 3); + uint16_t s3_01 = s3 ^ ROT(s3, 1), s3_123 = ROT(s3_01, 1) ^ ROT(s3, 3); + uint16_t s4_01 = s4 ^ ROT(s4, 1), s4_123 = ROT(s4_01, 1) ^ ROT(s4, 3); + uint16_t s5_01 = s5 ^ ROT(s5, 1), s5_123 = ROT(s5_01, 1) ^ ROT(s5, 3); + uint16_t s6_01 = s6 ^ ROT(s6, 1), s6_123 = ROT(s6_01, 1) ^ ROT(s6, 3); + uint16_t s7_01 = s7 ^ ROT(s7, 1), s7_123 = ROT(s7_01, 1) ^ ROT(s7, 3); + /* Now compute s = s?_123 + {02} * s?_01. */ + s->slice[0] = s7_01 ^ s0_123; + s->slice[1] = s7_01 ^ s0_01 ^ s1_123; + s->slice[2] = s1_01 ^ s2_123; + s->slice[3] = s7_01 ^ s2_01 ^ s3_123; + s->slice[4] = s7_01 ^ s3_01 ^ s4_123; + s->slice[5] = s4_01 ^ s5_123; + s->slice[6] = s5_01 ^ s6_123; + s->slice[7] = s6_01 ^ s7_123; + if (inv) { + /* In the reverse direction, we further need to multiply by + * {04}x^2 + {05}, which can be written as {04} * (x^2 + {01}) + {01}. + * + * First compute (x^2 + {01}) * s into the t?_02 variables: */ + uint16_t t0_02 = s->slice[0] ^ ROT(s->slice[0], 2); + uint16_t t1_02 = s->slice[1] ^ ROT(s->slice[1], 2); + uint16_t t2_02 = s->slice[2] ^ ROT(s->slice[2], 2); + uint16_t t3_02 = s->slice[3] ^ ROT(s->slice[3], 2); + uint16_t t4_02 = s->slice[4] ^ ROT(s->slice[4], 2); + uint16_t t5_02 = s->slice[5] ^ ROT(s->slice[5], 2); + uint16_t t6_02 = s->slice[6] ^ ROT(s->slice[6], 2); + uint16_t t7_02 = s->slice[7] ^ ROT(s->slice[7], 2); + /* And then update s += {04} * t?_02 */ + s->slice[0] ^= t6_02; + s->slice[1] ^= t6_02 ^ t7_02; + s->slice[2] ^= t0_02 ^ t7_02; + s->slice[3] ^= t1_02 ^ t6_02; + s->slice[4] ^= t2_02 ^ t6_02 ^ t7_02; + s->slice[5] ^= t3_02 ^ t7_02; + s->slice[6] ^= t4_02; + s->slice[7] ^= t5_02; + } +} + +static void AddRoundKey(AES_state* s, const AES_state* round) { + int b; + for (b = 0; b < 8; b++) { + s->slice[b] ^= round->slice[b]; + } +} + +/** column_0(s) = column_c(a) */ +static void GetOneColumn(AES_state* s, const AES_state* a, int c) { + int b; + for (b = 0; b < 8; b++) { + s->slice[b] = (a->slice[b] >> c) & 0x1111; + } +} + +/** column_c1(r) |= (column_0(s) ^= column_c2(a)) */ +static void KeySetupColumnMix(AES_state* s, AES_state* r, const AES_state* a, int c1, int c2) { + int b; + for (b = 0; b < 8; b++) { + r->slice[b] |= ((s->slice[b] ^= ((a->slice[b] >> c2) & 0x1111)) & 0x1111) << c1; + } +} + +/** Rotate the rows in s one position upwards, and xor in r */ +static void KeySetupTransform(AES_state* s, const AES_state* r) { + int b; + for (b = 0; b < 8; b++) { + s->slice[b] = ((s->slice[b] >> 4) | (s->slice[b] << 12)) ^ r->slice[b]; + } +} + +/* Multiply the cells in s by x, as polynomials over GF(2) mod x^8 + x^4 + x^3 + x + 1 */ +static void MultX(AES_state* s) { + uint16_t top = s->slice[7]; + s->slice[7] = s->slice[6]; + s->slice[6] = s->slice[5]; + s->slice[5] = s->slice[4]; + s->slice[4] = s->slice[3] ^ top; + s->slice[3] = s->slice[2] ^ top; + s->slice[2] = s->slice[1]; + s->slice[1] = s->slice[0] ^ top; + s->slice[0] = top; +} + +/** Expand the cipher key into the key schedule. + * + * state must be a pointer to an array of size nrounds + 1. + * key must be a pointer to 4 * nkeywords bytes. + * + * AES128 uses nkeywords = 4, nrounds = 10 + * AES192 uses nkeywords = 6, nrounds = 12 + * AES256 uses nkeywords = 8, nrounds = 14 + */ +static void AES_setup(AES_state* rounds, const uint8_t* key, int nkeywords, int nrounds) +{ + int i; + + /* The one-byte round constant */ + AES_state rcon = {{1,0,0,0,0,0,0,0}}; + /* The number of the word being generated, modulo nkeywords */ + int pos = 0; + /* The column representing the word currently being processed */ + AES_state column; + + for (i = 0; i < nrounds + 1; i++) { + int b; + for (b = 0; b < 8; b++) { + rounds[i].slice[b] = 0; + } + } + + /* The first nkeywords round columns are just taken from the key directly. */ + for (i = 0; i < nkeywords; i++) { + int r; + for (r = 0; r < 4; r++) { + LoadByte(&rounds[i >> 2], *(key++), r, i & 3); + } + } + + GetOneColumn(&column, &rounds[(nkeywords - 1) >> 2], (nkeywords - 1) & 3); + + for (i = nkeywords; i < 4 * (nrounds + 1); i++) { + /* Transform column */ + if (pos == 0) { + SubBytes(&column, 0); + KeySetupTransform(&column, &rcon); + MultX(&rcon); + } else if (nkeywords > 6 && pos == 4) { + SubBytes(&column, 0); + } + if (++pos == nkeywords) pos = 0; + KeySetupColumnMix(&column, &rounds[i >> 2], &rounds[(i - nkeywords) >> 2], i & 3, (i - nkeywords) & 3); + } +} + +static void AES_encrypt(const AES_state* rounds, int nrounds, unsigned char* cipher16, const unsigned char* plain16) { + AES_state s = {{0}}; + int round; + + LoadBytes(&s, plain16); + AddRoundKey(&s, rounds++); + + for (round = 1; round < nrounds; round++) { + SubBytes(&s, 0); + ShiftRows(&s); + MixColumns(&s, 0); + AddRoundKey(&s, rounds++); + } + + SubBytes(&s, 0); + ShiftRows(&s); + AddRoundKey(&s, rounds); + + SaveBytes(cipher16, &s); +} + +static void AES_decrypt(const AES_state* rounds, int nrounds, unsigned char* plain16, const unsigned char* cipher16) { + /* Most AES decryption implementations use the alternate scheme + * (the Equivalent Inverse Cipher), which allows for more code reuse between + * the encryption and decryption code, but requires separate setup for both. + */ + AES_state s = {{0}}; + int round; + + rounds += nrounds; + + LoadBytes(&s, cipher16); + AddRoundKey(&s, rounds--); + + for (round = 1; round < nrounds; round++) { + InvShiftRows(&s); + SubBytes(&s, 1); + AddRoundKey(&s, rounds--); + MixColumns(&s, 1); + } + + InvShiftRows(&s); + SubBytes(&s, 1); + AddRoundKey(&s, rounds); + + SaveBytes(plain16, &s); +} + +void AES128_init(AES128_ctx* ctx, const unsigned char* key16) { + AES_setup(ctx->rk, key16, 4, 10); +} + +void AES128_encrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) { + while (blocks--) { + AES_encrypt(ctx->rk, 10, cipher16, plain16); + cipher16 += 16; + plain16 += 16; + } +} + +void AES128_decrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) { + while (blocks--) { + AES_decrypt(ctx->rk, 10, plain16, cipher16); + cipher16 += 16; + plain16 += 16; + } +} + +void AES192_init(AES192_ctx* ctx, const unsigned char* key24) { + AES_setup(ctx->rk, key24, 6, 12); +} + +void AES192_encrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) { + while (blocks--) { + AES_encrypt(ctx->rk, 12, cipher16, plain16); + cipher16 += 16; + plain16 += 16; + } + +} + +void AES192_decrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) { + while (blocks--) { + AES_decrypt(ctx->rk, 12, plain16, cipher16); + cipher16 += 16; + plain16 += 16; + } +} + +void AES256_init(AES256_ctx* ctx, const unsigned char* key32) { + AES_setup(ctx->rk, key32, 8, 14); +} + +void AES256_encrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16) { + while (blocks--) { + AES_encrypt(ctx->rk, 14, cipher16, plain16); + cipher16 += 16; + plain16 += 16; + } +} + +void AES256_decrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16) { + while (blocks--) { + AES_decrypt(ctx->rk, 14, plain16, cipher16); + cipher16 += 16; + plain16 += 16; + } +} diff --git a/src/crypto/ctaes/ctaes.h b/src/crypto/ctaes/ctaes.h new file mode 100644 index 000000000..8a0a5a103 --- /dev/null +++ b/src/crypto/ctaes/ctaes.h @@ -0,0 +1,41 @@ + /*********************************************************************** + * Copyright (c) 2016 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php .* + ************************************************************************/ + +#ifndef _CTAES_H_ +#define _CTAES_H_ 1 + +#include +#include + +typedef struct { + uint16_t slice[8]; +} AES_state; + +typedef struct { + AES_state rk[11]; +} AES128_ctx; + +typedef struct { + AES_state rk[13]; +} AES192_ctx; + +typedef struct { + AES_state rk[15]; +} AES256_ctx; + +void AES128_init(AES128_ctx* ctx, const unsigned char* key16); +void AES128_encrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16); +void AES128_decrypt(const AES128_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16); + +void AES192_init(AES192_ctx* ctx, const unsigned char* key24); +void AES192_encrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16); +void AES192_decrypt(const AES192_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16); + +void AES256_init(AES256_ctx* ctx, const unsigned char* key32); +void AES256_encrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* cipher16, const unsigned char* plain16); +void AES256_decrypt(const AES256_ctx* ctx, size_t blocks, unsigned char* plain16, const unsigned char* cipher16); + +#endif diff --git a/src/crypto/ctaes/test.c b/src/crypto/ctaes/test.c new file mode 100644 index 000000000..7fe481e48 --- /dev/null +++ b/src/crypto/ctaes/test.c @@ -0,0 +1,110 @@ + /*********************************************************************** + * Copyright (c) 2016 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php .* + ************************************************************************/ + +#include "ctaes.h" + +#include +#include +#include + +typedef struct { + int keysize; + const char* key; + const char* plain; + const char* cipher; +} ctaes_test; + +static const ctaes_test ctaes_tests[] = { + /* AES test vectors from FIPS 197. */ + {128, "000102030405060708090a0b0c0d0e0f", "00112233445566778899aabbccddeeff", "69c4e0d86a7b0430d8cdb78070b4c55a"}, + {192, "000102030405060708090a0b0c0d0e0f1011121314151617", "00112233445566778899aabbccddeeff", "dda97ca4864cdfe06eaf70a0ec0d7191"}, + {256, "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "00112233445566778899aabbccddeeff", "8ea2b7ca516745bfeafc49904b496089"}, + + /* AES-ECB test vectors from NIST sp800-38a. */ + {128, "2b7e151628aed2a6abf7158809cf4f3c", "6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97"}, + {128, "2b7e151628aed2a6abf7158809cf4f3c", "ae2d8a571e03ac9c9eb76fac45af8e51", "f5d3d58503b9699de785895a96fdbaaf"}, + {128, "2b7e151628aed2a6abf7158809cf4f3c", "30c81c46a35ce411e5fbc1191a0a52ef", "43b1cd7f598ece23881b00e3ed030688"}, + {128, "2b7e151628aed2a6abf7158809cf4f3c", "f69f2445df4f9b17ad2b417be66c3710", "7b0c785e27e8ad3f8223207104725dd4"}, + {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "6bc1bee22e409f96e93d7e117393172a", "bd334f1d6e45f25ff712a214571fa5cc"}, + {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "ae2d8a571e03ac9c9eb76fac45af8e51", "974104846d0ad3ad7734ecb3ecee4eef"}, + {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "30c81c46a35ce411e5fbc1191a0a52ef", "ef7afd2270e2e60adce0ba2face6444e"}, + {192, "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "f69f2445df4f9b17ad2b417be66c3710", "9a4b41ba738d6c72fb16691603c18e0e"}, + {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "6bc1bee22e409f96e93d7e117393172a", "f3eed1bdb5d2a03c064b5a7e3db181f8"}, + {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "ae2d8a571e03ac9c9eb76fac45af8e51", "591ccb10d410ed26dc5ba74a31362870"}, + {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "30c81c46a35ce411e5fbc1191a0a52ef", "b6ed21b99ca6f4f9f153e7b1beafed1d"}, + {256, "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "f69f2445df4f9b17ad2b417be66c3710", "23304b7a39f9f3ff067d8d8f9e24ecc7"} +}; + +static void from_hex(unsigned char* data, int len, const char* hex) { + int p; + for (p = 0; p < len; p++) { + int v = 0; + int n; + for (n = 0; n < 2; n++) { + assert((*hex >= '0' && *hex <= '9') || (*hex >= 'a' && *hex <= 'f')); + if (*hex >= '0' && *hex <= '9') { + v |= (*hex - '0') << (4 * (1 - n)); + } else { + v |= (*hex - 'a' + 10) << (4 * (1 - n)); + } + hex++; + } + *(data++) = v; + } + assert(*hex == 0); +} + +int main(void) { + int i; + int fail = 0; + for (i = 0; i < sizeof(ctaes_tests) / sizeof(ctaes_tests[0]); i++) { + unsigned char key[32], plain[16], cipher[16], ciphered[16], deciphered[16]; + const ctaes_test* test = &ctaes_tests[i]; + assert(test->keysize == 128 || test->keysize == 192 || test->keysize == 256); + from_hex(plain, 16, test->plain); + from_hex(cipher, 16, test->cipher); + switch (test->keysize) { + case 128: { + AES128_ctx ctx; + from_hex(key, 16, test->key); + AES128_init(&ctx, key); + AES128_encrypt(&ctx, 1, ciphered, plain); + AES128_decrypt(&ctx, 1, deciphered, cipher); + break; + } + case 192: { + AES192_ctx ctx; + from_hex(key, 24, test->key); + AES192_init(&ctx, key); + AES192_encrypt(&ctx, 1, ciphered, plain); + AES192_decrypt(&ctx, 1, deciphered, cipher); + break; + } + case 256: { + AES256_ctx ctx; + from_hex(key, 32, test->key); + AES256_init(&ctx, key); + AES256_encrypt(&ctx, 1, ciphered, plain); + AES256_decrypt(&ctx, 1, deciphered, cipher); + break; + } + } + if (memcmp(cipher, ciphered, 16)) { + fprintf(stderr, "E(key=\"%s\", plain=\"%s\") != \"%s\"\n", test->key, test->plain, test->cipher); + fail++; + } + if (memcmp(plain, deciphered, 16)) { + fprintf(stderr, "D(key=\"%s\", cipher=\"%s\") != \"%s\"\n", test->key, test->cipher, test->plain); + fail++; + } + } + if (fail == 0) { + fprintf(stderr, "All tests successful\n"); + } else { + fprintf(stderr, "%i tests failed\n", fail); + } + return (fail != 0); +} diff --git a/src/crypto/equihash.cpp b/src/crypto/equihash.cpp index 863c4f673..5a4111838 100644 --- a/src/crypto/equihash.cpp +++ b/src/crypto/equihash.cpp @@ -22,10 +22,9 @@ #include #include +#include #include -#include - static EhSolverCancelledException solver_cancelled; template @@ -639,7 +638,7 @@ bool Equihash::OptimisedSolve(const eh_HashState& base_state, size_t hashLen; size_t lenIndices; unsigned char tmpHash[HashOutput]; - std::vector>>> X; + std::vector>>> X; X.reserve(K+1); // 3) Repeat steps 1 and 2 for each partial index @@ -657,7 +656,7 @@ bool Equihash::OptimisedSolve(const eh_HashState& base_state, N/8, HashLength, CollisionBitLength, newIndex); if (cancelled(PartialGeneration)) throw solver_cancelled; } - boost::optional>> ic = icv; + std::optional>> ic = icv; // 2a) For each pair of lists: hashLen = HashLength; @@ -682,7 +681,7 @@ bool Equihash::OptimisedSolve(const eh_HashState& base_state, if (ic->size() == 0) goto invalidsolution; - X[r] = boost::none; + X[r] = std::nullopt; hashLen -= CollisionByteLength; lenIndices *= 2; rti = lti; diff --git a/src/crypto/equihash.h b/src/crypto/equihash.h index be2a02d1f..9f0244c77 100644 --- a/src/crypto/equihash.h +++ b/src/crypto/equihash.h @@ -284,6 +284,7 @@ inline bool EhOptimisedSolveUncancellable(unsigned int n, unsigned int k, const } else if (n == 48 && k == 5) { \ ret = Eh48_5.IsValidSolution(base_state, soln); \ } else { \ + ret = false; \ throw std::invalid_argument("Unsupported Equihash parameters"); \ } diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index 494ab98ce..ab1202990 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -14,6 +14,8 @@ #include #include +#include + static leveldb::Options GetOptions(size_t nCacheSize) { leveldb::Options options; diff --git a/src/deprecation.cpp b/src/deprecation.cpp index 168969ff3..8f8cfc9b0 100644 --- a/src/deprecation.cpp +++ b/src/deprecation.cpp @@ -20,7 +20,6 @@ void EnforceNodeDeprecation(int nHeight, bool forceLogging, bool fThread) { if (networkID != "main") return; int blocksToDeprecation = DEPRECATION_HEIGHT - nHeight; - bool disableDeprecation = (GetArg("-disabledeprecation", "") == CLIENT_VERSION_STR); if (blocksToDeprecation <= 0) { // In order to ensure we only log once per process when deprecation is // disabled (to avoid log spam), we only need to log in two cases: @@ -32,10 +31,6 @@ void EnforceNodeDeprecation(int nHeight, bool forceLogging, bool fThread) { auto msg = strprintf(_("This version has been deprecated as of block height %d."), DEPRECATION_HEIGHT) + " " + _("You should upgrade to the latest version of BitcoinZ."); - if (!disableDeprecation) { - msg += " " + strprintf(_("To disable deprecation for this version, set %s%s."), - "-disabledeprecation=", CLIENT_VERSION_STR); - } LogPrintf("*** %s\n", msg); CAlert::Notify(msg, fThread); uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR); diff --git a/src/experimental_features.cpp b/src/experimental_features.cpp new file mode 100644 index 000000000..67afbf7fc --- /dev/null +++ b/src/experimental_features.cpp @@ -0,0 +1,56 @@ +// Copyright (c) 2020 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#include "experimental_features.h" + +#include "util.h" + +bool fExperimentalDeveloperEncryptWallet = false; +bool fExperimentalDeveloperSetPoolSizeZero = false; +bool fExperimentalPaymentDisclosure = false; +bool fExperimentalInsightExplorer = false; +bool fExperimentalLightWalletd = false; + +std::optional InitExperimentalMode() +{ + auto fExperimentalMode = GetBoolArg("-experimentalfeatures", false); + fExperimentalDeveloperEncryptWallet = GetBoolArg("-developerencryptwallet", false); + fExperimentalDeveloperSetPoolSizeZero = GetBoolArg("-developersetpoolsizezero", false); + fExperimentalPaymentDisclosure = GetBoolArg("-paymentdisclosure", false); + fExperimentalInsightExplorer = GetBoolArg("-insightexplorer", false); + fExperimentalLightWalletd = GetBoolArg("-lightwalletd", false); + + // Fail if user has set experimental options without the global flag + if (!fExperimentalMode) { + if (fExperimentalDeveloperEncryptWallet) { + return _("Wallet encryption requires -experimentalfeatures."); + } else if (fExperimentalDeveloperSetPoolSizeZero) { + return _("Setting the size of shielded pools to zero requires -experimentalfeatures."); + } else if (fExperimentalPaymentDisclosure) { + return _("Payment disclosure requires -experimentalfeatures."); + } else if (fExperimentalInsightExplorer) { + return _("Insight explorer requires -experimentalfeatures."); + } else if (fExperimentalLightWalletd) { + return _("Light Walletd requires -experimentalfeatures."); + } + } + return std::nullopt; +} + +std::vector GetExperimentalFeatures() +{ + std::vector experimentalfeatures; + if (fExperimentalDeveloperEncryptWallet) + experimentalfeatures.push_back("developerencryptwallet"); + if (fExperimentalDeveloperSetPoolSizeZero) + experimentalfeatures.push_back("developersetpoolsizezero"); + if (fExperimentalPaymentDisclosure) + experimentalfeatures.push_back("paymentdisclosure"); + if (fExperimentalInsightExplorer) + experimentalfeatures.push_back("insightexplorer"); + if (fExperimentalLightWalletd) + experimentalfeatures.push_back("lightwalletd"); + + return experimentalfeatures; +} diff --git a/src/experimental_features.h b/src/experimental_features.h new file mode 100644 index 000000000..390cb7d0e --- /dev/null +++ b/src/experimental_features.h @@ -0,0 +1,16 @@ +// Copyright (c) 2020 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#include +#include +#include + +extern bool fExperimentalDeveloperEncryptWallet; +extern bool fExperimentalDeveloperSetPoolSizeZero; +extern bool fExperimentalPaymentDisclosure; +extern bool fExperimentalInsightExplorer; +extern bool fExperimentalLightWalletd; + +std::optional InitExperimentalMode(); +std::vector GetExperimentalFeatures(); diff --git a/src/fuzzing/CheckBlock/fuzz.cpp b/src/fuzzing/CheckBlock/fuzz.cpp new file mode 100644 index 000000000..838f9cd10 --- /dev/null +++ b/src/fuzzing/CheckBlock/fuzz.cpp @@ -0,0 +1,29 @@ +#include "consensus/validation.h" +#include "chainparams.h" + +int main (int argc, char *argv[]) { + int retval = 0; + + SelectParams(CBaseChainParams::MAIN); + + CBlock block; + CAutoFile filein(fopen(argv[1], "rb"), SER_DISK, CLIENT_VERSION); + try { + filein >> block; + } catch (const std::exception& e) { + return -1; + } + + // We don't load the SNARK parameters because it's too slow. This means that + // valid blocks with shielded transactions will generate a crash. + + const CChainParams& chainparams = Params(); + auto verifier = libzcash::ProofVerifier::Disabled(); + CValidationState state; + // We don't check the PoW or Merkle tree root in order to reach more code. + if (!CheckBlock(block, state, chainparams, verifier, false, false)) { + retval = -1; + } + + return retval; +} diff --git a/src/fuzzing/CheckBlock/input/0.bin b/src/fuzzing/CheckBlock/input/0.bin new file mode 100644 index 000000000..af3882252 Binary files /dev/null and b/src/fuzzing/CheckBlock/input/0.bin differ diff --git a/src/fuzzing/CheckBlock/input/476431.bin b/src/fuzzing/CheckBlock/input/476431.bin new file mode 100644 index 000000000..ba56c7b7e Binary files /dev/null and b/src/fuzzing/CheckBlock/input/476431.bin differ diff --git a/src/fuzzing/CheckBlock/input/620000.bin b/src/fuzzing/CheckBlock/input/620000.bin new file mode 100644 index 000000000..72ee3018f Binary files /dev/null and b/src/fuzzing/CheckBlock/input/620000.bin differ diff --git a/src/fuzzing/DecodeHexTx/fuzz.cpp b/src/fuzzing/DecodeHexTx/fuzz.cpp new file mode 100644 index 000000000..6e8f0e9f4 --- /dev/null +++ b/src/fuzzing/DecodeHexTx/fuzz.cpp @@ -0,0 +1,17 @@ +extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx); + +bool fuzz_DecodeHexTxFunction (const std::string& strHexTx) { + CTransaction tx; + return DecodeHexTx(tx, strHexTx); +} + + +int fuzz_DecodeHexTx (int argc, char *argv[]) { + std::ifstream t(argv[1]); + std::string str((std::istreambuf_iterator(t)), + std::istreambuf_iterator()); + if (fuzz_DecodeHexTxFunction (str)) { fprintf(stdout, "Decoded hex string") ; return 0; } + else { fprintf(stderr, "Could not decode hex string") ; return -1; } +} + +int main (int argc, char *argv[]) { return fuzz_DecodeHexTx(argc, argv); } diff --git a/src/fuzzing/DecodeHexTx/input/coinbase.txt b/src/fuzzing/DecodeHexTx/input/coinbase.txt new file mode 100644 index 000000000..dd224cf13 --- /dev/null +++ b/src/fuzzing/DecodeHexTx/input/coinbase.txt @@ -0,0 +1 @@ +0400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff2a03677b090004e161a75d0edb51e814ae3737f790e3c94f11495327270fdfbd6132d5e90f87507455844cffffffff023f1e9b3b000000001976a914e0082ee3d89f84adbadaaebddd1746bb20e6d4ee88ac80b2e60e0000000017a914ce811a7457b9f4553af120e553bc8ddd8bb33ce98700000000000000000000000000000000000000 diff --git a/src/fuzzing/DecodeHexTx/input/manyoutputs.txt b/src/fuzzing/DecodeHexTx/input/manyoutputs.txt new file mode 100644 index 000000000..71e255be0 --- /dev/null +++ b/src/fuzzing/DecodeHexTx/input/manyoutputs.txt @@ -0,0 +1 @@ +0400008085202f8902befc1c37af31039fc287f26ce1240524a8aa209e4b668cd9bd928347e62355c2000000006a47304402206f85716662f762565b040b21059d7a1e8a1cc520b781d6d46a1c2a685d6ac125022063dedfa9b036169a1a9b81bffcd4e7717c993286a507d84224fa630590fe82d0012102a1e96e2736efd7dbd5b6dc807c24b657fdcc6d3a7e6c7fac5607a9f3e47b8748ffffffffc5d479c0fa4ff1b932b4c80105643dfd8df963f45fe363bf2794a3c86473e985050000006b48304502210081dfd38fcc7a39aebbf26606e987a1ed68d10faaca0a200aa65f040065b88ac80220082eccb4fbd4d0bf1b55fc14b7b4f25d76a1e93fe6181922bd0cfe9d77d1fa9d012102a1e96e2736efd7dbd5b6dc807c24b657fdcc6d3a7e6c7fac5607a9f3e47b8748ffffffff47c204d31d000000001976a91478a6c1f4016e651d17a861b027fd6d217472d27288acc703ac00000000001976a914b70661b7ddf8450e44b06b9f8e466cb209c504a688acc2fa4701000000001976a9143d6d2394b9f0b9a4a56c1536f4c6adf979eb772488acae8f0703000000001976a9140f5ebfa68d92de9f10110a874fe69fb2c2ae122088acde342200000000001976a9142c3ef04a3a41df528234ebfa438a96895f94c40d88ac5e2ba400000000001976a9142fb59e414b3e73d2665266f9add4253b83ae455e88ac7fa51500000000001976a9147da516f0a4e5b54e6870c88da34d4cb7951411bd88acbc614900000000001976a91408135077ee8808dc75623dc6c80a9edad8803d9688acd0851003000000001976a914e2a878e046a5006a4adeae1b6e4e004bb07fc57c88ac25494e00000000001976a9144be18cbda2883ebbc5061da1bd471600a59a94cf88ace7821002000000001976a914031a94992926a4e6ebcda8ebb5e865ceb91bebd888ac1b509d00000000001976a91420eb1449216e61aa99ac4a4efc8da3a8288bb8df88aca1070500000000001976a914179e347753c9e04358eb529c43925b68b5d3df1888ac611ea800000000001976a914a2649b4b77da4ee11651182b56b175977efaac3588acd6901000000000001976a914fba4aee4df81f8ec128644b6ffc3fcf7340c312088ac1b5aec000000000017a91441ca4c4997f4158b20831a6bdb3502c2e2668c5c8790e61100000000001976a914d3f19ab072fa80f501733e17aa1c74b974b6f63588ac57e99800000000001976a91477d55248c52900cb278f25a93b366037a273f59388acfb6e0500000000001976a914448d4c46027d917038a6ec1359b428d94a21816088accda91100000000001976a914157b6515820f71cc5fec6cddefba67b39c28945288aca6730f00000000001976a9141e11d2a44c56d52c6030c92484e3cbff7668f85f88acd690a100000000001976a9144340ebe430837105b17270f3db8b4b493125977588ac38e1911a000000001976a914780332e7f8ad8a3b164daa66f358112f3e5da3ca88acacf30d00000000001976a914be547067034818d54721d0639ca2567fab92627388ac12102700000000001976a91482d5fee592be74fb6b5b93132936296f778e5e2588ac5dfba200000000001976a9149e89130245c481e76f898209ffa49a1f1e9b6b3788ac01c5a300000000001976a9146fd439218e6ea0ebfcb71c2c884f62c3072dd1bf88acca201400000000001976a91489d97fc368a849890b71672e4d119e8241dc82b888ac6bd79800000000001976a9146680bb7e80f4633c4fe8f5d454cd6249b09cd84088aca1d10800000000001976a9141957b979db9371ad172db3c2e14828a921c4375c88ac50aa1800000000001976a91431ba04310f5744bf82e389646744f6957e4d804088acde574d00000000001976a914bdb6082119d4f48b164c22d63758aba0fdad926888acc59e9b00000000001976a9144ee4278bfaebe562d022b098adca6c6f0fd6226688ac97960f00000000001976a914a9830a65a06703b7f3479fb76dba84a5c609c27888ac1e96bd00000000001976a9147073f14a83cd3c1409d4654f823b3d212248ac6e88acfd6e9a00000000001976a91495db46ddbdcec98ae44286a27d0e2261b6f7c85688ac29de2000000000001976a9147d9d90e38ab26b1b3bad803fba3d61ce2784a93688ac27fb9800000000001976a914f6f5e13d7d234837f0d87ee78d4ff8c3f4144ed588aca5ec86bf0e0000001976a9148255a41ba998eaffb465a3d8e93c594a1da8f1ab88ac93f33101000000001976a9144dbd328cecc555c670e4cf5fb2797326d9645aad88ac7bdd9900000000001976a9149b4dbcdfa48ec8ad89347dacb084eecb8261006888ac30e60203000000001976a914e1f431e2ae6cefd567231846f9dcf0c66d76e16588ac09daa700000000001976a914401a49d45a413e9696be0db70f975ce70f8c7cf388acdb63cd06000000001976a914708b30c60031ef4ab36787f5cf2a3b4578a4853888ac213f5503000000001976a914719fe2aea706e8aec771905582ded2518c18a22688ac40180200000000001976a914ef4056d82ac0b683fc0d3f07128b180fd03ee2dd88ac91ca1f00000000001976a914f161281ea6a041a88461e940d2c21404bcfab94588ac4aaf1200000000001976a914b69c7339f573f40513cf7a44dd4e5c3cc0a5e4b988acf90075060000000017a914d0ee49d95f1af8813af892f6f8f0b20cc0b2d623876d010200000000001976a914fb0c18362cfca25b7c94b472e6fc7553b0d4738188ac50cf0600000000001976a9142e10260dbb4a0fcbaa3b06c0bcd94c1f37f1c72d88ac722baf00000000001976a914baf763fa7d1cb569203b8be11c05c07baa50fbd588ac47b25d00000000001976a914ee5b497487fcd2790b007421b6031b5c9112dd6788ac75602800000000001976a914eddfc57e127d733926e97a58821839b83adb0b2a88ac76359a00000000001976a91432c5172f4f9ffcb2ac6742d19ca2e669f553513d88ace6a59f00000000001976a91433fc10b166d54a051560ba929388c874b9557edc88ac6e161500000000001976a914f12ca2a753b1d7b0a99432c4b9bf1da85653f55c88acd41a9b00000000001976a91442f117744d7e20658e54dc6dea545e9c5312462888acf76d4d00000000001976a914e34554ba274741b2a3ced9c054c27b91c0c2e03d88aced230200000000001976a91428062481ce9b03fd727d64bfa72b3dffacaf452b88ac418a171e000000001976a9142aec5ce62b93b06089074cd7657fc46694d4bfc088acc0540f00000000001976a9140e4819142771ccf9ab3c54fb17d834636c8f6a9488ac91731100000000001976a914ba5c11856d2c042e3ac4734e7e06b23fd99c0b7288ac76021500000000001976a9144d036eb4c1e0946c30559728001c66a108ee4a1288acf9f38219000000001976a9146f2bc25d2c470ce061f2678b98a1a4ddb4be4d4f88acf9047300000000001976a91438dfba1089757034c516a7949ebeb053ff015d6f88ac44825d00000000001976a91424da8bf275c1fc6efdfb2654bfd9e3e236bd881d88acffef5c00000000001976a9144a9ed8c7b52bf44d835326ff8967ef63f2f4830f88ac83bbfc05000000001976a91430dc5101259b18d053c794ec61731da4b06d182788ac72c0e400000000001976a9149c91bf5ba5c0b1e11e7af0aef690f4bb180bb9b788ac50870a00000000001976a914df89be1a534e1fd4b9a4b3616c27bf99fbc44efc88ac00000000548809000000000000000000000000 diff --git a/src/fuzzing/DecodeHexTx/input/sapling.txt b/src/fuzzing/DecodeHexTx/input/sapling.txt new file mode 100644 index 000000000..4fbc26f2a --- /dev/null +++ b/src/fuzzing/DecodeHexTx/input/sapling.txt @@ -0,0 +1 @@ +0400008085202f89000000000000ec8a0900102700000000000001251409d9698abef6527f651bac9cfd1eb57b7ff934b05e6921879e5fae0678adf9792e02ab24556f3fc6a24519d24ae7f2b8e3aed982cf3e36ea1a0c1243600d953fae63415e818e050048edb6fed27cc3f893d1b163620270bd7d7ce2065f303f57c1d621d3336305bcf9ffb8c13c917fcbcc05b68c27c77abf90a1a7013e1791fe0bfc4c147a66c8cf87a3ede59ba56f585bb6301eb3e0952fe066a0e40cfb8a58c1ed227471e9eafb999169ff7e19a85c3e9c739f7fe974c849309c379c9e3d6ed2d913ddaee302e6c54e929a85193ae7a7eb327fbae9082945732dfbd14a0b1cf66446b20c7e054e7cbd4a428eded695035e5d7144efb73b9e4ce10d2ce23516e95bbb3971403460ced0ac269eb2b86142ddb53d83ef09c6673cdba495f23dc0e1d17317c8debb31d0963c45884d2af79448057084b23a1776feacb8109246d49dc988b3fa7f32d53dbc3c40e5a0932dad6a87c916b6bbbec2d803bd806424ab3374eab7880e69570c6e94495e6c7445ad3911a29bfdf1f702688a66180902a001d887b84e87a1a08147b3ec53b92f7f3f214a1a1c60cded3d7b9e1516033a2586a074ad5b01a178db42b76d16c3db5302d62825347390cf5b760ea2362a27db3063d4a2021514a3c64e3bca0896a6b52c0b8ba4ef9120eb7cf9367ad6ca859d1986b00789a7889d2caf7b016a2e000bd0538359b250871497686c12321941787b6a65364138c7484037e7143d83a6d2606722b27ce75426cb1392e92ae4470dd8aa04f0fdeca4a924c599822496689bd7388214e68c8a94a9e07f0a41d485ff7cdce14fb1442f017231b0d27b7992b17007d034b0df7cb373495fd99668a4be34ceeea5b3a425cda44a1bb726e1cf0ac6b9cd05da93482524bdc60aec7300ae09281d5c62325d3c9ada64c41802358a692fb219712ff1e872476806d690b7f2ff68b023df2942d220a98b09af78dc85d1c1f4e39cc01aa4d4d7892fd665e1c0ec2fc35724586c75a9ff3c5f2d27226b8013562b59a6ee69d4d36e9d858da5a41a32c9769c41e7362681b5c93b5bb915adf1d08b71e2f74f15407dc2f3f48d7043d619d22f613714f21b481a80113a4a2b9616325aa52cf4cc6dd8db54f764ae7c7270476406ee8313b66e1109c14cb4ccd138b41e6c9e8005c593ab6e40a5d6bf5017a52faec7d0fdc3adf600af499d0e3c73a5567bbd2bd366132e2b222095843898814865e3b3a2e8662e87f9618764eb4b962e5eb8e8a7740197365eb2d0c086b4ffd65bd19cec6dba33634eefba2353ac622985f3e4dd6df772691661d58de3297d440ea58edc6297e877790e56320d13adfafa71b79b7381366564befbb40470b254935bb83a9acf4124cc45993c99c1713f500dad49bb3ba6ce70dfbb75091790a0a033a9c3dd0d8975fd005a0c5b9d3ca230c36173c96dc3d41833d3b75ef392edc08c5343f838f8d19714a5ce6afaafe34914a65177e348d56133ec9d1fdec768a4b4e3221d7820f941c0e79f5a97d25ca99a02e3211fd4d74b926cf14fad605fcd8631b2a9ce8156703e9623a1f6ef50e039e71ae0560a9b96a2965c964b6b133d8b3ee35e38f91c18645fab67b798a287fd50c9d48f39b213a1904b8a62102c214a0692ad01f5f74df6ff639cd28d95e720842295cd337d9639dd2e90f8996fcad10911eac82e8aa060ae211ad4620c1c6cc20b277f5b1f45b906625d98f07dfd16b5b70b983cd881571a6af39012ec30c43b8b1e12c3534d852453b26f8c2c50c4a902a339d67a0dc9081668a383ae6f28c0f2c7eb3c9cc0597d16c1ba83062729e1c90407431caf00f46e04c3350277bc318d2cc5d8d9857d294d50729b72dc3b78725a8ad6a40ffcae066d91108ebb9d34a6bfee2bb41b56fc7f08bf4b50e8c52567509215948f414356e5639cfadeceb04fd7d8b3e151fa3ee77f7ba87dbc0337b81e240e03508c69d35d1e5e3d998a589443edb68059b87e39b241cb16e09b6f1da1b381cd467f85df6b1cb29e7d8a89bf6216fdf927ede71ee945c36f313278ca50618da3d160fce0da32b325f27be0afaaeb92856d4dea26dba9922f5c541e76453893bea8f4ad4aed716835fa6ee6a04453d5fa1efe6efb64e060a82406c4230c8ed981f45f4ab078864b4388f3866aee9f76d2b0e2bea8601b4f8e79245fc5c94995be9674c1ae064242f6a65fad2ef9ea28e6bcba11fa07f14fad1c9da5f9cc78b4bb7217015968122f9c9ea59b661c3188c909e76caffd48185f6917ee306be440b67f7712500c5d37d14481e3ea01d78aeeca4178bb9835627d1d799bd5514039ac1f4bde04315bbfa194900885b9718be9871d629b9df14a022821c83c3039aec07f32575d2e84f6c3acc90d02a26a6380d63012310f6abd49c746cec06eb324715a2fa74d6c8e8327c85cabcbd78ece00fcff64cc36822b3ed28f15cc85fd4945e4010192890f30df28b6de4d3354e40e77121647a224e35874175a2de9cabca4dcead549d697a3bb76c0a2280c2a459ba63a9625ff53ce8accddd9b3dabb4a285d4cac4d410e787f5e8b9f1ba509d28fd95a2e0d3400d1c5e27394a64324ed44884eed42b273375bccc8b7df8bc035172eea0198b9ac8c1c99ecbe547102ec8449cc0d436f85567247cbb2942a51abbce1714caeb852afbd4a64649c2655d7b577061591b6a928c88f679a3f914e5608cc400c027e78911c192704f260cf4e05b96c5df0579a22e591e28c9c344320c12088fff7e81e4aef56ad417a2782dc03dc1d94909f0cb2a70304b2e6cabe4165ee53893dd63b58a08968fa43a03851da5151c7609715c3f6d21f01d15b578d8c37426da5008801107e35f62525734cd0a7876f065b920e2ec461c4f3700b792cf89c406893949a1058cf422837ffe1f87209212cc379a3b482e15e8993b468d94565317917870c734555a61db272a24fe52e40479c9a25276a0cc2e0c42404d11e9e1aae1c7545a6f99cbcb2cc2dfc11e889eade5df7f7da7aa38f12af116d217af57f8e3ae575e69190676502088cba9295f775538dfe653eecd0cf504643c2ff6920719d0d83047e16052016459f7fc802b420f0796c771b7d988fd95a42b17f363a692346455e1c6e173298aafeea3fcfca393349ebbefa6899777264b5d0452aa8f70573ae688d9916861447da00d9d847eda7e34f88988086d6734bb43ec53b4a2d9f260103cde700415214614727f24927a7e49fa191153a41eb24e73f78aaf544c10d68fbe459e232be1af6b48fa01b2d018774e28483d2f990d0eae272680f57e5980ff2033907 diff --git a/src/fuzzing/DecodeHexTx/input/sprout.txt b/src/fuzzing/DecodeHexTx/input/sprout.txt new file mode 100644 index 000000000..d3a4d9aab --- /dev/null +++ b/src/fuzzing/DecodeHexTx/input/sprout.txt @@ -0,0 +1 @@ +0400008085202f89000000000000ed8a090000000000000000000000010000000000000000102700000000000046e5b5ba294641c0491ef8cb5a97591fe1fcee2bab2301553f9bc0f9acc9bcb70f836c9945bfbae86faf169fd9be228f6c373e0b029fd648e7d0660d8412b50c0597c61387abfc9f1122179f1c612ad72ce09cf6dd8576f60494d0a828c10706f7594b5f237eeec5fd0474f6a16f3923a6e6881a0fe790a5328813abb559dcba268fbbe6e428783271ce752e1b21bedd8b70d7c7ca741651853bcc411ff5099d7cb3dee3ee072fd53bc32b597f0deff17ceb2cd47448bf1432f5bfdc022435060208d9cbd0f9af4dd89bbd62cb05ad865c3bd6b691ef5fa04f5498d32004874acf51385eea2e98e23f9d4b440b00bdbd972f049c559b4934bbbb429029adf8892c7f3c1a86d5d2be4db51cfe098ea31451ea6965fe49e06ada1c6734c3d180068816e8c85e02ecb55f6a4e558590c52b04c768f5d22682b7eb2cfc18c308542e67b85a4831130409b5ae2cb15c18873ab269b3560f1a4d09d723f82dcd4051db4fcaefbfcf923fcfb35befc8777a7afbf7a4ffbee41aeb53172e1b67efbaad4e12e75a08e3bd85b16af909d3262e3d43085a8f54dd8c00047394265d0368323e82bc345da1477026f3dbc5e05d85723ea77b4dd7b98dbf6bbe7c8988eae224ece369106513fc1b3604b6cfb5ac49da226e6269a52d6aa30a3ae70d06dfce27cb497083568cf4e362be2417328107ed01fbf63e1667ba221ee89c4fa37e9460eafcbb15f6f9184c09fff97ba4ca183b46246d354ef47f4423dbbda454738effb3efe0cc0cd7381d73e0d768bb1e7056fce119bf4877ca07c2e959027285c3a24f3b58b8ff31acc3e30f5c09ccdfad7b762ce5e7388d15f154db726a68b8a0f4b9bdb943d9fd9aef8c1a4c7d89709e5b931804d6b32dcc42fc0790c77e0db3c86623f89cc961ad3a41a80a42a5c1700ff2e6c70ce03fdbe498beb8184bb3a2ad5eb806d349fdfbd6bd066133977790df768abfcd02806d33bd5507ec279f5cea71734d9990e3cebee3e2e631caa21253f20a75b5e59f626f4f5d0da425e4387d73f4ab7179b753f396583f39b6b849c0bde5179c15b82d459d1d06e0d929a0b5d6e8d51453b12edc59c402bdcd79872b7a3e53f67ec37c2ad9a024668f62e1c0def0f8b1d11836fc20fe732327721a0b061466240b7fd5de687c01f08f186da67b867767b401395acefa618c012d72f0cee463e0eb73ac8a8b94fdbcb759afc4b337c47eb65a4105986dc82fdd45e65f9fb4a131eaa59257e2e4d28b7463575d9e641df173cfebf32a3cecee2e77d1b46b317b6d55e5c3103893a019d340ee5e91d55365f70ad36eb6d7fed94a052187d856231873df88093d10b4724a635372b4bf0232a88b9d7d3b7681a523d2f8d82a921c6bcd687cdf2aa19aecc202b87fb9fcd1997b73afde048c69e7c6b5c122435bd5df8e6b197042d0e6ab2770551f0cdaf008cbf5a25468aca996d8c13f3de549afbacc363b55e94ee10c1bde4c7d7a55bc014935b65267de17ffe5592cc5ce641a2de2a303cc557bd829a19651971eeac586654b282f92486c59dc8ef335c6a9ecfb178c3e0d6ea6df5c2e84604ca89b2fe5902a26ac3274be48259fcabf0dde398c2821cfedd1c93cb05e9a9cb7dd3107cbac001af08f0a64727447e17d6cf5678dcac770dfe7af08de1e1f16dfbe4df37675a54b0a9c2cdb32b2eaa54850b9e338139974f49e2b3c02646529170e69622d64f300cda3903ea6a83923de195ef2b69528ffcbf182a0297c0ee5e11916e60190981625e819739226f68b924237532175d9b05a6859a92dd78e7abcca7cfc10497857a12f07e5d0fcad158ed0b9b76663902c6508a9f51de19204536de5830a497fa9a75d8a0aa610c868960fa868a45afa466fd70834864b6b85f80ac6ee226920b702415579e8fe1129e60a35dd3dee6ba67a2151c027137ce7ce7c296678360463408fc6f02ea00333d2fec8323fe4cfe2a70c4d4cfb169b5954e31c575474d29d4167a6d3a4fc2ba5a8963aec24e775056c34d7b5ad1a9287f22d55b1d7d22e72ae79c9d55ab4ca67dd05c63e2c0cde5342b79a9d838106b416ce9a858fb8cdfa30174c18314485fe46d2151bc94f43b99544998c127fe504919cc9d9c105544c72b7265314a35dc38e04b282301cd4780352a978fadb080d8d2493ae0b92493be110700f943e63de82e68e129e894a2182a2fcfac30f770ce4f0601f57dc22c01330d409349b4c44b4a627dfc74b8a5c6a066a032fc93c7c7ee1aaeb17a7bfaefc5197e4355a4bd41cdd8ac651fae7d4d2d1c0713ffe1399199275c27da96ca6f959550c1040d46364c7f65fe3af541a43042dae394be74bef1515e25ce1c1d126295b44dc05dbc4a658d076ca39f35504966aa8872008447f38f9259099d0056b0c057ce9926ac208984fb6875b3c1f440e37a1ab9c6cb0957e39972596db5e3eb10252434bff0738aa107152cd4184329ee63dd7cdfdcbb3a3548e3c5431cae2c2ca85f1cd30f2aeeedd04 diff --git a/src/fuzzing/DeserializeAddrMan/fuzz.cpp b/src/fuzzing/DeserializeAddrMan/fuzz.cpp new file mode 100644 index 000000000..1b520efc8 --- /dev/null +++ b/src/fuzzing/DeserializeAddrMan/fuzz.cpp @@ -0,0 +1,13 @@ +#include "addrman.h" +#include "streams.h" + +int main (int argc, char *argv[]) { + CAddrMan addrman; + CAutoFile filein(fopen(argv[1], "rb"), SER_DISK, CLIENT_VERSION); + try { + filein >> addrman; + return 0; + } catch (const std::exception&) { + return -1; + } +} diff --git a/src/fuzzing/DeserializeAddrMan/input/peers.dat-minus-4-byte-header b/src/fuzzing/DeserializeAddrMan/input/peers.dat-minus-4-byte-header new file mode 100644 index 000000000..ce52b0a1b Binary files /dev/null and b/src/fuzzing/DeserializeAddrMan/input/peers.dat-minus-4-byte-header differ diff --git a/src/fuzzing/DeserializeTx/fuzz.cpp b/src/fuzzing/DeserializeTx/fuzz.cpp new file mode 100644 index 000000000..0eedf4be4 --- /dev/null +++ b/src/fuzzing/DeserializeTx/fuzz.cpp @@ -0,0 +1,21 @@ +bool fuzz_TxDeserializeFunction (const std::vector txData) { + CTransaction tx; + CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); + try { + ssData >> tx; + return true; + } catch (const std::exception&) { + return false; + } +} + + +int fuzz_TxDeserialize (int argc, char *argv[]) { + std::ifstream t(argv[1]); + std::vector vec((std::istreambuf_iterator(t)), + std::istreambuf_iterator()); + if (fuzz_TxDeserializeFunction (vec)) { fprintf(stdout, "Deserialized the transaction.") ; return 0; } + else { fprintf(stderr, "Could not deserialize the transaction.") ; return -1; } +} + +int main (int argc, char *argv[]) { return fuzz_TxDeserialize(argc, argv); } diff --git a/src/fuzzing/DeserializeTx/input/coinbase.bin b/src/fuzzing/DeserializeTx/input/coinbase.bin new file mode 100644 index 000000000..ca36e8cad Binary files /dev/null and b/src/fuzzing/DeserializeTx/input/coinbase.bin differ diff --git a/src/fuzzing/DeserializeTx/input/manyoutputs.bin b/src/fuzzing/DeserializeTx/input/manyoutputs.bin new file mode 100644 index 000000000..e726fb74a Binary files /dev/null and b/src/fuzzing/DeserializeTx/input/manyoutputs.bin differ diff --git a/src/fuzzing/DeserializeTx/input/sapling.bin b/src/fuzzing/DeserializeTx/input/sapling.bin new file mode 100644 index 000000000..2ac9414f2 Binary files /dev/null and b/src/fuzzing/DeserializeTx/input/sapling.bin differ diff --git a/src/fuzzing/DeserializeTx/input/sprout.bin b/src/fuzzing/DeserializeTx/input/sprout.bin new file mode 100644 index 000000000..b35aa0d5a Binary files /dev/null and b/src/fuzzing/DeserializeTx/input/sprout.bin differ diff --git a/src/fuzzing/ReadFeeEstimates/fuzz.cpp b/src/fuzzing/ReadFeeEstimates/fuzz.cpp new file mode 100644 index 000000000..1bdf2cf1d --- /dev/null +++ b/src/fuzzing/ReadFeeEstimates/fuzz.cpp @@ -0,0 +1,13 @@ +#include "txmempool.h" + +int main (int argc, char *argv[]) { + CFeeRate rate; + CTxMemPool mempool(rate); + CAutoFile est_filein(fopen(argv[1], "rb"), SER_DISK, CLIENT_VERSION); + + if (mempool.ReadFeeEstimates(est_filein)) { + return 0; + } else { + return -1; + } +} diff --git a/src/fuzzing/ReadFeeEstimates/input/fee_estimates.dat b/src/fuzzing/ReadFeeEstimates/input/fee_estimates.dat new file mode 100644 index 000000000..c3c5961ac Binary files /dev/null and b/src/fuzzing/ReadFeeEstimates/input/fee_estimates.dat differ diff --git a/src/gtest/main.cpp b/src/gtest/main.cpp index 5f32b5fef..e40bcec14 100644 --- a/src/gtest/main.cpp +++ b/src/gtest/main.cpp @@ -5,11 +5,10 @@ #include "zcash/JoinSplit.hpp" #include "util.h" -#include -#include - #include "librustzcash.h" +const std::function G_TRANSLATION_FUN = nullptr; + struct ECCryptoClosure { ECCVerifyHandle handle; @@ -23,12 +22,7 @@ int main(int argc, char **argv) { assert(init_and_check_sodium() != -1); ECC_Start(); - libsnark::default_r1cs_ppzksnark_pp::init_public_params(); - libsnark::inhibit_profiling_info = true; - libsnark::inhibit_profiling_counters = true; - boost::filesystem::path pk_path = ZC_GetParamsDir() / "sprout-proving.key"; - boost::filesystem::path vk_path = ZC_GetParamsDir() / "sprout-verifying.key"; - params = ZCJoinSplit::Prepared(vk_path.string(), pk_path.string()); + params = ZCJoinSplit::Prepared(); boost::filesystem::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params"; boost::filesystem::path sapling_output = ZC_GetParamsDir() / "sapling-output.params"; @@ -54,7 +48,11 @@ int main(int argc, char **argv) { ); testing::InitGoogleMock(&argc, argv); - + + // The "threadsafe" style is necessary for correct operation of death/exit + // tests on macOS (https://github.com/zcash/zcash/issues/4802). + testing::FLAGS_gtest_death_test_style = "threadsafe"; + auto ret = RUN_ALL_TESTS(); ECC_Stop(); diff --git a/src/gtest/test_block.cpp b/src/gtest/test_block.cpp index a0cdc1162..302c5882c 100644 --- a/src/gtest/test_block.cpp +++ b/src/gtest/test_block.cpp @@ -3,7 +3,7 @@ #include "primitives/block.h" -TEST(block_tests, header_size_is_expected) { +TEST(BlockTests, HeaderSizeIsExpected) { // Dummy header with an empty Equihash solution. CBlockHeader header; CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); diff --git a/src/gtest/test_checkblock.cpp b/src/gtest/test_checkblock.cpp index 7e286309e..56caf6a67 100644 --- a/src/gtest/test_checkblock.cpp +++ b/src/gtest/test_checkblock.cpp @@ -48,7 +48,7 @@ TEST(CheckBlock, BlockSproutRejectsBadVersion) { mtx.vout[0].scriptPubKey = CScript() << OP_TRUE; mtx.vout[0].nValue = 0; mtx.vout.push_back(CTxOut( - GetBlockSubsidy(1, Params().GetConsensus())/5, + GetBlockSubsidy(1, Params().GetConsensus()) * 0.05, Params().GetCommunityFeeScriptAtHeight(1))); mtx.fOverwintered = false; mtx.nVersion = -1; @@ -70,11 +70,11 @@ TEST(CheckBlock, BlockSproutRejectsBadVersion) { class ContextualCheckBlockTest : public ::testing::Test { protected: - virtual void SetUp() { + void SetUp() override { SelectParams(CBaseChainParams::MAIN); } - virtual void TearDown() { + void TearDown() override { // Revert to test default. No-op on mainnet params. RegtestDeactivateSapling(); } @@ -97,7 +97,7 @@ class ContextualCheckBlockTest : public ::testing::Test { // Give it a Founder's Reward vout for height 1. mtx.vout.push_back(CTxOut( - GetBlockSubsidy(1, Params().GetConsensus())/5, + GetBlockSubsidy(1, Params().GetConsensus()) * 0.05, Params().GetCommunityFeeScriptAtHeight(1))); return mtx; @@ -156,7 +156,7 @@ TEST_F(ContextualCheckBlockTest, BadCoinbaseHeight) { // Give the transaction a Founder's Reward vout mtx.vout.push_back(CTxOut( - GetBlockSubsidy(1, Params().GetConsensus())/5, + GetBlockSubsidy(1, Params().GetConsensus()) * 0.05, Params().GetCommunityFeeScriptAtHeight(1))); // Treating block as non-genesis should fail @@ -164,19 +164,19 @@ TEST_F(ContextualCheckBlockTest, BadCoinbaseHeight) { block.vtx[0] = tx2; CBlock prev; CBlockIndex indexPrev {prev}; - indexPrev.nHeight = 0; + indexPrev.nHeight = 50; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1); EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev)); // Setting to an incorrect height should fail - mtx.vin[0].scriptSig = CScript() << 2 << OP_0; + mtx.vin[0].scriptSig = CScript() << 52 << OP_0; CTransaction tx3 {mtx}; block.vtx[0] = tx3; EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1); EXPECT_FALSE(ContextualCheckBlock(block, state, Params(), &indexPrev)); // After correcting the scriptSig, should pass - mtx.vin[0].scriptSig = CScript() << 1 << OP_0; + mtx.vin[0].scriptSig = CScript() << 51 << OP_0; CTransaction tx4 {mtx}; block.vtx[0] = tx4; EXPECT_TRUE(ContextualCheckBlock(block, state, Params(), &indexPrev)); diff --git a/src/gtest/test_checktransaction.cpp b/src/gtest/test_checktransaction.cpp index a30b1268c..4068db42d 100644 --- a/src/gtest/test_checktransaction.cpp +++ b/src/gtest/test_checktransaction.cpp @@ -9,7 +9,7 @@ extern ZCJoinSplit* params; -TEST(checktransaction_tests, check_vpub_not_both_nonzero) { +TEST(ChecktransactionTests, CheckVpubNotBothNonzero) { CMutableTransaction tx; tx.nVersion = 2; @@ -96,14 +96,14 @@ void CreateJoinSplitSignature(CMutableTransaction& mtx, uint32_t consensusBranch ) == 0); } -TEST(checktransaction_tests, valid_transaction) { +TEST(ChecktransactionTests, ValidTransaction) { CMutableTransaction mtx = GetValidTransaction(); CTransaction tx(mtx); MockCValidationState state; EXPECT_TRUE(CheckTransactionWithoutProofVerification(tx, state)); } -TEST(checktransaction_tests, BadVersionTooLow) { +TEST(ChecktransactionTests, BadVersionTooLow) { CMutableTransaction mtx = GetValidTransaction(); mtx.nVersion = 0; @@ -113,7 +113,7 @@ TEST(checktransaction_tests, BadVersionTooLow) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_vin_empty) { +TEST(ChecktransactionTests, BadTxnsVinEmpty) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit.resize(0); mtx.vin.resize(0); @@ -124,7 +124,7 @@ TEST(checktransaction_tests, bad_txns_vin_empty) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_vout_empty) { +TEST(ChecktransactionTests, BadTxnsVoutEmpty) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit.resize(0); mtx.vout.resize(0); @@ -136,7 +136,7 @@ TEST(checktransaction_tests, bad_txns_vout_empty) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, BadTxnsOversize) { +TEST(ChecktransactionTests, BadTxnsOversize) { SelectParams(CBaseChainParams::REGTEST); CMutableTransaction mtx = GetValidTransaction(); @@ -195,7 +195,7 @@ TEST(checktransaction_tests, BadTxnsOversize) { } } -TEST(checktransaction_tests, OversizeSaplingTxns) { +TEST(ChecktransactionTests, OversizeSaplingTxns) { RegtestActivateSapling(); CMutableTransaction mtx = GetValidTransaction(); @@ -252,7 +252,7 @@ TEST(checktransaction_tests, OversizeSaplingTxns) { RegtestDeactivateSapling(); } -TEST(checktransaction_tests, bad_txns_vout_negative) { +TEST(ChecktransactionTests, BadTxnsVoutNegative) { CMutableTransaction mtx = GetValidTransaction(); mtx.vout[0].nValue = -1; @@ -263,7 +263,7 @@ TEST(checktransaction_tests, bad_txns_vout_negative) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_vout_toolarge) { +TEST(ChecktransactionTests, BadTxnsVoutToolarge) { CMutableTransaction mtx = GetValidTransaction(); mtx.vout[0].nValue = MAX_MONEY + 1; @@ -274,7 +274,7 @@ TEST(checktransaction_tests, bad_txns_vout_toolarge) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_txouttotal_toolarge_outputs) { +TEST(ChecktransactionTests, BadTxnsTxouttotalToolargeOutputs) { CMutableTransaction mtx = GetValidTransaction(); mtx.vout[0].nValue = MAX_MONEY; mtx.vout[1].nValue = 1; @@ -286,7 +286,7 @@ TEST(checktransaction_tests, bad_txns_txouttotal_toolarge_outputs) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, ValueBalanceNonZero) { +TEST(ChecktransactionTests, ValueBalanceNonZero) { CMutableTransaction mtx = GetValidTransaction(); mtx.valueBalance = 10; @@ -297,7 +297,7 @@ TEST(checktransaction_tests, ValueBalanceNonZero) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, PositiveValueBalanceTooLarge) { +TEST(ChecktransactionTests, PositiveValueBalanceTooLarge) { CMutableTransaction mtx = GetValidTransaction(); mtx.vShieldedSpend.resize(1); mtx.valueBalance = MAX_MONEY + 1; @@ -309,7 +309,7 @@ TEST(checktransaction_tests, PositiveValueBalanceTooLarge) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, NegativeValueBalanceTooLarge) { +TEST(ChecktransactionTests, NegativeValueBalanceTooLarge) { CMutableTransaction mtx = GetValidTransaction(); mtx.vShieldedSpend.resize(1); mtx.valueBalance = -(MAX_MONEY + 1); @@ -321,7 +321,7 @@ TEST(checktransaction_tests, NegativeValueBalanceTooLarge) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, ValueBalanceOverflowsTotal) { +TEST(ChecktransactionTests, ValueBalanceOverflowsTotal) { CMutableTransaction mtx = GetValidTransaction(); mtx.vShieldedSpend.resize(1); mtx.vout[0].nValue = 1; @@ -334,7 +334,7 @@ TEST(checktransaction_tests, ValueBalanceOverflowsTotal) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_txouttotal_toolarge_joinsplit) { +TEST(ChecktransactionTests, BadTxnsTxouttotalToolargeJoinsplit) { CMutableTransaction mtx = GetValidTransaction(); mtx.vout[0].nValue = 1; mtx.vJoinSplit[0].vpub_old = MAX_MONEY; @@ -346,7 +346,7 @@ TEST(checktransaction_tests, bad_txns_txouttotal_toolarge_joinsplit) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_txintotal_toolarge_joinsplit) { +TEST(ChecktransactionTests, BadTxnsTxintotalToolargeJoinsplit) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit[0].vpub_new = MAX_MONEY - 1; mtx.vJoinSplit[1].vpub_new = MAX_MONEY - 1; @@ -358,7 +358,7 @@ TEST(checktransaction_tests, bad_txns_txintotal_toolarge_joinsplit) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_vpub_old_negative) { +TEST(ChecktransactionTests, BadTxnsVpubOldNegative) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit[0].vpub_old = -1; @@ -369,7 +369,7 @@ TEST(checktransaction_tests, bad_txns_vpub_old_negative) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_vpub_new_negative) { +TEST(ChecktransactionTests, BadTxnsVpubNewNegative) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit[0].vpub_new = -1; @@ -380,7 +380,7 @@ TEST(checktransaction_tests, bad_txns_vpub_new_negative) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_vpub_old_toolarge) { +TEST(ChecktransactionTests, BadTxnsVpubOldToolarge) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit[0].vpub_old = MAX_MONEY + 1; @@ -391,7 +391,7 @@ TEST(checktransaction_tests, bad_txns_vpub_old_toolarge) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_vpub_new_toolarge) { +TEST(ChecktransactionTests, BadTxnsVpubNewToolarge) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit[0].vpub_new = MAX_MONEY + 1; @@ -402,7 +402,7 @@ TEST(checktransaction_tests, bad_txns_vpub_new_toolarge) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_vpubs_both_nonzero) { +TEST(ChecktransactionTests, BadTxnsVpubsBothNonzero) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit[0].vpub_old = 1; mtx.vJoinSplit[0].vpub_new = 1; @@ -414,7 +414,7 @@ TEST(checktransaction_tests, bad_txns_vpubs_both_nonzero) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_inputs_duplicate) { +TEST(ChecktransactionTests, BadTxnsInputsDuplicate) { CMutableTransaction mtx = GetValidTransaction(); mtx.vin[1].prevout.hash = mtx.vin[0].prevout.hash; mtx.vin[1].prevout.n = mtx.vin[0].prevout.n; @@ -426,7 +426,7 @@ TEST(checktransaction_tests, bad_txns_inputs_duplicate) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_joinsplits_nullifiers_duplicate_same_joinsplit) { +TEST(ChecktransactionTests, BadJoinsplitsNullifiersDuplicateSameJoinsplit) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit[0].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); mtx.vJoinSplit[0].nullifiers.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); @@ -438,7 +438,7 @@ TEST(checktransaction_tests, bad_joinsplits_nullifiers_duplicate_same_joinsplit) CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_joinsplits_nullifiers_duplicate_different_joinsplit) { +TEST(ChecktransactionTests, BadJoinsplitsNullifiersDuplicateDifferentJoinsplit) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit[0].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); mtx.vJoinSplit[1].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); @@ -450,7 +450,7 @@ TEST(checktransaction_tests, bad_joinsplits_nullifiers_duplicate_different_joins CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_cb_has_joinsplits) { +TEST(ChecktransactionTests, BadCbHasJoinsplits) { CMutableTransaction mtx = GetValidTransaction(); // Make it a coinbase. mtx.vin.resize(1); @@ -466,7 +466,7 @@ TEST(checktransaction_tests, bad_cb_has_joinsplits) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_cb_empty_scriptsig) { +TEST(ChecktransactionTests, BadCbEmptyScriptsig) { CMutableTransaction mtx = GetValidTransaction(); // Make it a coinbase. mtx.vin.resize(1); @@ -482,7 +482,7 @@ TEST(checktransaction_tests, bad_cb_empty_scriptsig) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_prevout_null) { +TEST(ChecktransactionTests, BadTxnsPrevoutNull) { CMutableTransaction mtx = GetValidTransaction(); mtx.vin[1].prevout.SetNull(); @@ -494,7 +494,7 @@ TEST(checktransaction_tests, bad_txns_prevout_null) { CheckTransactionWithoutProofVerification(tx, state); } -TEST(checktransaction_tests, bad_txns_invalid_joinsplit_signature) { +TEST(ChecktransactionTests, BadTxnsInvalidJoinsplitSignature) { SelectParams(CBaseChainParams::REGTEST); auto chainparams = Params(); @@ -505,12 +505,12 @@ TEST(checktransaction_tests, bad_txns_invalid_joinsplit_signature) { MockCValidationState state; // during initial block download, DoS ban score should be zero, else 100 EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); - ContextualCheckTransaction(tx, state, chainparams, 0, 100, [](const CChainParams&) { return false; });; + ContextualCheckTransaction(tx, state, chainparams, 0, 100, [](const CChainParams&) { return true; }); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); ContextualCheckTransaction(tx, state, chainparams, 0, 100, [](const CChainParams&) { return false; }); } -TEST(checktransaction_tests, non_canonical_ed25519_signature) { +TEST(ChecktransactionTests, NonCanonicalEd25519Signature) { SelectParams(CBaseChainParams::REGTEST); auto chainparams = Params(); @@ -542,12 +542,12 @@ TEST(checktransaction_tests, non_canonical_ed25519_signature) { MockCValidationState state; // during initial block download, DoS ban score should be zero, else 100 EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); - ContextualCheckTransaction(tx, state, chainparams, 0, 100, [](const CChainParams&) { return false; });; + ContextualCheckTransaction(tx, state, chainparams, 0, 100, [](const CChainParams&) { return true; }); EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1); ContextualCheckTransaction(tx, state, chainparams, 0, 100, [](const CChainParams&) { return false; }); } -TEST(checktransaction_tests, OverwinterConstructors) { +TEST(ChecktransactionTests, OverwinterConstructors) { CMutableTransaction mtx; mtx.fOverwintered = true; mtx.nVersion = OVERWINTER_TX_VERSION; @@ -578,7 +578,7 @@ TEST(checktransaction_tests, OverwinterConstructors) { EXPECT_TRUE(tx2 == tx); } -TEST(checktransaction_tests, OverwinterSerialization) { +TEST(ChecktransactionTests, OverwinterSerialization) { CMutableTransaction mtx; mtx.fOverwintered = true; mtx.nVersion = OVERWINTER_TX_VERSION; @@ -631,7 +631,7 @@ TEST(checktransaction_tests, OverwinterSerialization) { } } -TEST(checktransaction_tests, OverwinterDefaultValues) { +TEST(ChecktransactionTests, OverwinterDefaultValues) { // Check default values (this will fail when defaults change; test should then be updated) CTransaction tx; EXPECT_EQ(tx.nVersion, 1); @@ -641,7 +641,7 @@ TEST(checktransaction_tests, OverwinterDefaultValues) { } // A valid v3 transaction with no joinsplits -TEST(checktransaction_tests, OverwinterValidTx) { +TEST(ChecktransactionTests, OverwinterValidTx) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit.resize(0); mtx.fOverwintered = true; @@ -653,7 +653,7 @@ TEST(checktransaction_tests, OverwinterValidTx) { EXPECT_TRUE(CheckTransactionWithoutProofVerification(tx, state)); } -TEST(checktransaction_tests, OverwinterExpiryHeight) { +TEST(ChecktransactionTests, OverwinterExpiryHeight) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit.resize(0); mtx.fOverwintered = true; @@ -691,7 +691,7 @@ TEST(checktransaction_tests, OverwinterExpiryHeight) { } } -TEST(checktransaction_tests, BlossomExpiryHeight) { +TEST(ChecktransactionTests, BlossomExpiryHeight) { const Consensus::Params& params = RegtestActivateBlossom(false, 100); CMutableTransaction preBlossomMtx = CreateNewContextualCMutableTransaction(params, 99); EXPECT_EQ(preBlossomMtx.nExpiryHeight, 100 - 1); @@ -702,7 +702,7 @@ TEST(checktransaction_tests, BlossomExpiryHeight) { // Test that a Sprout tx with a negative version number is detected // given the new Overwinter logic -TEST(checktransaction_tests, SproutTxVersionTooLow) { +TEST(ChecktransactionTests, SproutTxVersionTooLow) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit.resize(0); mtx.fOverwintered = false; @@ -724,7 +724,7 @@ class UNSAFE_CTransaction : public CTransaction { UNSAFE_CTransaction(const CMutableTransaction &tx) : CTransaction(tx, true) {} }; -TEST(checktransaction_tests, SaplingSproutInputSumsTooLarge) { +TEST(ChecktransactionTests, SaplingSproutInputSumsTooLarge) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit.resize(0); mtx.fOverwintered = true; @@ -748,7 +748,6 @@ TEST(checktransaction_tests, SaplingSproutInputSumsTooLarge) { std::array outputMap; auto jsdesc = JSDescription::Randomized( - true, *params, joinSplitPubKey, rt, inputs, outputs, inputMap, outputMap, @@ -778,7 +777,7 @@ TEST(checktransaction_tests, SaplingSproutInputSumsTooLarge) { } // Test bad Overwinter version number in CheckTransactionWithoutProofVerification -TEST(checktransaction_tests, OverwinterVersionNumberLow) { +TEST(ChecktransactionTests, OverwinterVersionNumberLow) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit.resize(0); mtx.fOverwintered = true; @@ -793,7 +792,7 @@ TEST(checktransaction_tests, OverwinterVersionNumberLow) { } // Test bad Overwinter version number in ContextualCheckTransaction -TEST(checktransaction_tests, OverwinterVersionNumberHigh) { +TEST(ChecktransactionTests, OverwinterVersionNumberHigh) { SelectParams(CBaseChainParams::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); @@ -815,7 +814,7 @@ TEST(checktransaction_tests, OverwinterVersionNumberHigh) { // Test bad Overwinter version group id -TEST(checktransaction_tests, OverwinterBadVersionGroupId) { +TEST(ChecktransactionTests, OverwinterBadVersionGroupId) { CMutableTransaction mtx = GetValidTransaction(); mtx.vJoinSplit.resize(0); mtx.fOverwintered = true; @@ -830,7 +829,7 @@ TEST(checktransaction_tests, OverwinterBadVersionGroupId) { } // This tests an Overwinter transaction checked against Sprout -TEST(checktransaction_tests, OverwinterNotActive) { +TEST(ChecktransactionTests, OverwinterNotActive) { SelectParams(CBaseChainParams::TESTNET); auto chainparams = Params(); @@ -850,7 +849,7 @@ TEST(checktransaction_tests, OverwinterNotActive) { } // This tests a transaction without the fOverwintered flag set, against the Overwinter consensus rule set. -TEST(checktransaction_tests, OverwinterFlagNotSet) { +TEST(ChecktransactionTests, OverwinterFlagNotSet) { SelectParams(CBaseChainParams::REGTEST); UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); @@ -871,7 +870,7 @@ TEST(checktransaction_tests, OverwinterFlagNotSet) { // Overwinter (NU0) does not allow soft fork to version 4 Overwintered tx. -TEST(checktransaction_tests, OverwinterInvalidSoftForkVersion) { +TEST(ChecktransactionTests, OverwinterInvalidSoftForkVersion) { CMutableTransaction mtx = GetValidTransaction(); mtx.fOverwintered = true; mtx.nVersion = 4; // This is not allowed @@ -903,7 +902,7 @@ static void ContextualCreateTxCheck(const Consensus::Params& params, int nHeight // Test CreateNewContextualCMutableTransaction sets default values based on height -TEST(checktransaction_tests, OverwinteredContextualCreateTx) { +TEST(ChecktransactionTests, OverwinteredContextualCreateTx) { SelectParams(CBaseChainParams::REGTEST); const Consensus::Params& params = Params().GetConsensus(); int overwinterActivationHeight = 5; @@ -930,10 +929,14 @@ TEST(checktransaction_tests, OverwinteredContextualCreateTx) { ContextualCreateTxCheck(params, saplingActivationHeight - DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA + 3, OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); // Just before Sapling activation - ContextualCreateTxCheck(params, saplingActivationHeight - 4, OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); - ContextualCreateTxCheck(params, saplingActivationHeight - 3, OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); - ContextualCreateTxCheck(params, saplingActivationHeight - 2, OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); - ContextualCreateTxCheck(params, saplingActivationHeight - 1, OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); + ContextualCreateTxCheck(params, saplingActivationHeight - 4, + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); + ContextualCreateTxCheck(params, saplingActivationHeight - 3, + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); + ContextualCreateTxCheck(params, saplingActivationHeight - 2, + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); + ContextualCreateTxCheck(params, saplingActivationHeight - 1, + OVERWINTER_TX_VERSION, true, OVERWINTER_VERSION_GROUP_ID, saplingActivationHeight - 1); // Sapling activates ContextualCreateTxCheck(params, saplingActivationHeight, SAPLING_TX_VERSION, true, SAPLING_VERSION_GROUP_ID, saplingActivationHeight + DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA); @@ -942,7 +945,7 @@ TEST(checktransaction_tests, OverwinteredContextualCreateTx) { } // Test a v1 transaction which has a malformed header, perhaps modified in-flight -TEST(checktransaction_tests, BadTxReceivedOverNetwork) +TEST(ChecktransactionTests, BadTxReceivedOverNetwork) { // First four bytes <01 00 00 00> have been modified to be (-4 as an int32) std::string goodPrefix = "01000000"; diff --git a/src/gtest/test_circuit.cpp b/src/gtest/test_circuit.cpp deleted file mode 100644 index ab2a8ecb6..000000000 --- a/src/gtest/test_circuit.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include -#include "uint256.h" - -#include "zcash/util.h" - -#include -#include -#include - -#include -#include -#include -#include - -#include "zcash/IncrementalMerkleTree.hpp" - -using namespace libsnark; -using namespace libzcash; - -#include "zcash/circuit/utils.tcc" -#include "zcash/circuit/merkle.tcc" - -template -void test_value_equals(uint64_t i) { - protoboard pb; - pb_variable_array num; - num.allocate(pb, 64, ""); - num.fill_with_bits(pb, uint64_to_bool_vector(i)); - pb.add_r1cs_constraint(r1cs_constraint( - packed_addition(num), - FieldT::one(), - FieldT::one() * i - ), ""); - ASSERT_TRUE(pb.is_satisfied()); -} - -TEST(circuit, values) -{ - typedef Fr FieldT; - test_value_equals(0); - test_value_equals(1); - test_value_equals(3); - test_value_equals(5391); - test_value_equals(883128374); - test_value_equals(173419028459); - test_value_equals(2205843009213693953); -} - -TEST(circuit, endianness) -{ - std::vector before = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63 - }; - auto result = swap_endianness_u64(before); - - std::vector after = { - 56, 57, 58, 59, 60, 61, 62, 63, - 48, 49, 50, 51, 52, 53, 54, 55, - 40, 41, 42, 43, 44, 45, 46, 47, - 32, 33, 34, 35, 36, 37, 38, 39, - 24, 25, 26, 27, 28, 29, 30, 31, - 16, 17, 18, 19, 20, 21, 22, 23, - 8, 9, 10, 11, 12, 13, 14, 15, - 0, 1, 2, 3, 4, 5, 6, 7 - }; - - EXPECT_EQ(after, result); - - std::vector bad = {0, 1, 2, 3}; - - ASSERT_THROW(swap_endianness_u64(bad), std::length_error); -} - -template -bool test_merkle_gadget( - bool enforce_a, - bool enforce_b, - bool write_root_first -) -{ - protoboard pb; - digest_variable root(pb, 256, "root"); - pb.set_input_sizes(256); - - digest_variable commitment1(pb, 256, "commitment1"); - digest_variable commitment2(pb, 256, "commitment2"); - - pb_variable commitment1_read; - commitment1_read.allocate(pb); - pb_variable commitment2_read; - commitment2_read.allocate(pb); - - merkle_tree_gadget mgadget1(pb, commitment1, root, commitment1_read); - merkle_tree_gadget mgadget2(pb, commitment2, root, commitment2_read); - - commitment1.generate_r1cs_constraints(); - commitment2.generate_r1cs_constraints(); - root.generate_r1cs_constraints(); - mgadget1.generate_r1cs_constraints(); - mgadget2.generate_r1cs_constraints(); - - SproutMerkleTree tree; - uint256 commitment1_data = uint256S("54d626e08c1c802b305dad30b7e54a82f102390cc92c7d4db112048935236e9c"); - uint256 commitment2_data = uint256S("59d2cde5e65c1414c32ba54f0fe4bdb3d67618125286e6a191317917c812c6d7"); - tree.append(commitment1_data); - auto wit1 = tree.witness(); - tree.append(commitment2_data); - wit1.append(commitment2_data); - auto wit2 = tree.witness(); - auto expected_root = tree.root(); - tree.append(uint256S("3e243c8798678570bb8d42616c23a536af44be15c4eef073490c2a44ae5f32c3")); - auto unexpected_root = tree.root(); - tree.append(uint256S("26d9b20c7f1c3d2528bbcd43cd63344b0afd3b6a0a8ebd37ec51cba34907bec7")); - auto badwit1 = tree.witness(); - tree.append(uint256S("02c2467c9cd15e0d150f74cd636505ed675b0b71b66a719f6f52fdb49a5937bb")); - auto badwit2 = tree.witness(); - - // Perform the test - - pb.val(commitment1_read) = enforce_a ? FieldT::one() : FieldT::zero(); - pb.val(commitment2_read) = enforce_b ? FieldT::one() : FieldT::zero(); - - commitment1.bits.fill_with_bits(pb, uint256_to_bool_vector(commitment1_data)); - commitment2.bits.fill_with_bits(pb, uint256_to_bool_vector(commitment2_data)); - - if (write_root_first) { - root.bits.fill_with_bits(pb, uint256_to_bool_vector(expected_root)); - } - - mgadget1.generate_r1cs_witness(wit1.path()); - mgadget2.generate_r1cs_witness(wit2.path()); - - // Overwrite with our expected root - root.bits.fill_with_bits(pb, uint256_to_bool_vector(expected_root)); - - return pb.is_satisfied(); -} - -TEST(circuit, merkle_tree_gadget_weirdness) -{ - /* - The merkle tree gadget takes a leaf in the merkle tree (the Note commitment), - a merkle tree authentication path, and a root (anchor). It also takes a parameter - called read_success, which is used to determine if the commitment actually needs to - appear in the tree. - - If two input notes use the same root (which our protocol does) then if `read_success` - is disabled on the first note but enabled on the second note (i.e., the first note - has value of zero and second note has nonzero value) then there is an edge case in - the witnessing behavior. The first witness will accidentally constrain the root to - equal null (the default value of the anchor) and the second witness will actually - copy the bits, violating the constraint system. - - Notice that this edge case is not in the constraint system but in the witnessing - behavior. - */ - - typedef Fr FieldT; - - // Test the normal case - ASSERT_TRUE(test_merkle_gadget(true, true, false)); - ASSERT_TRUE(test_merkle_gadget(true, true, true)); - - // Test the case where the first commitment is enforced but the second isn't - // Works because the first read is performed before the second one - ASSERT_TRUE(test_merkle_gadget(true, false, false)); - ASSERT_TRUE(test_merkle_gadget(true, false, true)); - - // Test the case where the first commitment isn't enforced but the second is - // Doesn't work because the first multipacker witnesses the existing root (which - // is null) - ASSERT_TRUE(!test_merkle_gadget(false, true, false)); - - // Test the last again, except this time write the root first. - ASSERT_TRUE(test_merkle_gadget(false, true, true)); -} diff --git a/src/gtest/test_consensus.cpp b/src/gtest/test_consensus.cpp new file mode 100644 index 000000000..46dd730dd --- /dev/null +++ b/src/gtest/test_consensus.cpp @@ -0,0 +1,69 @@ +#include +#include + +#include "uint256.h" +#include "utilstrencodings.h" + +void TestLibsodiumEd25519SignatureVerification( + const std::string &scope, + const std::string &msg, + std::vector pubkey, + std::vector sig) +{ + SCOPED_TRACE(scope); + + EXPECT_EQ( + crypto_sign_verify_detached( + sig.data(), + (const unsigned char*)msg.data(), msg.size(), + pubkey.data()), + 0); +} + +TEST(ConsensusTests, LibsodiumPubkeyValidation) { + // libsodium <= 1.0.15 accepts valid signatures for a non-zero pubkey with + // small order; this is currently part of our consensus rules. + // libsodium >= 1.0.16 rejects all pubkeys with small order. + // + // These test vectors were generated by finding pairs of points (A, P) both + // in the eight-torsion subgroup such that R = B + P and R = [1] B - [k] A + // (where SHA512(bytes(R) || bytes(A) || message) represents k in + // little-endian order, as in Ed25519). + TestLibsodiumEd25519SignatureVerification( + "Test vector 1", + "zcash ed25519 libsodium compatibility", + ParseHex("0100000000000000000000000000000000000000000000000000000000000000"), + ParseHex("58666666666666666666666666666666666666666666666666666666666666660100000000000000000000000000000000000000000000000000000000000000")); + TestLibsodiumEd25519SignatureVerification( + "Test vector 2", + "zcash ed25519 libsodium compatibility", + ParseHex("0000000000000000000000000000000000000000000000000000000000000080"), + ParseHex("58666666666666666666666666666666666666666666666666666666666666660100000000000000000000000000000000000000000000000000000000000000")); + TestLibsodiumEd25519SignatureVerification( + "Test vector 3", + "zcash ed25519 libsodium compatibility", + ParseHex("26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85"), + ParseHex("da99e28ba529cdde35a25fba9059e78ecaee239f99755b9b1aa4f65df00803e20100000000000000000000000000000000000000000000000000000000000000")); + TestLibsodiumEd25519SignatureVerification( + "Test vector 4", + "zcash ed25519 libsodium compatibility", + ParseHex("c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a"), + ParseHex("95999999999999999999999999999999999999999999999999999999999999990100000000000000000000000000000000000000000000000000000000000000")); + TestLibsodiumEd25519SignatureVerification( + "Test vector 5", + "zcash ed25519 libsodium compatibility", + ParseHex("26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85"), + ParseHex("13661d745ad63221ca5da0456fa618713511dc60668aa464e55b09a20ff7fc1d0100000000000000000000000000000000000000000000000000000000000000")); + + // libsodium <= 1.0.15 contains a blocklist of small-order points that R is + // checked against. However, it does not contain all canonical small-order + // points; in particular, it is missing the negative of one of the points. + // + // This test case is the only pair of points (A, R) both in the eight-torsion + // subgroup, that satisfies R = [0] B - [k] A and also evades the blocklist. + TestLibsodiumEd25519SignatureVerification( + "Small order R that is not rejected by libsodium <= 1.0.15", + "zcash ed25519 libsodium compatibility", + ParseHex("c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a"), + ParseHex("26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc850000000000000000000000000000000000000000000000000000000000000000")); +} diff --git a/src/gtest/test_deprecation.cpp b/src/gtest/test_deprecation.cpp index d84e160a0..19a3da9ab 100644 --- a/src/gtest/test_deprecation.cpp +++ b/src/gtest/test_deprecation.cpp @@ -12,6 +12,7 @@ #include #include +using namespace boost::placeholders; using ::testing::StrictMock; static const std::string CLIENT_VERSION_STR = FormatVersion(CLIENT_VERSION); @@ -34,14 +35,14 @@ static bool ThreadSafeMessageBox(MockUIInterface *mock, class DeprecationTest : public ::testing::Test { protected: - virtual void SetUp() { + void SetUp() override { uiInterface.ThreadSafeMessageBox.disconnect_all_slots(); uiInterface.ThreadSafeMessageBox.connect(boost::bind(ThreadSafeMessageBox, &mock_, _1, _2, _3)); SelectParams(CBaseChainParams::MAIN); } - virtual void TearDown() { + void TearDown() override { fRequestShutdown = false; mapArgs.clear(); } @@ -121,22 +122,6 @@ TEST_F(DeprecationTest, DeprecatedNodeIgnoredOnTestnet) { EXPECT_FALSE(ShutdownRequested()); } -TEST_F(DeprecationTest, DeprecatedNodeShutsDownIfOldVersionDisabled) { - EXPECT_FALSE(ShutdownRequested()); - mapArgs["-disabledeprecation"] = "1.0.0"; - EXPECT_CALL(mock_, ThreadSafeMessageBox(::testing::_, "", CClientUIInterface::MSG_ERROR)); - EnforceNodeDeprecation(DEPRECATION_HEIGHT); - EXPECT_TRUE(ShutdownRequested()); -} - -TEST_F(DeprecationTest, DeprecatedNodeKeepsRunningIfCurrentVersionDisabled) { - EXPECT_FALSE(ShutdownRequested()); - mapArgs["-disabledeprecation"] = CLIENT_VERSION_STR; - EXPECT_CALL(mock_, ThreadSafeMessageBox(::testing::_, "", CClientUIInterface::MSG_ERROR)); - EnforceNodeDeprecation(DEPRECATION_HEIGHT); - EXPECT_FALSE(ShutdownRequested()); -} - TEST_F(DeprecationTest, AlertNotify) { boost::filesystem::path temp = GetTempPath() / boost::filesystem::unique_path("alertnotify-%%%%.txt"); @@ -151,7 +136,7 @@ TEST_F(DeprecationTest, AlertNotify) { // -alertnotify restricts the message to safe characters. auto expectedMsg = strprintf( - "This version will be deprecated at block height %d, and will automatically shut down. You should upgrade to the latest version of Zcash.", + "This version will be deprecated at block height %d, and will automatically shut down. You should upgrade to the latest version of BitcoinZ.", DEPRECATION_HEIGHT); // Windows built-in echo semantics are different than posixy shells. Quotes and diff --git a/src/gtest/test_dynamicusage.cpp b/src/gtest/test_dynamicusage.cpp new file mode 100644 index 000000000..6cbb5d8ba --- /dev/null +++ b/src/gtest/test_dynamicusage.cpp @@ -0,0 +1,111 @@ +// Copyright (c) 2019 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#include +#include + +#include "coins.h" +#include "init.h" +#include "key.h" +#include "transaction_builder.h" +#include "utiltest.h" + +extern ZCJoinSplit* params; + +TEST(RecursiveDynamicUsageTests, TestTransactionTransparent) +{ + auto consensusParams = RegtestActivateSapling(); + + CBasicKeyStore keystore; + CKey tsk = AddTestCKeyToKeyStore(keystore); + auto scriptPubKey = GetScriptForDestination(tsk.GetPubKey().GetID()); + CTxDestination taddr = tsk.GetPubKey().GetID(); + + auto builder = TransactionBuilder(consensusParams, 1, &keystore); + builder.AddTransparentInput(COutPoint(), scriptPubKey, 50000); + builder.AddTransparentOutput(taddr, 40000); + + auto tx = builder.Build().GetTxOrThrow(); + // 1 vin + 1 vout + // (96 + 128) + 64 + EXPECT_EQ(288, RecursiveDynamicUsage(tx)); + + RegtestDeactivateSapling(); +} + +TEST(RecursiveDynamicUsageTests, TestTransactionJoinSplit) +{ + auto consensusParams = RegtestActivateSapling(); + + auto sproutSk = libzcash::SproutSpendingKey::random(); + + auto wtx = GetValidSproutReceive(*params, sproutSk, 25000, true); + // 2 vin + 1 vJoinSplit + 1 vShieldedOutput + // 160 + 1856 + 976 + EXPECT_EQ(2992, RecursiveDynamicUsage(wtx)); + + RegtestDeactivateSapling(); +} + +TEST(RecursiveDynamicUsageTests, TestTransactionSaplingToSapling) +{ + auto consensusParams = RegtestActivateSapling(); + + auto sk = libzcash::SaplingSpendingKey::random(); + auto testNote = GetTestSaplingNote(sk.default_address(), 50000); + + auto builder = TransactionBuilder(consensusParams, 1); + builder.AddSaplingSpend(sk.expanded_spending_key(), testNote.note, testNote.tree.root(), testNote.tree.witness()); + builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 5000, {}); + + auto tx = builder.Build().GetTxOrThrow(); + // 1 vShieldedSpend + 2 vShieldedOutput + // 400 + 1920 + EXPECT_EQ(2320, RecursiveDynamicUsage(tx)); + + RegtestDeactivateSapling(); +} + +TEST(RecursiveDynamicUsageTests, TestTransactionTransparentToSapling) +{ + auto consensusParams = RegtestActivateSapling(); + + CBasicKeyStore keystore; + CKey tsk = AddTestCKeyToKeyStore(keystore); + auto scriptPubKey = GetScriptForDestination(tsk.GetPubKey().GetID()); + auto sk = libzcash::SaplingSpendingKey::random(); + + auto builder = TransactionBuilder(consensusParams, 1, &keystore); + builder.AddTransparentInput(COutPoint(), scriptPubKey, 50000); + builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 40000, {}); + + auto tx = builder.Build().GetTxOrThrow(); + // 1 vin + 1 vShieldedOutput + // (96 + 128) + 976 + EXPECT_EQ(1200, RecursiveDynamicUsage(tx)); + + RegtestDeactivateSapling(); +} + +TEST(RecursiveDynamicUsageTests, TestTransactionSaplingToTransparent) +{ + auto consensusParams = RegtestActivateSapling(); + + CBasicKeyStore keystore; + CKey tsk = AddTestCKeyToKeyStore(keystore); + CTxDestination taddr = tsk.GetPubKey().GetID(); + auto sk = libzcash::SaplingSpendingKey::random(); + auto testNote = GetTestSaplingNote(sk.default_address(), 50000); + + auto builder = TransactionBuilder(consensusParams, 1, &keystore); + builder.AddSaplingSpend(sk.expanded_spending_key(), testNote.note, testNote.tree.root(), testNote.tree.witness()); + builder.AddTransparentOutput(taddr, 40000); + + auto tx = builder.Build().GetTxOrThrow(); + // 1 vShieldedSpend + 1 vout + // 400 + 64 + EXPECT_EQ(464, RecursiveDynamicUsage(tx)); + + RegtestDeactivateSapling(); +} diff --git a/src/gtest/test_equihash.cpp b/src/gtest/test_equihash.cpp index 6134e43c9..c1cfad746 100644 --- a/src/gtest/test_equihash.cpp +++ b/src/gtest/test_equihash.cpp @@ -25,7 +25,7 @@ void TestExpandAndCompress(const std::string &scope, size_t bit_len, size_t byte EXPECT_EQ(compact, out); } -TEST(equihash_tests, expand_and_contract_arrays) { +TEST(EquihashTests, ExpandAndContractArrays) { TestExpandAndCompress("8 11-bit chunks, all-ones", 11, 0, ParseHex("ffffffffffffffffffffff"), ParseHex("07ff07ff07ff07ff07ff07ff07ff07ff")); @@ -54,7 +54,7 @@ void TestMinimalSolnRepr(const std::string &scope, size_t cBitLen, EXPECT_EQ(minimal, GetMinimalFromIndices(indices, cBitLen)); } -TEST(equihash_tests, minimal_solution_representation) { +TEST(EquihashTests, MinimalSolutionRepresentation) { TestMinimalSolnRepr("Test 1", 20, {1, 1, 1, 1, 1, 1, 1, 1}, ParseHex("000008000040000200001000008000040000200001")); @@ -70,7 +70,7 @@ TEST(equihash_tests, minimal_solution_representation) { ParseHex("000220000a7ffffe004d10014c800ffc00002fffff")); } -TEST(equihash_tests, is_probably_duplicate) { +TEST(EquihashTests, IsProbablyDuplicate) { std::shared_ptr p1 (new eh_trunc[4] {0, 1, 2, 3}, std::default_delete()); std::shared_ptr p2 (new eh_trunc[4] {0, 1, 1, 3}, std::default_delete()); std::shared_ptr p3 (new eh_trunc[4] {3, 1, 1, 3}, std::default_delete()); @@ -81,7 +81,7 @@ TEST(equihash_tests, is_probably_duplicate) { } #ifdef ENABLE_MINING -TEST(equihash_tests, check_basic_solver_cancelled) { +TEST(EquihashTests, CheckBasicSolverCancelled) { Equihash<48,5> Eh48_5; crypto_generichash_blake2b_state state; Eh48_5.InitialiseState(state); @@ -185,7 +185,7 @@ TEST(equihash_tests, check_basic_solver_cancelled) { } } -TEST(equihash_tests, check_optimised_solver_cancelled) { +TEST(EquihashTests, CheckOptimisedSolverCancelled) { Equihash<48,5> Eh48_5; crypto_generichash_blake2b_state state; Eh48_5.InitialiseState(state); diff --git a/src/gtest/test_foundersreward.cpp b/src/gtest/test_foundersreward.cpp index a497cff52..296ea6eb6 100644 --- a/src/gtest/test_foundersreward.cpp +++ b/src/gtest/test_foundersreward.cpp @@ -16,15 +16,15 @@ #include "utiltest.h" // To run tests: -// ./zcash-gtest --gtest_filter="founders_reward_test.*" +// ./bitcoinz-gtest --gtest_filter="FoundersRewardTest.*" // // Enable this test to generate and print 48 testnet 2-of-3 multisig addresses. // The output can be copied into chainparams.cpp. -// The temporary wallet file can be renamed as wallet.dat and used for testing with zcashd. +// The temporary wallet file can be renamed as wallet.dat and used for testing with bitcoinzd. // #if 0 -TEST(founders_reward_test, create_testnet_2of3multisig) { +TEST(FoundersRewardTest, create_testnet_2of3multisig) { SelectParams(CBaseChainParams::TESTNET); boost::filesystem::path pathTemp = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); boost::filesystem::create_directories(pathTemp); @@ -83,41 +83,33 @@ TEST(founders_reward_test, create_testnet_2of3multisig) { } #endif -static int GetLastCommunityFeeHeight(const Consensus::Params& params) { - int blossomActivationHeight = Params().GetConsensus().vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight; - bool blossom = blossomActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; - //return params.GetLastCommunityFeeBlockHeight(blossom ? blossomActivationHeight : 0); - return Params().GetLastCommunityFeeBlockHeight(); -} - -// Utility method to check the number of unique addresses from height 1 to maxHeight +// Utility method to check the number of unique addresses from 1 to maxHeight void checkNumberOfUniqueAddresses(int nUnique) { - int maxHeight = Params().GetLastCommunityFeeBlockHeight(); std::set addresses; - for (int i = 1; i <= maxHeight; i++) { + for (int i = 1; i <= Params().GetLastCommunityFeeBlockHeight(); i++) { addresses.insert(Params().GetCommunityFeeAddressAtHeight(i)); } - //EXPECT_EQ(addresses.size(), nUnique); - ASSERT_TRUE(addresses.size() == nUnique); + EXPECT_EQ(addresses.size(), nUnique); } -TEST(founders_reward_test, general) { +TEST(FoundersRewardTest, General) { SelectParams(CBaseChainParams::TESTNET); CChainParams params = Params(); // Fourth testnet reward: - // address = t2ENg7hHVqqs9JwU5cgjvSbxnT2a9USNfhy - // script.ToString() = OP_HASH160 55d64928e69829d9376c776550b6cc710d427153 OP_EQUAL - // HexStr(script) = a91455d64928e69829d9376c776550b6cc710d42715387 - EXPECT_EQ(HexStr(params.GetCommunityFeeScriptAtHeight(1)), "a914ef775f1f997f122a062fff1a2d7443abd1f9c64287"); - EXPECT_EQ(params.GetCommunityFeeAddressAtHeight(1), "t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi"); - EXPECT_EQ(HexStr(params.GetCommunityFeeScriptAtHeight(53126)), "a914ac67f4c072668138d88a86ff21b27207b283212f87"); - EXPECT_EQ(params.GetCommunityFeeAddressAtHeight(53126), "t2NGQjYMQhFndDHguvUw4wZdNdsssA6K7x2"); - EXPECT_EQ(HexStr(params.GetCommunityFeeScriptAtHeight(53127)), "a91455d64928e69829d9376c776550b6cc710d42715387"); - EXPECT_EQ(params.GetCommunityFeeAddressAtHeight(53127), "t2ENg7hHVqqs9JwU5cgjvSbxnT2a9USNfhy"); - + // address = t2EwBFfC96DCiCAcJuEqGUbUes8rTNmaD6Q + // script.ToString() = OP_HASH160 5bfbeb4df59710514b7004041e75ad287dad9bc8 OP_EQUAL + // HexStr(script) = a9145bfbeb4df59710514b7004041e75ad287dad9bc887 + EXPECT_EQ(HexStr(params.GetCommunityFeeScriptAtHeight(1)), "a91465a7c41acd34d55e7001a02d68c39f5470ae38cf87"); + EXPECT_EQ(params.GetCommunityFeeAddressAtHeight(1), "t2FpKCWt95LAPVRed61YbBny9yz5nqexLGN"); + EXPECT_EQ(HexStr(params.GetCommunityFeeScriptAtHeight(53126)), "a9145bfbeb4df59710514b7004041e75ad287dad9bc887"); + EXPECT_EQ(params.GetCommunityFeeAddressAtHeight(53126), "t2EwBFfC96DCiCAcJuEqGUbUes8rTNmaD6Q"); + EXPECT_EQ(HexStr(params.GetCommunityFeeScriptAtHeight(53127)), "a9145bfbeb4df59710514b7004041e75ad287dad9bc887"); + EXPECT_EQ(params.GetCommunityFeeAddressAtHeight(53127), "t2EwBFfC96DCiCAcJuEqGUbUes8rTNmaD6Q"); + + int minHeight = params.GetCommunityFeeStartHeight(); int maxHeight = params.GetLastCommunityFeeBlockHeight(); // If the block height parameter is out of bounds, there is an assert. @@ -127,34 +119,32 @@ TEST(founders_reward_test, general) { EXPECT_DEATH(params.GetCommunityFeeAddressAtHeight(maxHeight+1), "nHeight"); } -TEST(founders_reward_test, regtest_get_last_block_blossom) { +TEST(FoundersRewardTest, RegtestGetLastBlockBlossom) { int blossomActivationHeight = Consensus::PRE_BLOSSOM_REGTEST_HALVING_INTERVAL / 2; // = 75 auto params = RegtestActivateBlossom(false, blossomActivationHeight); - int lastFRHeight = Params().GetLastCommunityFeeBlockHeight(); - EXPECT_EQ(0, params.Halving(lastFRHeight)); - EXPECT_EQ(1, params.Halving(lastFRHeight + 1)); + int lastCFHeight = Params().GetLastCommunityFeeBlockHeight(); + EXPECT_EQ(0, params.Halving(lastCFHeight)); RegtestDeactivateBlossom(); } -TEST(founders_reward_test, mainnet_get_last_block) { +TEST(FoundersRewardTest, MainnetGetLastBlock) { SelectParams(CBaseChainParams::MAIN); auto params = Params().GetConsensus(); - int lastFRHeight = GetLastCommunityFeeHeight(params); - EXPECT_EQ(0, params.Halving(lastFRHeight)); - EXPECT_EQ(1, params.Halving(lastFRHeight + 1)); + int lastCFHeight = Params().GetLastCommunityFeeBlockHeight(); + EXPECT_EQ(1, params.Halving(lastCFHeight)); } -#define NUM_MAINNET_FOUNDER_ADDRESSES 48 +#define NUM_MAINNET_FOUNDER_ADDRESSES 100 -TEST(founders_reward_test, mainnet) { +TEST(FoundersRewardTest, Mainnet) { SelectParams(CBaseChainParams::MAIN); checkNumberOfUniqueAddresses(NUM_MAINNET_FOUNDER_ADDRESSES); } -#define NUM_TESTNET_FOUNDER_ADDRESSES 48 +#define NUM_TESTNET_FOUNDER_ADDRESSES 100 -TEST(founders_reward_test, testnet) { +TEST(FoundersRewardTest, Testnet) { SelectParams(CBaseChainParams::TESTNET); checkNumberOfUniqueAddresses(NUM_TESTNET_FOUNDER_ADDRESSES); } @@ -162,60 +152,88 @@ TEST(founders_reward_test, testnet) { #define NUM_REGTEST_FOUNDER_ADDRESSES 1 -TEST(founders_reward_test, regtest) { +TEST(FoundersRewardTest, Regtest) { SelectParams(CBaseChainParams::REGTEST); checkNumberOfUniqueAddresses(NUM_REGTEST_FOUNDER_ADDRESSES); } -// Test that 10% community fee is fully rewarded after the first halving and slow start shift. -// On Mainnet, this would be 2,100,000 ZEC after 850,000 blocks (840,000 + 10,000). -TEST(founders_reward_test, slow_start_subsidy) { +// Test that 5% community fee is fully rewarded in a defined period. +// On Mainnet: nHeight > 328500 && nHeight <= 1400000 (494687187.5 BTCZ) +TEST(FoundersRewardTest, SlowStartSubsidy) { SelectParams(CBaseChainParams::MAIN); CChainParams params = Params(); + int minHeight = params.GetCommunityFeeStartHeight(); int maxHeight = params.GetLastCommunityFeeBlockHeight(); + CAmount totalSubsidy = 0; for (int nHeight = 1; nHeight <= maxHeight; nHeight++) { - CAmount nSubsidy = GetBlockSubsidy(nHeight, params.GetConsensus()) / 5; - totalSubsidy += nSubsidy; + CAmount nSubsidy = GetBlockSubsidy(nHeight, params.GetConsensus()) * 0.05; + if (nHeight > minHeight) { + totalSubsidy += nSubsidy; + } } - ASSERT_TRUE(totalSubsidy == MAX_MONEY/10.0); + EXPECT_EQ(totalSubsidy, 49468718750000000); } -// For use with mainnet and testnet which each have 48 addresses. +// For use with mainnet and testnet which each have 100 addresses. // Verify the number of rewards each individual address receives. -void verifyNumberOfRewards() { +// Since on the main network vCommunityFeeStartHeight does not start from 0, +// the first 22 elements of vCommunityFeeAddress are skipped. +void verifyNumberOfRewards(bool fMainNet) { CChainParams params = Params(); + + int minHeight = params.GetCommunityFeeStartHeight(); int maxHeight = params.GetLastCommunityFeeBlockHeight(); + std::map ms; for (int nHeight = 1; nHeight <= maxHeight; nHeight++) { std::string addr = params.GetCommunityFeeAddressAtHeight(nHeight); if (ms.count(addr) == 0) { ms[addr] = 0; } - ms[addr] = ms[addr] + GetBlockSubsidy(nHeight, params.GetConsensus()) / 5; + if (nHeight > minHeight) { + ms[addr] = ms[addr] + GetBlockSubsidy(nHeight, params.GetConsensus()) * 0.05; + } + } + + if (fMainNet) { + EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(0)], 0 * 625 * COIN); + EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(1)], 0 * 625 * COIN); + EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(22)], 0 * 625 * COIN); + EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(23)], 7523 * 625 * COIN); + } else { + EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(0)], 12500 * 625 * COIN); + EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(1)], 14001 * 625 * COIN); + EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(22)], 14001 * 625 * COIN); + EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(23)], 14001 * 625 * COIN); } - EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(0)], 1960039937500); - EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(1)], 4394460062500); - for (int i = 2; i <= 46; i++) { - EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(i)], 17709 * COIN * 2.5); + for (int i = 24; i <= 58; i++) { + EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(i)], 14001 * 625 * COIN); } - EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(47)], 17677 * COIN * 2.5); + + EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(59)], 8731875 * COIN); + + for (int i = 60; i <= 98; i++) { + EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(i)], 14001 * 312.5 * COIN); + } + + EXPECT_EQ(ms[params.GetCommunityFeeAddressAtIndex(99)], 13902 * 312.5 * COIN); } // Verify the number of rewards going to each mainnet address -TEST(founders_reward_test, per_address_reward_mainnet) { +TEST(FoundersRewardTest, PerAddressRewardMainnet) { SelectParams(CBaseChainParams::MAIN); - verifyNumberOfRewards(); + verifyNumberOfRewards(true); } // Verify the number of rewards going to each testnet address -TEST(founders_reward_test, per_address_reward_testnet) { +TEST(FoundersRewardTest, PerAddressRewardTestnet) { SelectParams(CBaseChainParams::TESTNET); - verifyNumberOfRewards(); + verifyNumberOfRewards(false); } diff --git a/src/gtest/test_joinsplit.cpp b/src/gtest/test_joinsplit.cpp index c54f07823..da5433dde 100644 --- a/src/gtest/test_joinsplit.cpp +++ b/src/gtest/test_joinsplit.cpp @@ -2,9 +2,6 @@ #include "utilstrencodings.h" -#include -#include - #include "zcash/prf.h" #include "util.h" #include "streams.h" @@ -22,10 +19,9 @@ using namespace libzcash; extern ZCJoinSplit* params; -typedef std::array SproutProofs; -// Make both the PHGR and Groth proof for a Sprout statement, -// and store the results in JSDescription objects. -SproutProofs makeSproutProofs( +// Make the Groth proof for a Sprout statement, +// and store the result in a JSDescription object. +JSDescription makeSproutProof( ZCJoinSplit& js, const std::array& inputs, const std::array& outputs, @@ -34,25 +30,17 @@ SproutProofs makeSproutProofs( uint64_t vpub_new, const uint256& rt ){ - //Making the PHGR proof - JSDescription phgr(false, js, joinSplitPubKey, rt, inputs, outputs, vpub_old, vpub_new); - //Making the Groth proof - JSDescription groth(true, js, joinSplitPubKey, rt, inputs, outputs, vpub_old, vpub_new); - - return {phgr, groth}; - + return JSDescription(js, joinSplitPubKey, rt, inputs, outputs, vpub_old, vpub_new); } -bool verifySproutProofs( +bool verifySproutProof( ZCJoinSplit& js, - const SproutProofs& jsdescs, + const JSDescription& jsdesc, const uint256& joinSplitPubKey ) { auto verifier = libzcash::ProofVerifier::Strict(); - bool phgrPassed = jsdescs[0].Verify(js, verifier, joinSplitPubKey); - bool grothPassed = jsdescs[1].Verify(js, verifier, joinSplitPubKey); - return phgrPassed && grothPassed; + return jsdesc.Verify(js, verifier, joinSplitPubKey); } @@ -73,7 +61,7 @@ void test_full_api(ZCJoinSplit* js) uint64_t vpub_new = 0; uint256 joinSplitPubKey = random_uint256(); uint256 rt = tree.root(); - SproutProofs jsdescs; + JSDescription jsdesc; { std::array inputs = { @@ -89,7 +77,7 @@ void test_full_api(ZCJoinSplit* js) std::array output_notes; // Perform the proofs - jsdescs = makeSproutProofs( + jsdesc = makeSproutProof( *js, inputs, outputs, @@ -101,13 +89,11 @@ void test_full_api(ZCJoinSplit* js) } // Verify both PHGR and Groth Proof: - ASSERT_TRUE(verifySproutProofs(*js, jsdescs, joinSplitPubKey)); + ASSERT_TRUE(verifySproutProof(*js, jsdesc, joinSplitPubKey)); - // Run tests using both phgr and groth as basis for field values - for (auto jsdesc : jsdescs) { SproutMerkleTree tree; - SproutProofs jsdescs2; + JSDescription jsdesc2; // Recipient should decrypt // Now the recipient should spend the money again auto h_sig = js->h_sig(jsdesc.randomSeed, jsdesc.nullifiers, joinSplitPubKey); @@ -153,7 +139,7 @@ void test_full_api(ZCJoinSplit* js) // Perform the proofs - jsdescs2 = makeSproutProofs( + jsdesc2 = makeSproutProof( *js, inputs, outputs, @@ -166,8 +152,8 @@ void test_full_api(ZCJoinSplit* js) } - // Verify both PHGR and Groth Proof: - ASSERT_TRUE(verifySproutProofs(*js, jsdescs2, joinSplitPubKey2)); + // Verify Groth Proof: + ASSERT_TRUE(verifySproutProof(*js, jsdesc2, joinSplitPubKey2)); } } @@ -191,28 +177,8 @@ void invokeAPI( std::array output_notes; - // PHGR - SproutProof proof = js->prove( - false, - inputs, - outputs, - output_notes, - ciphertexts, - ephemeralKey, - joinSplitPubKey, - randomSeed, - macs, - nullifiers, - commitments, - vpub_old, - vpub_new, - rt, - false - ); - // Groth - proof = js->prove( - true, + SproutProof proof = js->prove( inputs, outputs, output_notes, @@ -250,7 +216,7 @@ void invokeAPIFailure( } } -TEST(joinsplit, h_sig) +TEST(Joinsplit, HSig) { /* // by Taylor Hornby @@ -314,7 +280,7 @@ for test_input in TEST_VECTORS: } }; - BOOST_FOREACH(std::vector& v, tests) { + for (std::vector& v : tests) { auto expected = ZCJoinSplit::h_sig( uint256S(v[0]), {uint256S(v[1]), uint256S(v[2])}, @@ -338,7 +304,7 @@ void increment_note_witnesses( witnesses.push_back(tree.witness()); } -TEST(joinsplit, full_api_test) +TEST(Joinsplit, FullApiTest) { { std::vector witnesses; @@ -540,7 +506,7 @@ TEST(joinsplit, full_api_test) test_full_api(params); } -TEST(joinsplit, note_plaintexts) +TEST(Joinsplit, NotePlaintexts) { uint252 a_sk = uint252(uint256S("f6da8716682d600f74fc16bd0187faad6a26b4aa4c24d5c055b216d94516840e")); uint256 a_pk = PRF_addr_a_pk(a_sk); @@ -593,7 +559,7 @@ TEST(joinsplit, note_plaintexts) ASSERT_EQ(note_pt.r, note_pt2.r); } -TEST(joinsplit, note_class) +TEST(Joinsplit, NoteClass) { uint252 a_sk = uint252(uint256S("f6da8716682d600f74fc16bd0187faad6a26b4aa4c24d5c055b216d94516840e")); uint256 a_pk = PRF_addr_a_pk(a_sk); diff --git a/src/gtest/test_keys.cpp b/src/gtest/test_keys.cpp index a74ef066d..8caebdd92 100644 --- a/src/gtest/test_keys.cpp +++ b/src/gtest/test_keys.cpp @@ -4,6 +4,8 @@ #include "utiltest.h" +#include + #include TEST(Keys, EncodeAndDecodeSapling) @@ -23,9 +25,9 @@ TEST(Keys, EncodeAndDecodeSapling) auto spendingkey2 = DecodeSpendingKey(sk_string); EXPECT_TRUE(IsValidSpendingKey(spendingkey2)); - ASSERT_TRUE(boost::get(&spendingkey2) != nullptr); - auto sk2 = boost::get(spendingkey2); - EXPECT_EQ(sk, sk2); + ASSERT_TRUE(std::get_if(&spendingkey2) != nullptr); + auto sk2 = std::get(spendingkey2); + EXPECT_EQ(sk, sk2); } { auto extfvk = sk.ToXFVK(); @@ -37,8 +39,8 @@ TEST(Keys, EncodeAndDecodeSapling) auto viewingkey2 = DecodeViewingKey(vk_string); EXPECT_TRUE(IsValidViewingKey(viewingkey2)); - ASSERT_TRUE(boost::get(&viewingkey2) != nullptr); - auto extfvk2 = boost::get(viewingkey2); + ASSERT_TRUE(std::get_if(&viewingkey2) != nullptr); + auto extfvk2 = std::get(viewingkey2); EXPECT_EQ(extfvk, extfvk2); } { @@ -52,8 +54,8 @@ TEST(Keys, EncodeAndDecodeSapling) auto paymentaddr2 = DecodePaymentAddress(addr_string); EXPECT_TRUE(IsValidPaymentAddress(paymentaddr2)); - ASSERT_TRUE(boost::get(&paymentaddr2) != nullptr); - auto addr2 = boost::get(paymentaddr2); + ASSERT_TRUE(std::get_if(&paymentaddr2) != nullptr); + auto addr2 = std::get(paymentaddr2); EXPECT_EQ(addr, addr2); } } diff --git a/src/gtest/test_keystore.cpp b/src/gtest/test_keystore.cpp index fd1e6c303..e1a7a2d35 100644 --- a/src/gtest/test_keystore.cpp +++ b/src/gtest/test_keystore.cpp @@ -14,7 +14,7 @@ #define MAKE_STRING(x) std::string((x), (x)+sizeof(x)) -TEST(keystore_tests, StoreAndRetrieveHDSeed) { +TEST(KeystoreTests, StoreAndRetrieveHDSeed) { CBasicKeyStore keyStore; HDSeed seedOut; @@ -41,7 +41,7 @@ TEST(keystore_tests, StoreAndRetrieveHDSeed) { EXPECT_EQ(seed, seedOut); } -TEST(keystore_tests, sapling_keys) { +TEST(KeystoreTests, SaplingKeys) { // ["sk, ask, nsk, ovk, ak, nk, ivk, default_d, default_pk_d, note_v, note_r, note_cm, note_pos, note_nf"], UniValue sapling_keys = read_json(MAKE_STRING(json_tests::sapling_key_components)); @@ -95,7 +95,7 @@ TEST(keystore_tests, sapling_keys) { } } -TEST(keystore_tests, store_and_retrieve_spending_key) { +TEST(KeystoreTests, StoreAndRetrieveSpendingKey) { CBasicKeyStore keyStore; libzcash::SproutSpendingKey skOut; @@ -120,7 +120,7 @@ TEST(keystore_tests, store_and_retrieve_spending_key) { EXPECT_EQ(1, addrs.count(addr)); } -TEST(keystore_tests, store_and_retrieve_note_decryptor) { +TEST(KeystoreTests, StoreAndRetrieveNoteDecryptor) { CBasicKeyStore keyStore; ZCNoteDecryption decOut; @@ -134,7 +134,7 @@ TEST(keystore_tests, store_and_retrieve_note_decryptor) { EXPECT_EQ(ZCNoteDecryption(sk.receiving_key()), decOut); } -TEST(keystore_tests, StoreAndRetrieveViewingKey) { +TEST(KeystoreTests, StoreAndRetrieveViewingKey) { CBasicKeyStore keyStore; libzcash::SproutViewingKey vkOut; libzcash::SproutSpendingKey skOut; @@ -192,7 +192,7 @@ TEST(keystore_tests, StoreAndRetrieveViewingKey) { } // Sapling -TEST(keystore_tests, StoreAndRetrieveSaplingSpendingKey) { +TEST(KeystoreTests, StoreAndRetrieveSaplingSpendingKey) { CBasicKeyStore keyStore; libzcash::SaplingExtendedSpendingKey skOut; libzcash::SaplingExtendedFullViewingKey extfvkOut; @@ -282,7 +282,7 @@ class TestCCryptoKeyStore : public CCryptoKeyStore bool Unlock(const CKeyingMaterial& vMasterKeyIn) { return CCryptoKeyStore::Unlock(vMasterKeyIn); } }; -TEST(keystore_tests, StoreAndRetrieveHDSeedInEncryptedStore) { +TEST(KeystoreTests, StoreAndRetrieveHDSeedInEncryptedStore) { TestCCryptoKeyStore keyStore; CKeyingMaterial vMasterKey(32, 0); GetRandBytes(vMasterKey.data(), 32); @@ -342,7 +342,7 @@ TEST(keystore_tests, StoreAndRetrieveHDSeedInEncryptedStore) { EXPECT_EQ(seed3, seedOut); } -TEST(keystore_tests, store_and_retrieve_spending_key_in_encrypted_store) { +TEST(KeystoreTests, StoreAndRetrieveSpendingKeyInEncryptedStore) { TestCCryptoKeyStore keyStore; uint256 r {GetRandHash()}; CKeyingMaterial vMasterKey (r.begin(), r.end()); diff --git a/src/gtest/test_libzcash_utils.cpp b/src/gtest/test_libzcash_utils.cpp index ff84608bc..396053b18 100644 --- a/src/gtest/test_libzcash_utils.cpp +++ b/src/gtest/test_libzcash_utils.cpp @@ -1,7 +1,7 @@ #include #include "zcash/util.h" -TEST(libzcash_utils, convertBytesVectorToVector) +TEST(LibzcashUtils, ConvertBytesVectorToVector) { std::vector bytes = {0x00, 0x01, 0x03, 0x12, 0xFF}; std::vector expected_bits = { @@ -19,7 +19,7 @@ TEST(libzcash_utils, convertBytesVectorToVector) ASSERT_TRUE(convertBytesVectorToVector(bytes) == expected_bits); } -TEST(libzcash_utils, convertVectorToInt) +TEST(LibzcashUtils, convertVectorToInt) { ASSERT_TRUE(convertVectorToInt({0}) == 0); ASSERT_TRUE(convertVectorToInt({1}) == 1); diff --git a/src/gtest/test_mempool.cpp b/src/gtest/test_mempool.cpp index 834e29f64..372594a55 100644 --- a/src/gtest/test_mempool.cpp +++ b/src/gtest/test_mempool.cpp @@ -102,70 +102,6 @@ TEST(Mempool, PriorityStatsDoNotCrash) { EXPECT_EQ(dPriority, MAX_PRIORITY); } -TEST(Mempool, TxInputLimit) { - SelectParams(CBaseChainParams::REGTEST); - - CTxMemPool pool(::minRelayTxFee); - bool missingInputs; - - // Create an obviously-invalid transaction - // We intentionally set tx.nVersion = 0 to reliably trigger an error, as - // it's the first check that occurs after the -mempooltxinputlimit check, - // and it means that we don't have to mock out a lot of global state. - CMutableTransaction mtx; - mtx.nVersion = 0; - mtx.vin.resize(10); - - // Check it fails as expected - CValidationState state1; - CTransaction tx1(mtx); - EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); - EXPECT_EQ(state1.GetRejectReason(), "bad-txns-version-too-low"); - - // Set a limit - mapArgs["-mempooltxinputlimit"] = "10"; - - // Check it still fails as expected - CValidationState state2; - EXPECT_FALSE(AcceptToMemoryPool(pool, state2, tx1, false, &missingInputs)); - EXPECT_EQ(state2.GetRejectReason(), "bad-txns-version-too-low"); - - // Resize the transaction - mtx.vin.resize(11); - - // Check it now fails due to exceeding the limit - CValidationState state3; - CTransaction tx3(mtx); - EXPECT_FALSE(AcceptToMemoryPool(pool, state3, tx3, false, &missingInputs)); - // The -mempooltxinputlimit check doesn't set a reason - EXPECT_EQ(state3.GetRejectReason(), ""); - - // Activate Overwinter - UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); - - // Check it no longer fails due to exceeding the limit - CValidationState state4; - EXPECT_FALSE(AcceptToMemoryPool(pool, state4, tx3, false, &missingInputs)); - EXPECT_EQ(state4.GetRejectReason(), "bad-txns-version-too-low"); - - // Deactivate Overwinter - UpdateNetworkUpgradeParameters(Consensus::UPGRADE_OVERWINTER, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); - - // Check it now fails due to exceeding the limit - CValidationState state5; - EXPECT_FALSE(AcceptToMemoryPool(pool, state5, tx3, false, &missingInputs)); - // The -mempooltxinputlimit check doesn't set a reason - EXPECT_EQ(state5.GetRejectReason(), ""); - - // Clear the limit - mapArgs.erase("-mempooltxinputlimit"); - - // Check it no longer fails due to exceeding the limit - CValidationState state6; - EXPECT_FALSE(AcceptToMemoryPool(pool, state6, tx3, false, &missingInputs)); - EXPECT_EQ(state6.GetRejectReason(), "bad-txns-version-too-low"); -} - // Valid overwinter v3 format tx gets rejected because overwinter hasn't activated yet. TEST(Mempool, OverwinterNotActiveYet) { SelectParams(CBaseChainParams::REGTEST); @@ -182,6 +118,7 @@ TEST(Mempool, OverwinterNotActiveYet) { CValidationState state1; CTransaction tx1(mtx); + LOCK(cs_main); EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); EXPECT_EQ(state1.GetRejectReason(), "tx-overwinter-not-active"); @@ -206,6 +143,7 @@ TEST(Mempool, SproutV3TxFailsAsExpected) { CValidationState state1; CTransaction tx1(mtx); + LOCK(cs_main); EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); EXPECT_EQ(state1.GetRejectReason(), "version"); } @@ -227,6 +165,7 @@ TEST(Mempool, SproutV3TxWhenOverwinterActive) { CValidationState state1; CTransaction tx1(mtx); + LOCK(cs_main); EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); EXPECT_EQ(state1.GetRejectReason(), "tx-overwinter-flag-not-set"); @@ -248,7 +187,7 @@ TEST(Mempool, SproutNegativeVersionTxWhenOverwinterActive) { mtx.vJoinSplit.resize(0); // no joinsplits mtx.fOverwintered = false; - // A Sprout transaction with version -3 is created using Sprout code (as found in zcashd <= 1.0.14). + // A Sprout transaction with version -3 is created using Sprout code (as found in bitcoinzd <= 1.0.14). // First four bytes of transaction, parsed as an uint32_t, has the value: 0xfffffffd // This test simulates an Overwinter node receiving this transaction, but incorrectly deserializing the // transaction due to a (pretend) bug of not detecting the most significant bit, which leads @@ -262,11 +201,12 @@ TEST(Mempool, SproutNegativeVersionTxWhenOverwinterActive) { EXPECT_EQ(tx1.nVersion, -3); CValidationState state1; + LOCK(cs_main); EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); EXPECT_EQ(state1.GetRejectReason(), "bad-txns-version-too-low"); } - // A Sprout transaction with version -3 created using Overwinter code (as found in zcashd >= 1.0.15). + // A Sprout transaction with version -3 created using Overwinter code (as found in bitcoinzd >= 1.0.15). // First four bytes of transaction, parsed as an uint32_t, has the value: 0x80000003 // This test simulates the same pretend bug described above. // The resulting Sprout tx with nVersion -2147483645 should be rejected by the Overwinter node's mempool. @@ -278,6 +218,7 @@ TEST(Mempool, SproutNegativeVersionTxWhenOverwinterActive) { EXPECT_EQ(tx1.nVersion, -2147483645); CValidationState state1; + LOCK(cs_main); EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); EXPECT_EQ(state1.GetRejectReason(), "bad-txns-version-too-low"); } @@ -310,6 +251,7 @@ TEST(Mempool, ExpiringSoonTxRejection) { CValidationState state1; CTransaction tx1(mtx); + LOCK(cs_main); EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); EXPECT_EQ(state1.GetRejectReason(), "tx-expiring-soon"); } diff --git a/src/gtest/test_mempoollimit.cpp b/src/gtest/test_mempoollimit.cpp new file mode 100644 index 000000000..718b24962 --- /dev/null +++ b/src/gtest/test_mempoollimit.cpp @@ -0,0 +1,162 @@ +// Copyright (c) 2019 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://www.opensource.org/licenses/mit-license.php . + +#include +#include + +#include "arith_uint256.h" +#include "mempool_limit.h" +#include "utiltime.h" +#include "utiltest.h" +#include "transaction_builder.h" + + +const uint256 TX_ID1 = ArithToUint256(1); +const uint256 TX_ID2 = ArithToUint256(2); +const uint256 TX_ID3 = ArithToUint256(3); + +TEST(MempoolLimitTests, RecentlyEvictedListAddWrapsAfterMaxSize) +{ + RecentlyEvictedList recentlyEvicted(2, 100); + SetMockTime(1); + recentlyEvicted.add(TX_ID1); + recentlyEvicted.add(TX_ID2); + recentlyEvicted.add(TX_ID3); + // tx 1 should be overwritten by tx 3 due to maxSize 2 + EXPECT_FALSE(recentlyEvicted.contains(TX_ID1)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID2)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); +} + +TEST(MempoolLimitTests, RecentlyEvictedListDoesNotContainAfterExpiry) +{ + SetMockTime(1); + // maxSize=3, timeToKeep=1 + RecentlyEvictedList recentlyEvicted(3, 1); + recentlyEvicted.add(TX_ID1); + SetMockTime(2); + recentlyEvicted.add(TX_ID2); + recentlyEvicted.add(TX_ID3); + // After 1 second the txId will still be there + EXPECT_TRUE(recentlyEvicted.contains(TX_ID1)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID2)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); + SetMockTime(3); + // After 2 seconds it is gone + EXPECT_FALSE(recentlyEvicted.contains(TX_ID1)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID2)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); + SetMockTime(4); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID1)); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID2)); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID3)); +} + +TEST(MempoolLimitTests, RecentlyEvictedDropOneAtATime) +{ + SetMockTime(1); + RecentlyEvictedList recentlyEvicted(3, 2); + recentlyEvicted.add(TX_ID1); + SetMockTime(2); + recentlyEvicted.add(TX_ID2); + SetMockTime(3); + recentlyEvicted.add(TX_ID3); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID1)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID2)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); + SetMockTime(4); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID1)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID2)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); + SetMockTime(5); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID1)); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID2)); + EXPECT_TRUE(recentlyEvicted.contains(TX_ID3)); + SetMockTime(6); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID1)); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID2)); + EXPECT_FALSE(recentlyEvicted.contains(TX_ID3)); +} + +TEST(MempoolLimitTests, WeightedTxTreeCheckSizeAfterDropping) +{ + std::set testedDropping; + // Run the test until we have tested dropping each of the elements + int trialNum = 0; + while (testedDropping.size() < 3) { + WeightedTxTree tree(MIN_TX_COST * 2); + EXPECT_EQ(0, tree.getTotalWeight().cost); + EXPECT_EQ(0, tree.getTotalWeight().evictionWeight); + tree.add(WeightedTxInfo(TX_ID1, TxWeight(MIN_TX_COST, MIN_TX_COST))); + EXPECT_EQ(4000, tree.getTotalWeight().cost); + EXPECT_EQ(4000, tree.getTotalWeight().evictionWeight); + tree.add(WeightedTxInfo(TX_ID2, TxWeight(MIN_TX_COST, MIN_TX_COST))); + EXPECT_EQ(8000, tree.getTotalWeight().cost); + EXPECT_EQ(8000, tree.getTotalWeight().evictionWeight); + EXPECT_FALSE(tree.maybeDropRandom().has_value()); + tree.add(WeightedTxInfo(TX_ID3, TxWeight(MIN_TX_COST, MIN_TX_COST + LOW_FEE_PENALTY))); + EXPECT_EQ(12000, tree.getTotalWeight().cost); + EXPECT_EQ(12000 + LOW_FEE_PENALTY, tree.getTotalWeight().evictionWeight); + std::optional drop = tree.maybeDropRandom(); + ASSERT_TRUE(drop.has_value()); + uint256 txid = drop.value(); + testedDropping.insert(txid); + // Do not continue to test if a particular trial fails + ASSERT_EQ(8000, tree.getTotalWeight().cost); + ASSERT_EQ(txid == TX_ID3 ? 8000 : 8000 + LOW_FEE_PENALTY, tree.getTotalWeight().evictionWeight); + } +} + +TEST(MempoolLimitTests, WeightedTxInfoFromTx) +{ + // The transaction creation is based on the test: + // test_transaction_builder.cpp/TEST(TransactionBuilder, SetFee) + auto consensusParams = RegtestActivateSapling(); + + auto sk = libzcash::SaplingSpendingKey::random(); + auto testNote = GetTestSaplingNote(sk.default_address(), 50000); + + // Default fee + { + auto builder = TransactionBuilder(consensusParams, 1); + builder.AddSaplingSpend(sk.expanded_spending_key(), testNote.note, testNote.tree.root(), testNote.tree.witness()); + builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 25000, {}); + + WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow(), 10000); + EXPECT_EQ(MIN_TX_COST, info.txWeight.cost); + EXPECT_EQ(MIN_TX_COST, info.txWeight.evictionWeight); + } + + // Lower than standard fee + { + auto builder = TransactionBuilder(consensusParams, 1); + builder.AddSaplingSpend(sk.expanded_spending_key(), testNote.note, testNote.tree.root(), testNote.tree.witness()); + builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 25000, {}); + builder.SetFee(9999); + + WeightedTxInfo info = WeightedTxInfo::from(builder.Build().GetTxOrThrow(), 9999); + EXPECT_EQ(MIN_TX_COST, info.txWeight.cost); + EXPECT_EQ(MIN_TX_COST + LOW_FEE_PENALTY, info.txWeight.evictionWeight); + } + + // Larger Tx + { + auto builder = TransactionBuilder(consensusParams, 1); + builder.AddSaplingSpend(sk.expanded_spending_key(), testNote.note, testNote.tree.root(), testNote.tree.witness()); + builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 5000, {}); + builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 5000, {}); + builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 5000, {}); + builder.AddSaplingOutput(sk.full_viewing_key().ovk, sk.default_address(), 5000, {}); + + auto result = builder.Build(); + if (result.IsError()) { + std::cerr << result.GetError() << std::endl; + } + WeightedTxInfo info = WeightedTxInfo::from(result.GetTxOrThrow(), 10000); + EXPECT_EQ(5168, info.txWeight.cost); + EXPECT_EQ(5168, info.txWeight.evictionWeight); + } + + RegtestDeactivateSapling(); +} diff --git a/src/gtest/test_merkletree.cpp b/src/gtest/test_merkletree.cpp index 23c39c044..17f4b2e03 100644 --- a/src/gtest/test_merkletree.cpp +++ b/src/gtest/test_merkletree.cpp @@ -1,14 +1,12 @@ #include #include "test/data/merkle_roots.json.h" -#include "test/data/merkle_roots_empty.json.h" #include "test/data/merkle_serialization.json.h" #include "test/data/merkle_witness_serialization.json.h" #include "test/data/merkle_path.json.h" #include "test/data/merkle_commitments.json.h" #include "test/data/merkle_roots_sapling.json.h" -#include "test/data/merkle_roots_empty_sapling.json.h" #include "test/data/merkle_serialization_sapling.json.h" #include "test/data/merkle_witness_serialization_sapling.json.h" #include "test/data/merkle_path_sapling.json.h" @@ -26,17 +24,9 @@ #include "zcash/IncrementalMerkleTree.hpp" #include "zcash/util.h" -#include -#include -#include -#include - -#include - #include "json_test_vectors.h" using namespace std; -using namespace libsnark; template<> void expect_deser_same(const SproutTestingWitness& expected) @@ -58,8 +48,7 @@ void test_tree( UniValue root_tests, UniValue ser_tests, UniValue witness_ser_tests, - UniValue path_tests, - bool libsnark_test + UniValue path_tests ) { size_t witness_ser_i = 0; @@ -104,7 +93,7 @@ void test_tree( expect_ser_test_vector(ser_tests[i], tree, tree); bool first = true; // The first witness can never form a path - BOOST_FOREACH(Witness& wit, witnesses) + for (Witness& wit : witnesses) { // Append the same commitment to all the witnesses wit.append(test_commitment); @@ -115,55 +104,6 @@ void test_tree( } else { auto path = wit.path(); expect_test_vector(path_tests[path_i++], path); - - if (libsnark_test) { - typedef Fr FieldT; - - protoboard pb; - pb_variable_array positions; - digest_variable commitment(pb, 256, "commitment"); - digest_variable root(pb, 256, "root"); - positions.allocate(pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, "pos"); - merkle_authentication_path_variable> authvars(pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, "auth"); - merkle_tree_check_read_gadget> auth( - pb, INCREMENTAL_MERKLE_TREE_DEPTH_TESTING, positions, commitment, root, authvars, ONE, "path" - ); - commitment.generate_r1cs_constraints(); - root.generate_r1cs_constraints(); - authvars.generate_r1cs_constraints(); - auth.generate_r1cs_constraints(); - - std::vector commitment_bv; - { - uint256 witnessed_commitment = wit.element(); - std::vector commitment_v(witnessed_commitment.begin(), witnessed_commitment.end()); - commitment_bv = convertBytesVectorToVector(commitment_v); - } - - size_t path_index = convertVectorToInt(path.index); - - commitment.bits.fill_with_bits(pb, bit_vector(commitment_bv)); - positions.fill_with_bits_of_uint64(pb, path_index); - - authvars.generate_r1cs_witness(path_index, path.authentication_path); - auth.generate_r1cs_witness(); - - std::vector root_bv; - { - uint256 witroot = wit.root(); - std::vector root_v(witroot.begin(), witroot.end()); - root_bv = convertBytesVectorToVector(root_v); - } - - root.bits.fill_with_bits(pb, bit_vector(root_bv)); - - ASSERT_TRUE(pb.is_satisfied()); - - root_bv[0] = !root_bv[0]; - root.bits.fill_with_bits(pb, bit_vector(root_bv)); - - ASSERT_TRUE(!pb.is_satisfied()); - } } // Check witness serialization @@ -179,7 +119,7 @@ void test_tree( // Tree should be full now ASSERT_THROW(tree.append(uint256()), std::runtime_error); - BOOST_FOREACH(Witness& wit, witnesses) + for (Witness& wit : witnesses) { ASSERT_THROW(wit.append(uint256()), std::runtime_error); } @@ -200,8 +140,7 @@ TEST(merkletree, vectors) { root_tests, ser_tests, witness_ser_tests, - path_tests, - true + path_tests ); } @@ -217,18 +156,19 @@ TEST(merkletree, SaplingVectors) { root_tests, ser_tests, witness_ser_tests, - path_tests, - false + path_tests ); } TEST(merkletree, emptyroots) { - UniValue empty_roots = read_json(MAKE_STRING(json_tests::merkle_roots_empty)); - libzcash::EmptyMerkleRoots<64, libzcash::SHA256Compress> emptyroots; + std::array computed; - for (size_t depth = 0; depth <= 64; depth++) { - expect_test_vector(empty_roots[depth], emptyroots.empty_root(depth)); + computed.at(0) = libzcash::SHA256Compress::uncommitted(); + ASSERT_TRUE(emptyroots.empty_root(0) == computed.at(0)); + for (size_t d = 1; d <= 64; d++) { + computed.at(d) = libzcash::SHA256Compress::combine(computed.at(d-1), computed.at(d-1), d-1); + ASSERT_TRUE(emptyroots.empty_root(d) == computed.at(d)); } // Double check that we're testing (at least) all the empty roots we'll use. @@ -236,12 +176,14 @@ TEST(merkletree, emptyroots) { } TEST(merkletree, EmptyrootsSapling) { - UniValue empty_roots = read_json(MAKE_STRING(json_tests::merkle_roots_empty_sapling)); - libzcash::EmptyMerkleRoots<62, libzcash::PedersenHash> emptyroots; + std::array computed; - for (size_t depth = 0; depth <= 62; depth++) { - expect_test_vector(empty_roots[depth], emptyroots.empty_root(depth)); + computed.at(0) = libzcash::PedersenHash::uncommitted(); + ASSERT_TRUE(emptyroots.empty_root(0) == computed.at(0)); + for (size_t d = 1; d <= 62; d++) { + computed.at(d) = libzcash::PedersenHash::combine(computed.at(d-1), computed.at(d-1), d-1); + ASSERT_TRUE(emptyroots.empty_root(d) == computed.at(d)); } // Double check that we're testing (at least) all the empty roots we'll use. @@ -249,7 +191,7 @@ TEST(merkletree, EmptyrootsSapling) { } TEST(merkletree, emptyroot) { - // This literal is the depth-20 empty tree root with the bytes reversed to + // This literal is the depth-29 empty tree root with the bytes reversed to // account for the fact that uint256S() loads a big-endian representation of // an integer which converted to little-endian internally. uint256 expected = uint256S("59d2cde5e65c1414c32ba54f0fe4bdb3d67618125286e6a191317917c812c6d7"); @@ -258,7 +200,7 @@ TEST(merkletree, emptyroot) { } TEST(merkletree, EmptyrootSapling) { - // This literal is the depth-20 empty tree root with the bytes reversed to + // This literal is the depth-32 empty tree root with the bytes reversed to // account for the fact that uint256S() loads a big-endian representation of // an integer which converted to little-endian internally. uint256 expected = uint256S("3e49b5f954aa9d3545bc6c37744661eea48d7c34e3000d82b7f0010c30f4c2fb"); diff --git a/src/gtest/test_metrics.cpp b/src/gtest/test_metrics.cpp index 6b766e4aa..3fbadb63d 100644 --- a/src/gtest/test_metrics.cpp +++ b/src/gtest/test_metrics.cpp @@ -95,15 +95,42 @@ TEST(Metrics, GetLocalSolPS) { } TEST(Metrics, EstimateNetHeight) { - auto params = RegtestActivateBlossom(false, 200); - int64_t blockTimes[400]; - for (int i = 0; i < 400; i++) { - blockTimes[i] = i ? blockTimes[i - 1] + params.PoWTargetSpacing(i) : 0; - } - SetMockTime(blockTimes[399]); - for (int i = 0; i < 400; i++) { - // Check that we are within 1 of the correct height - EXPECT_LT(std::abs(399 - EstimateNetHeight(params, i, blockTimes[i])), 2); - } - RegtestDeactivateBlossom(); + auto params = RegtestActivateBlossom(false, 200); + int64_t blockTimes[400]; + for (int i = 0; i < 400; i++) { + blockTimes[i] = i ? blockTimes[i - 1] + params.PoWTargetSpacing(i) : 0; + } + SetMockTime(blockTimes[399]); + for (int i = 0; i < 400; i++) { + // Check that we are within 1 of the correct height + EXPECT_LT(std::abs(399 - EstimateNetHeight(params, i, blockTimes[i])), 2); + } + RegtestDeactivateBlossom(); +} + +TEST(Metrics, NextUpgrade) { + SelectParams(CBaseChainParams::REGTEST); + const Consensus::Params& params = Params().GetConsensus(); + + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, 100); + + EXPECT_EQ(SecondsLeftToNextEpoch(params, 1).value(), 14850); + EXPECT_EQ(DisplayDuration(SecondsLeftToNextEpoch(params, 1).value(), DurationFormat::REDUCED), "4 hours"); + EXPECT_EQ(DisplayDuration(SecondsLeftToNextEpoch(params, 1).value(), DurationFormat::FULL), "4 hours, 7 minutes, 30 seconds"); + + EXPECT_EQ(SecondsLeftToNextEpoch(params, 90).value(), 1500); + EXPECT_EQ(DisplayDuration(SecondsLeftToNextEpoch(params, 90).value(), DurationFormat::REDUCED), "25 minutes"); + EXPECT_EQ(DisplayDuration(SecondsLeftToNextEpoch(params, 90).value(), DurationFormat::FULL), "25 minutes, 0 seconds"); + + EXPECT_EQ(SecondsLeftToNextEpoch(params, 99).value(), 150); + EXPECT_EQ(DisplayDuration(SecondsLeftToNextEpoch(params, 99).value(), DurationFormat::REDUCED), "2 minutes"); + EXPECT_EQ(DisplayDuration(SecondsLeftToNextEpoch(params, 99).value(), DurationFormat::FULL), "2 minutes, 30 seconds"); + + auto paramsBlossom = RegtestActivateBlossom(true); + EXPECT_EQ(SecondsLeftToNextEpoch(paramsBlossom, 1).value(), 7425); + EXPECT_EQ(DisplayDuration(SecondsLeftToNextEpoch(paramsBlossom, 1).value(), DurationFormat::REDUCED), "2 hours"); + EXPECT_EQ(DisplayDuration(SecondsLeftToNextEpoch(paramsBlossom, 1).value(), DurationFormat::FULL), "2 hours, 3 minutes, 45 seconds"); + RegtestDeactivateBlossom(); + + UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); } diff --git a/src/gtest/test_noteencryption.cpp b/src/gtest/test_noteencryption.cpp index 0ed6999f8..eddb659bf 100644 --- a/src/gtest/test_noteencryption.cpp +++ b/src/gtest/test_noteencryption.cpp @@ -2,6 +2,7 @@ #include "sodium.h" #include +#include #include #include "zcash/Note.hpp" @@ -20,7 +21,7 @@ class TestNoteDecryption : public ZCNoteDecryption { } }; -TEST(noteencryption, NotePlaintext) +TEST(Noteencryption, NotePlaintext) { using namespace libzcash; auto xsk = SaplingSpendingKey(uint256()).expanded_spending_key(); @@ -35,11 +36,11 @@ TEST(noteencryption, NotePlaintext) } SaplingNote note(addr, 39393); - auto cmu_opt = note.cm(); + auto cmu_opt = note.cmu(); if (!cmu_opt) { FAIL(); } - uint256 cmu = cmu_opt.get(); + uint256 cmu = cmu_opt.value(); SaplingNotePlaintext pt(note, memo); auto res = pt.encrypt(addr.pk_d); @@ -47,7 +48,7 @@ TEST(noteencryption, NotePlaintext) FAIL(); } - auto enc = res.get(); + auto enc = res.value(); auto ct = enc.first; auto encryptor = enc.second; @@ -73,7 +74,7 @@ TEST(noteencryption, NotePlaintext) FAIL(); } - auto bar = foo.get(); + auto bar = foo.value(); ASSERT_TRUE(bar.value() == pt.value()); ASSERT_TRUE(bar.memo() == pt.memo()); @@ -86,13 +87,13 @@ TEST(noteencryption, NotePlaintext) FAIL(); } - auto new_note = foobar.get(); + auto new_note = foobar.value(); ASSERT_TRUE(note.value() == new_note.value()); ASSERT_TRUE(note.d == new_note.d); ASSERT_TRUE(note.pk_d == new_note.pk_d); ASSERT_TRUE(note.r == new_note.r); - ASSERT_TRUE(note.cm() == new_note.cm()); + ASSERT_TRUE(note.cmu() == new_note.cmu()); SaplingOutgoingPlaintext out_pt; out_pt.pk_d = note.pk_d; @@ -121,7 +122,7 @@ TEST(noteencryption, NotePlaintext) FAIL(); } - auto decrypted_out_ct_unwrapped = decrypted_out_ct.get(); + auto decrypted_out_ct_unwrapped = decrypted_out_ct.value(); ASSERT_TRUE(decrypted_out_ct_unwrapped.pk_d == out_pt.pk_d); ASSERT_TRUE(decrypted_out_ct_unwrapped.esk == out_pt.esk); @@ -150,7 +151,7 @@ TEST(noteencryption, NotePlaintext) FAIL(); } - bar = foo.get(); + bar = foo.value(); ASSERT_TRUE(bar.value() == pt.value()); ASSERT_TRUE(bar.memo() == pt.memo()); @@ -158,7 +159,7 @@ TEST(noteencryption, NotePlaintext) ASSERT_TRUE(bar.rcm == pt.rcm); } -TEST(noteencryption, SaplingApi) +TEST(Noteencryption, SaplingApi) { using namespace libzcash; @@ -183,7 +184,7 @@ TEST(noteencryption, SaplingApi) } // Invalid diversifier - ASSERT_EQ(boost::none, SaplingNoteEncryption::FromDiversifier({1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); + ASSERT_EQ(std::nullopt, SaplingNoteEncryption::FromDiversifier({1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); // Encrypt to pk_1 auto enc = *SaplingNoteEncryption::FromDiversifier(pk_1.d); @@ -341,7 +342,7 @@ TEST(noteencryption, SaplingApi) )); } -TEST(noteencryption, api) +TEST(Noteencryption, api) { uint256 sk_enc = ZCNoteEncryption::generate_privkey(uint252(uint256S("21035d60bc1983e37950ce4803418a8fb33ea68d5b937ca382ecbae7564d6a07"))); uint256 pk_enc = ZCNoteEncryption::generate_pubkey(sk_enc); @@ -446,7 +447,7 @@ uint256 test_prf( return ret; } -TEST(noteencryption, prf_addr) +TEST(Noteencryption, PrfAddr) { for (size_t i = 0; i < 100; i++) { uint252 a_sk = libzcash::random_uint252(); @@ -466,7 +467,7 @@ TEST(noteencryption, prf_addr) } } -TEST(noteencryption, prf_nf) +TEST(Noteencryption, PrfNf) { for (size_t i = 0; i < 100; i++) { uint252 a_sk = libzcash::random_uint252(); @@ -477,7 +478,7 @@ TEST(noteencryption, prf_nf) } } -TEST(noteencryption, prf_pk) +TEST(Noteencryption, PrfPk) { for (size_t i = 0; i < 100; i++) { uint252 a_sk = libzcash::random_uint252(); @@ -500,7 +501,7 @@ TEST(noteencryption, prf_pk) ASSERT_THROW(PRF_pk(dummy_a, 2, dummy_b), std::domain_error); } -TEST(noteencryption, prf_rho) +TEST(Noteencryption, PrfRho) { for (size_t i = 0; i < 100; i++) { uint252 phi = libzcash::random_uint252(); @@ -523,7 +524,7 @@ TEST(noteencryption, prf_rho) ASSERT_THROW(PRF_rho(dummy_a, 2, dummy_b), std::domain_error); } -TEST(noteencryption, uint252) +TEST(Noteencryption, uint252) { ASSERT_THROW(uint252(uint256S("f6da8716682d600f74fc16bd0187faad6a26b4aa4c24d5c055b216d94516847e")), std::domain_error); } diff --git a/src/gtest/test_pow.cpp b/src/gtest/test_pow.cpp index ad1dbca4b..30ddc33f4 100644 --- a/src/gtest/test_pow.cpp +++ b/src/gtest/test_pow.cpp @@ -63,15 +63,14 @@ void TestDifficultyAveragingImpl(const Consensus::Params& params) blocks[lastBlk].nHeight + 1), GetNextWorkRequired(&blocks[lastBlk], nullptr, params)); - // FIXME: consensus changed -// // Result should be the same as if the average difficulty was used -// arith_uint256 average = UintToArith256(uint256S("0000796968696969696969696969696969696969696969696969696969696969")); -// EXPECT_EQ(CalculateNextWorkRequired(average, -// blocks[lastBlk].GetMedianTimePast(), -// blocks[firstBlk].GetMedianTimePast(), -// params, -// blocks[lastBlk].nHeight + 1), -// GetNextWorkRequired(&blocks[lastBlk], nullptr, params)); + // Result should be the same as if the average difficulty was used + arith_uint256 average = UintToArith256(uint256S("0000776275276276276276276276276276276276276276276276276276276276")); + EXPECT_EQ(CalculateNextWorkRequired(average, + blocks[lastBlk].GetMedianTimePast(), + blocks[firstBlk].GetMedianTimePast(), + params, + blocks[lastBlk].nHeight + 1), + GetNextWorkRequired(&blocks[lastBlk], nullptr, params)); } TEST(PoW, DifficultyAveraging) { @@ -80,9 +79,10 @@ TEST(PoW, DifficultyAveraging) { } TEST(PoW, DifficultyAveragingBlossom) { - TestDifficultyAveragingImpl(RegtestActivateBlossom(true)); + TestDifficultyAveragingImpl(RegtestActivateBlossom(false)); RegtestDeactivateBlossom(); } + TEST(PoW, MinDifficultyRules) { SelectParams(CBaseChainParams::TESTNET); const Consensus::Params& params = Params().GetConsensus(); @@ -93,7 +93,7 @@ TEST(PoW, MinDifficultyRules) { std::vector blocks(lastBlk+1); for (int i = 0; i <= lastBlk; i++) { blocks[i].pprev = i ? &blocks[i - 1] : nullptr; - blocks[i].nHeight = params.nPowAllowMinDifficultyBlocksAfterHeight.get() + i; + blocks[i].nHeight = params.nPowAllowMinDifficultyBlocksAfterHeight.value() + i; blocks[i].nTime = i ? blocks[i - 1].nTime + params.PoWTargetSpacing(i) : 1269211443; blocks[i].nBits = 0x1e7fffff; /* target 0x007fffff000... */ blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0); diff --git a/src/gtest/test_proofs.cpp b/src/gtest/test_proofs.cpp deleted file mode 100644 index 5b5c19395..000000000 --- a/src/gtest/test_proofs.cpp +++ /dev/null @@ -1,702 +0,0 @@ -#include -#include "zcash/Proof.hpp" - -#include - -#include -#include -#include - -using namespace libzcash; - -typedef libsnark::default_r1cs_ppzksnark_pp curve_pp; -typedef libsnark::default_r1cs_ppzksnark_pp::G1_type curve_G1; -typedef libsnark::default_r1cs_ppzksnark_pp::G2_type curve_G2; -typedef libsnark::default_r1cs_ppzksnark_pp::GT_type curve_GT; -typedef libsnark::default_r1cs_ppzksnark_pp::Fp_type curve_Fr; -typedef libsnark::default_r1cs_ppzksnark_pp::Fq_type curve_Fq; -typedef libsnark::default_r1cs_ppzksnark_pp::Fqe_type curve_Fq2; - -#include "streams.h" -#include "version.h" -#include "utilstrencodings.h" - -TEST(proofs, g1_pairing_at_infinity) -{ - for (size_t i = 0; i < 100; i++) { - auto r1 = curve_G1::random_element(); - auto r2 = curve_G2::random_element(); - ASSERT_TRUE( - curve_pp::reduced_pairing(curve_G1::zero(), r2) == - curve_GT::one() - ); - ASSERT_TRUE( - curve_pp::final_exponentiation( - curve_pp::double_miller_loop( - curve_pp::precompute_G1(curve_G1::zero()), - curve_pp::precompute_G2(r2), - curve_pp::precompute_G1(curve_G1::zero()), - curve_pp::precompute_G2(r2) - ) - ) == - curve_GT::one() - ); - ASSERT_TRUE( - curve_pp::final_exponentiation( - curve_pp::double_miller_loop( - curve_pp::precompute_G1(r1), - curve_pp::precompute_G2(r2), - curve_pp::precompute_G1(curve_G1::zero()), - curve_pp::precompute_G2(r2) - ) - ) == - curve_pp::reduced_pairing(r1, r2) - ); - ASSERT_TRUE( - curve_pp::final_exponentiation( - curve_pp::double_miller_loop( - curve_pp::precompute_G1(curve_G1::zero()), - curve_pp::precompute_G2(r2), - curve_pp::precompute_G1(r1), - curve_pp::precompute_G2(r2) - ) - ) == - curve_pp::reduced_pairing(r1, r2) - ); - } -} - -TEST(proofs, g2_subgroup_check) -{ - // all G2 elements are order r - ASSERT_TRUE(libsnark::alt_bn128_modulus_r * curve_G2::random_element() == curve_G2::zero()); - - // but that doesn't mean all elements that satisfy the curve equation are in G2... - curve_G2 p = curve_G2::one(); - - while (1) { - // This will construct an order r(2q-r) point with high probability - p.X = curve_Fq2::random_element(); - try { - p.Y = ((p.X.squared() * p.X) + libsnark::alt_bn128_twist_coeff_b).sqrt(); - break; - } catch(...) {} - } - - ASSERT_TRUE(p.is_well_formed()); // it's on the curve - ASSERT_TRUE(libsnark::alt_bn128_modulus_r * p != curve_G2::zero()); // but not the order r subgroup.. - - { - // libsnark unfortunately doesn't check, and the pairing will complete - auto e = curve_Fr("149"); - auto a = curve_pp::reduced_pairing(curve_G1::one(), p); - auto b = curve_pp::reduced_pairing(e * curve_G1::one(), p); - - // though it will not preserve bilinearity - ASSERT_TRUE((a^e) != b); - } - - { - // so, our decompression API should not allow you to decompress G2 elements of that form! - CompressedG2 badp(p); - try { - auto newp = badp.to_libsnark_g2(); - FAIL() << "Expected std::runtime_error"; - } catch (std::runtime_error const & err) { - EXPECT_EQ(err.what(), std::string("point is not in G2")); - } catch(...) { - FAIL() << "Expected std::runtime_error"; - } - } - - // educational purposes: showing that E'(Fp2) is of order r(2q-r), - // by multiplying our random point in E' by (2q-r) = (q + q - r) to - // get an element in G2 - { - auto p1 = libsnark::alt_bn128_modulus_q * p; - p1 = p1 + p1; - p1 = p1 - (libsnark::alt_bn128_modulus_r * p); - - ASSERT_TRUE(p1.is_well_formed()); - ASSERT_TRUE(libsnark::alt_bn128_modulus_r * p1 == curve_G2::zero()); - - CompressedG2 goodp(p1); - auto newp = goodp.to_libsnark_g2(); - - ASSERT_TRUE(newp == p1); - } -} - -TEST(proofs, sqrt_zero) -{ - ASSERT_TRUE(curve_Fq::zero() == curve_Fq::zero().sqrt()); - ASSERT_TRUE(curve_Fq2::zero() == curve_Fq2::zero().sqrt()); -} - -TEST(proofs, sqrt_fq) -{ - // Poor man's PRNG - curve_Fq acc = curve_Fq("348957923485290374852379485") ^ 1000; - - size_t quadratic_residues = 0; - size_t quadratic_nonresidues = 0; - - for (size_t i = 1; i < 1000; i++) { - try { - acc += curve_Fq("45634563456") ^ i; - - curve_Fq x = acc.sqrt(); - ASSERT_TRUE((x*x) == acc); - quadratic_residues += 1; - } catch (std::runtime_error &e) { - quadratic_nonresidues += 1; - } - } - - // Half of all nonzero elements in Fp are quadratic residues - ASSERT_TRUE(quadratic_residues == 511); - ASSERT_TRUE(quadratic_nonresidues == 488); - - for (size_t i = 0; i < 1000; i++) { - curve_Fq x = curve_Fq::random_element(); - curve_Fq x2 = x * x; - - ASSERT_TRUE((x2.sqrt() == x) || (x2.sqrt() == -x)); - } - - // Test vectors - ASSERT_TRUE( - curve_Fq("5204065062716160319596273903996315000119019512886596366359652578430118331601") - == - curve_Fq("348579348568").sqrt() - ); - ASSERT_THROW(curve_Fq("348579348569").sqrt(), std::runtime_error); -} - -TEST(proofs, sqrt_fq2) -{ - curve_Fq2 acc = curve_Fq2( - curve_Fq("3456293840592348059238409578239048769348760238476029347885092384059238459834") ^ 1000, - curve_Fq("2394578084760439457823945729347502374590283479582739485723945729384759823745") ^ 1000 - ); - - size_t quadratic_residues = 0; - size_t quadratic_nonresidues = 0; - - for (size_t i = 1; i < 1000; i++) { - try { - acc = acc + curve_Fq2( - curve_Fq("5204065062716160319596273903996315000119019512886596366359652578430118331601") ^ i, - curve_Fq("348957923485290374852379485348957923485290374852379485348957923485290374852") ^ i - ); - - curve_Fq2 x = acc.sqrt(); - ASSERT_TRUE((x*x) == acc); - quadratic_residues += 1; - } catch (std::runtime_error &e) { - quadratic_nonresidues += 1; - } - } - - // Half of all nonzero elements in Fp^k are quadratic residues as long - // as p != 2 - ASSERT_TRUE(quadratic_residues == 505); - ASSERT_TRUE(quadratic_nonresidues == 494); - - for (size_t i = 0; i < 1000; i++) { - curve_Fq2 x = curve_Fq2::random_element(); - curve_Fq2 x2 = x * x; - - ASSERT_TRUE((x2.sqrt() == x) || (x2.sqrt() == -x)); - } - - // Test vectors - ASSERT_THROW(curve_Fq2( - curve_Fq("2"), - curve_Fq("1") - ).sqrt(), std::runtime_error); - - ASSERT_THROW(curve_Fq2( - curve_Fq("3345897230485723946872934576923485762803457692345760237495682347502347589473"), - curve_Fq("1234912378405347958234756902345768290345762348957605678245967234857634857676") - ).sqrt(), std::runtime_error); - - curve_Fq2 x = curve_Fq2( - curve_Fq("12844195307879678418043983815760255909500142247603239203345049921980497041944"), - curve_Fq("7476417578426924565731404322659619974551724117137577781074613937423560117731") - ); - - curve_Fq2 nx = -x; - - curve_Fq2 x2 = curve_Fq2( - curve_Fq("3345897230485723946872934576923485762803457692345760237495682347502347589474"), - curve_Fq("1234912378405347958234756902345768290345762348957605678245967234857634857676") - ); - - ASSERT_TRUE(x == x2.sqrt()); - ASSERT_TRUE(nx == -x2.sqrt()); - ASSERT_TRUE(x*x == x2); - ASSERT_TRUE(nx*nx == x2); -} - -TEST(proofs, size_is_expected) -{ - PHGRProof p; - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << p; - - ASSERT_EQ(ss.size(), 296); -} - -TEST(proofs, fq_serializes_properly) -{ - for (size_t i = 0; i < 1000; i++) { - curve_Fq e = curve_Fq::random_element(); - - Fq e2(e); - - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << e2; - - Fq e3; - ss >> e3; - - curve_Fq e4 = e3.to_libsnark_fq(); - - ASSERT_TRUE(e == e4); - } -} - -TEST(proofs, fq2_serializes_properly) -{ - for (size_t i = 0; i < 1000; i++) { - curve_Fq2 e = curve_Fq2::random_element(); - - Fq2 e2(e); - - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << e2; - - Fq2 e3; - ss >> e3; - - curve_Fq2 e4 = e3.to_libsnark_fq2(); - - ASSERT_TRUE(e == e4); - } -} - -template -T deserialize_tv(std::string s) -{ - T e; - CDataStream ss(ParseHex(s), SER_NETWORK, PROTOCOL_VERSION); - ss >> e; - - return e; -} - -curve_Fq deserialize_fq(std::string s) -{ - return deserialize_tv(s).to_libsnark_fq(); -} - -curve_Fq2 deserialize_fq2(std::string s) -{ - return deserialize_tv(s).to_libsnark_fq2(); -} - -TEST(proofs, fq_valid) -{ - curve_Fq e = deserialize_fq("30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"); - - ASSERT_TRUE(e == curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582")); - ASSERT_TRUE(e != curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208581")); - - curve_Fq e2 = deserialize_fq("30644e72e131a029b75045b68181585d97816a916871ca8d3c208c16d87cfd46"); - - ASSERT_TRUE(e2 == curve_Fq("21888242871839275222221885816603420866962577604863418715751138068690288573766")); -} - -TEST(proofs, fq_invalid) -{ - // Should not be able to deserialize the modulus - ASSERT_THROW( - deserialize_fq("30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"), - std::logic_error - ); - - // Should not be able to deserialize the modulus plus one - ASSERT_THROW( - deserialize_fq("30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd48"), - std::logic_error - ); - - // Should not be able to deserialize a ridiculously out of bound int - ASSERT_THROW( - deserialize_fq("ff644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"), - std::logic_error - ); -} - -TEST(proofs, fq2_valid) -{ - // (q - 1) * q + q - curve_Fq2 e = deserialize_fq2("0925c4b8763cbf9c599a6f7c0348d21cb00b85511637560626edfa5c34c6b38d04689e957a1242c84a50189c6d96cadca602072d09eac1013b5458a2275d69b0"); - ASSERT_TRUE(e.c0 == curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582")); - ASSERT_TRUE(e.c1 == curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582")); - - curve_Fq2 e2 = deserialize_fq2("000000000000000000000000000000000000000000000000010245be1c91e3186bbbe1c430a93fcfc5aada4ab10c3492f70eea97a91c7b29554db55acffa34d2"); - ASSERT_TRUE(e2.c0 == curve_Fq("238769481237490823")); - ASSERT_TRUE(e2.c1 == curve_Fq("384579238459723485")); - - curve_Fq2 e3 = deserialize_fq2("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - ASSERT_TRUE(e3.c0 == curve_Fq("0")); - ASSERT_TRUE(e3.c1 == curve_Fq("0")); - - curve_Fq2 e4 = deserialize_fq2("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"); - ASSERT_TRUE(e4.c0 == curve_Fq("1")); - ASSERT_TRUE(e4.c1 == curve_Fq("0")); -} - -TEST(proofs, fq2_invalid) -{ - // (q - 1) * q + q is invalid - ASSERT_THROW( - deserialize_fq2("0925c4b8763cbf9c599a6f7c0348d21cb00b85511637560626edfa5c34c6b38d04689e957a1242c84a50189c6d96cadca602072d09eac1013b5458a2275d69b1"), - std::logic_error - ); - - // q * q + (q - 1) is invalid - ASSERT_THROW( - deserialize_fq2("0925c4b8763cbf9c599a6f7c0348d21cb00b85511637560626edfa5c34c6b38d34cced085b43e2f202a05e52ef18233a3d8371be725c8b8e7774e4b8ffda66f7"), - std::logic_error - ); - - // Ridiculously out of bounds - ASSERT_THROW( - deserialize_fq2("0fffc4b8763cbf9c599a6f7c0348d21cb00b85511637560626edfa5c34c6b38d04689e957a1242c84a50189c6d96cadca602072d09eac1013b5458a2275d69b0"), - std::logic_error - ); - ASSERT_THROW( - deserialize_fq2("ffffffff763cbf9c599a6f7c0348d21cb00b85511637560626edfa5c34c6b38d04689e957a1242c84a50189c6d96cadca602072d09eac1013b5458a2275d69b0"), - std::logic_error - ); -} - -TEST(proofs, g1_serializes_properly) -{ - // Cannot serialize zero - { - ASSERT_THROW({CompressedG1 g = CompressedG1(curve_G1::zero());}, std::domain_error); - } - - for (size_t i = 0; i < 1000; i++) { - curve_G1 e = curve_G1::random_element(); - - CompressedG1 e2(e); - - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << e2; - - CompressedG1 e3; - ss >> e3; - - ASSERT_TRUE(e2 == e3); - - curve_G1 e4 = e3.to_libsnark_g1(); - - ASSERT_TRUE(e == e4); - } -} - -TEST(proofs, g2_serializes_properly) -{ - // Cannot serialize zero - { - ASSERT_THROW({CompressedG2 g = CompressedG2(curve_G2::zero());}, std::domain_error); - } - - for (size_t i = 0; i < 1000; i++) { - curve_G2 e = curve_G2::random_element(); - - CompressedG2 e2(e); - - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << e2; - - CompressedG2 e3; - ss >> e3; - - ASSERT_TRUE(e2 == e3); - - curve_G2 e4 = e3.to_libsnark_g2(); - - ASSERT_TRUE(e == e4); - } -} - -TEST(proofs, zksnark_serializes_properly) -{ - auto example = libsnark::generate_r1cs_example_with_field_input(250, 4); - example.constraint_system.swap_AB_if_beneficial(); - auto kp = libsnark::r1cs_ppzksnark_generator(example.constraint_system); - auto vkprecomp = libsnark::r1cs_ppzksnark_verifier_process_vk(kp.vk); - - for (size_t i = 0; i < 20; i++) { - auto badproof = PHGRProof::random_invalid(); - auto proof = badproof.to_libsnark_proof>(); - - auto verifierEnabled = ProofVerifier::Strict(); - auto verifierDisabled = ProofVerifier::Disabled(); - // This verifier should catch the bad proof - ASSERT_FALSE(verifierEnabled.check( - kp.vk, - vkprecomp, - example.primary_input, - proof - )); - // This verifier won't! - ASSERT_TRUE(verifierDisabled.check( - kp.vk, - vkprecomp, - example.primary_input, - proof - )); - } - - for (size_t i = 0; i < 20; i++) { - auto proof = libsnark::r1cs_ppzksnark_prover( - kp.pk, - example.primary_input, - example.auxiliary_input, - example.constraint_system - ); - - { - auto verifierEnabled = ProofVerifier::Strict(); - auto verifierDisabled = ProofVerifier::Disabled(); - ASSERT_TRUE(verifierEnabled.check( - kp.vk, - vkprecomp, - example.primary_input, - proof - )); - ASSERT_TRUE(verifierDisabled.check( - kp.vk, - vkprecomp, - example.primary_input, - proof - )); - } - - ASSERT_TRUE(libsnark::r1cs_ppzksnark_verifier_strong_IC( - kp.vk, - example.primary_input, - proof - )); - - PHGRProof compressed_proof_0(proof); - - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << compressed_proof_0; - - PHGRProof compressed_proof_1; - ss >> compressed_proof_1; - - ASSERT_TRUE(compressed_proof_0 == compressed_proof_1); - - auto newproof = compressed_proof_1.to_libsnark_proof>(); - - ASSERT_TRUE(proof == newproof); - ASSERT_TRUE(libsnark::r1cs_ppzksnark_verifier_strong_IC( - kp.vk, - example.primary_input, - newproof - )); - } -} - -TEST(proofs, g1_deserialization) -{ - CompressedG1 g; - curve_G1 expected; - - // Valid G1 element. - { - CDataStream ss(ParseHex("0230644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - expected.X = curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582"); - expected.Y = curve_Fq("3969792565221544645472939191694882283483352126195956956354061729942568608776"); - expected.Z = curve_Fq::one(); - - ASSERT_TRUE(g.to_libsnark_g1() == expected); - } - - // Its negation. - { - CDataStream ss(ParseHex("0330644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - expected.X = curve_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582"); - expected.Y = curve_Fq("3969792565221544645472939191694882283483352126195956956354061729942568608776"); - expected.Z = curve_Fq::one(); - - ASSERT_TRUE(g.to_libsnark_g1() == -expected); - } - - // Invalid leading bytes - { - CDataStream ss(ParseHex("ff30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"), SER_NETWORK, PROTOCOL_VERSION); - - ASSERT_THROW(ss >> g, std::ios_base::failure); - } - - // Invalid point - { - CDataStream ss(ParseHex("0208c6d2adffacbc8438f09f321874ea66e2fcc29f8dcfec2caefa21ec8c96a77c"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - ASSERT_THROW(g.to_libsnark_g1(), std::runtime_error); - } - - // Point with out of bounds Fq - { - CDataStream ss(ParseHex("02ffc6d2adffacbc8438f09f321874ea66e2fcc29f8dcfec2caefa21ec8c96a77c"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - ASSERT_THROW(g.to_libsnark_g1(), std::logic_error); - } - - // Randomly produce valid G1 representations and fail/succeed to - // turn them into G1 points based on whether they are valid. - for (size_t i = 0; i < 5000; i++) { - curve_Fq e = curve_Fq::random_element(); - CDataStream ss(ParseHex("02"), SER_NETWORK, PROTOCOL_VERSION); - ss << Fq(e); - CompressedG1 g; - ss >> g; - - try { - curve_G1 g_real = g.to_libsnark_g1(); - } catch(...) { - - } - } -} - -TEST(proofs, g2_deserialization) -{ - CompressedG2 g; - curve_G2 expected = curve_G2::random_element(); - - // Valid G2 point - { - CDataStream ss(ParseHex("0a023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - expected.X = curve_Fq2( - curve_Fq("5923585509243758863255447226263146374209884951848029582715967108651637186684"), - curve_Fq("5336385337059958111259504403491065820971993066694750945459110579338490853570") - ); - expected.Y = curve_Fq2( - curve_Fq("10374495865873200088116930399159835104695426846400310764827677226300185211748"), - curve_Fq("5256529835065685814318509161957442385362539991735248614869838648137856366932") - ); - expected.Z = curve_Fq2::one(); - - ASSERT_TRUE(g.to_libsnark_g2() == expected); - } - - // Its negation - { - CDataStream ss(ParseHex("0b023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - expected.X = curve_Fq2( - curve_Fq("5923585509243758863255447226263146374209884951848029582715967108651637186684"), - curve_Fq("5336385337059958111259504403491065820971993066694750945459110579338490853570") - ); - expected.Y = curve_Fq2( - curve_Fq("10374495865873200088116930399159835104695426846400310764827677226300185211748"), - curve_Fq("5256529835065685814318509161957442385362539991735248614869838648137856366932") - ); - expected.Z = curve_Fq2::one(); - - ASSERT_TRUE(g.to_libsnark_g2() == -expected); - } - - // Invalid leading bytes - { - CDataStream ss(ParseHex("ff023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a"), SER_NETWORK, PROTOCOL_VERSION); - - ASSERT_THROW(ss >> g, std::ios_base::failure); - } - - - // Invalid point - { - CDataStream ss(ParseHex("0b023aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984b"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - ASSERT_THROW(g.to_libsnark_g2(), std::runtime_error); - } - - // Point with out of bounds Fq2 - { - CDataStream ss(ParseHex("0a0f3aed31b5a9e486366ea9988b05dba469c6206e58361d9c065bbea7d928204a761efc6e4fa08ed227650134b52c7f7dd0463963e8a4bf21f4899fe5da7f984a"), SER_NETWORK, PROTOCOL_VERSION); - ss >> g; - - ASSERT_THROW(g.to_libsnark_g2(), std::logic_error); - } - - // Randomly produce valid G2 representations and fail/succeed to - // turn them into G2 points based on whether they are valid. - for (size_t i = 0; i < 5000; i++) { - curve_Fq2 e = curve_Fq2::random_element(); - CDataStream ss(ParseHex("0a"), SER_NETWORK, PROTOCOL_VERSION); - ss << Fq2(e); - CompressedG2 g; - ss >> g; - - try { - curve_G2 g_real = g.to_libsnark_g2(); - } catch(...) { - - } - } -} - -#include "json_test_vectors.h" -#include "test/data/g1_compressed.json.h" - -TEST(proofs, g1_test_vectors) -{ - UniValue v = read_json(std::string(json_tests::g1_compressed, json_tests::g1_compressed + sizeof(json_tests::g1_compressed))); - - curve_G1 e = curve_Fr("34958239045823") * curve_G1::one(); - for (size_t i = 0; i < 10000; i++) { - e = (curve_Fr("34958239045823") ^ i) * e; - auto expected = CompressedG1(e); - - expect_test_vector(v[i], expected); - ASSERT_TRUE(expected.to_libsnark_g1() == e); - } -} - -#include "test/data/g2_compressed.json.h" - -TEST(proofs, g2_test_vectors) -{ - UniValue v = read_json(std::string(json_tests::g2_compressed, json_tests::g2_compressed + sizeof(json_tests::g2_compressed))); - - curve_G2 e = curve_Fr("34958239045823") * curve_G2::one(); - for (size_t i = 0; i < 10000; i++) { - e = (curve_Fr("34958239045823") ^ i) * e; - auto expected = CompressedG2(e); - - expect_test_vector(v[i], expected); - ASSERT_TRUE(expected.to_libsnark_g2() == e); - } -} diff --git a/src/gtest/test_rpc.cpp b/src/gtest/test_rpc.cpp index a7dc398cb..405855c85 100644 --- a/src/gtest/test_rpc.cpp +++ b/src/gtest/test_rpc.cpp @@ -11,7 +11,7 @@ extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); -TEST(rpc, check_blockToJSON_returns_minified_solution) { +TEST(rpc, CheckBlockToJSONReturnsMinifiedSolution) { SelectParams(CBaseChainParams::TESTNET); // Testnet block 006a87f9f91c1f51c7549e2c8965c0fd4fe8c212798f932efc54dc7bccbec780 @@ -27,48 +27,46 @@ TEST(rpc, check_blockToJSON_returns_minified_solution) { EXPECT_EQ("009f44ff7505d789b964d6817734b8ce1377d456255994370d06e59ac99bd5791b6ad174a66fd71c70e60cfc7fd88243ffe06f80b1ad181625f210779c745524629448e25348a5fce4f346a1735e60fdf53e144c0157dbc47c700a21a236f1efb7ee75f65b8d9d9e29026cfd09048233175202b211b9a49de4ab46f1cac71b6ea57a686377bd612378746e70c61a659c9cd683269e9c2a5cbc1d19f1149345302bbd0a1e62bf4bab01e9caeea789a1519441a61b146de35a4cc75dbdf01029127e311ad5073e7e96397f47226a7df9df66b2086b70756db013bbaeb068260157014b2602fc7dc71336e1439c887d2742d9730b4e79b08ec7839c3e2a037ae1565d04e05e351bb3531e5ef42cf7b71ca1482a9205245dd41f4db0f71644f8bdb88e845558537c03834c06ac83f336651e54e2edfc12e15ea9b7ea2c074e6155654d44c4d3bd90d9511050e9ad87d170db01448e5be6f45419cd86008978db5e3ceab79890234f992648d69bf1053855387db646ccdee5575c65f81dd0f670b016d9f9a84707d91f77b862f697b8bb08365ba71fbe6bfa47af39155a75ebdcb1e5d69f59c40c9e3a64988c1ec26f7f5159eef5c244d504a9e46125948ecc389c2ec3028ac4ff39ffd66e7743970819272b21e0c2df75b308bc62896873952147e57ed79446db4cdb5a563e76ec4c25899d41128afb9a5f8fc8063621efb7a58b9dd666d30c73e318cdcf3393bfec200e160f500e645f7baac263db99fa4a7c1cb4fea219fc512193102034d379f244c21a81821301b8d47c90247713a3e902c762d7bafa6cdb744eeb6d3b50dd175599d02b6e9f5bbda59366e04862aa765135968426e7ac0116de7351940dc57c0ae451d63f667e39891bc81e09e6c76f6f8a7582f7447c6f5945f717b0e52a7e3dd0c6db4061362123cc53fd8ede4abed4865201dc4d8eb4e5d48baa565183b69a5304a44c0600bb24dcaeee9d95ceebd27c1b0a33e0b46f23797d7d7907300b2bb7d62ef2fc5aa139250c73930c621bb5f41fc235534ee8014dfaddd5245aeb01198420ba7b5c076545329c94d54fa725a8e807579f5f0cc9d98170598023268f5930893620190275e6b3c6f5181e36310a9a475208316911d78f917d724c5946c553b7ec042c563c540114b6b78bd4c6e808ee391a4a9d93e127032983c5b3708037b14aa604cfb034e7c8b0ffdd6936446fe80216178506a87402653a373926eeff66e704daf992a0a9a5c3ad80566c0339be9e5b8e35b3b3226b2f7767e20d992ea6c3d6e322eca37b0c7f7e60060802f5abcc1975841365cadbdc3867063addfc803766ae525375ecddee61f9df9ffcd20343c83ab82b0e91de039c59cb435c8d3159cc338b4901f40c9b5c27043bcf2bd5fa9b685b65c9ba5a1e11a51dd3f773051560341f9ec81d05bf259e2d4b7161f896fbb6812cfc924a32120b7367d5e40439e267adda6a1315bb0d6200ce6a503174c8d2a638ea6fd6b1f486d68db11bdca63c4f4a725d1ab6231ea875484e70b27d293c05803386924f283d4c12bb953474d92b7dd43d2d97193bd96281ebb63fa075d2f9ecd310c70ee1d97b5330bd8fb5791c5943ecf084e5f2c83915acac57519c46b166136068d6f9ec0dd598616e32c591128ce13705a283ca39d5b211409600e07b3713113374d9700207a45394eac5b3b7afc9b1b2bad7d89fd3f35f6b2413ce615ee7869b3569009403b96fdacdb32ef0a7e5229e2b666d51e95bdfb009b892e88bde70621a9b6509f068781392df4bdbc5723bb15071993f0d9a11575af5ff6ef85eaea39bc86805b35d8beee91b779354147f2d85304b8b49d053e7444fdd3deb9d16de331f2552af5b3be7766bb8f3f6a78c62148efb231f2268", find_value(obj, "solution").get_str()); } - - - - -// -// TEST(rpc, CheckExperimentalDisabledHelpMsg) { -// EXPECT_EQ(experimentalDisabledHelpMsg("somerpc", {"somevalue"}), -// "\nWARNING: somerpc is disabled.\n" -// "To enable it, restart zcashd with the following command line options:\n" -// "-experimentalfeatures and -somevalue\n\n" -// "Alternatively add these two lines to the zcash.conf file:\n\n" -// "experimentalfeatures=1\n" -// "somevalue=1\n"); -// EXPECT_EQ(experimentalDisabledHelpMsg("somerpc", {"somevalue", "someothervalue"}), -// "\nWARNING: somerpc is disabled.\n" -// "To enable it, restart zcashd with the following command line options:\n" -// "-experimentalfeatures and -somevalue" -// " or:\n-experimentalfeatures and -someothervalue" -// "\n\n" -// "Alternatively add these two lines to the zcash.conf file:\n\n" -// "experimentalfeatures=1\n" -// "somevalue=1\n" -// "\nor:\n\n" -// "experimentalfeatures=1\n" -// "someothervalue=1\n"); -// EXPECT_EQ(experimentalDisabledHelpMsg("somerpc", {"somevalue", "someothervalue", "athirdvalue"}), -// "\nWARNING: somerpc is disabled.\n" -// "To enable it, restart zcashd with the following command line options:\n" -// "-experimentalfeatures and -somevalue" -// " or:\n-experimentalfeatures and -someothervalue" -// " or:\n-experimentalfeatures and -athirdvalue" -// "\n\n" -// "Alternatively add these two lines to the zcash.conf file:\n\n" -// "experimentalfeatures=1\n" -// "somevalue=1\n" -// "\nor:\n\n" -// "experimentalfeatures=1\n" -// "someothervalue=1\n" -// "\nor:\n\n" -// "experimentalfeatures=1\n" -// "athirdvalue=1\n"); -// } +TEST(rpc, CheckExperimentalDisabledHelpMsg) { + + EXPECT_EQ(experimentalDisabledHelpMsg("somerpc", {"somevalue"}), + "\nWARNING: somerpc is disabled.\n" + "To enable it, restart zcashd with the following command line options:\n" + "-experimentalfeatures and -somevalue\n\n" + "Alternatively add these two lines to the zcash.conf file:\n\n" + "experimentalfeatures=1\n" + "somevalue=1\n"); + + EXPECT_EQ(experimentalDisabledHelpMsg("somerpc", {"somevalue", "someothervalue"}), + "\nWARNING: somerpc is disabled.\n" + "To enable it, restart zcashd with the following command line options:\n" + "-experimentalfeatures and -somevalue" + " or:\n-experimentalfeatures and -someothervalue" + "\n\n" + "Alternatively add these two lines to the zcash.conf file:\n\n" + "experimentalfeatures=1\n" + "somevalue=1\n" + "\nor:\n\n" + "experimentalfeatures=1\n" + "someothervalue=1\n"); + + EXPECT_EQ(experimentalDisabledHelpMsg("somerpc", {"somevalue", "someothervalue", "athirdvalue"}), + "\nWARNING: somerpc is disabled.\n" + "To enable it, restart zcashd with the following command line options:\n" + "-experimentalfeatures and -somevalue" + " or:\n-experimentalfeatures and -someothervalue" + " or:\n-experimentalfeatures and -athirdvalue" + "\n\n" + "Alternatively add these two lines to the zcash.conf file:\n\n" + "experimentalfeatures=1\n" + "somevalue=1\n" + "\nor:\n\n" + "experimentalfeatures=1\n" + "someothervalue=1\n" + "\nor:\n\n" + "experimentalfeatures=1\n" + "athirdvalue=1\n"); +} TEST(rpc, ParseHeightArg) { EXPECT_EQ(parseHeightArg("15", 21), 15); diff --git a/src/gtest/test_sapling_note.cpp b/src/gtest/test_sapling_note.cpp index 3e336ec7e..8d850fb1e 100644 --- a/src/gtest/test_sapling_note.cpp +++ b/src/gtest/test_sapling_note.cpp @@ -45,7 +45,7 @@ TEST(SaplingNote, TestVectors) // Test commitment SaplingNote note = SaplingNote(diversifier, pk_d, v, r); - ASSERT_EQ(note.cm().get(), cm); + ASSERT_EQ(note.cmu().value(), cm); // Test nullifier SaplingSpendingKey spendingKey(sk); diff --git a/src/gtest/test_tautology.cpp b/src/gtest/test_tautology.cpp index 3d1386714..45ab14f7f 100644 --- a/src/gtest/test_tautology.cpp +++ b/src/gtest/test_tautology.cpp @@ -1,6 +1,6 @@ #include -TEST(tautologies, seven_eq_seven) { +TEST(tautologies, SevenEqSeven) { ASSERT_EQ(7, 7); } diff --git a/src/gtest/test_transaction.cpp b/src/gtest/test_transaction.cpp index 1350768ff..4ba48c3d2 100644 --- a/src/gtest/test_transaction.cpp +++ b/src/gtest/test_transaction.cpp @@ -45,7 +45,6 @@ TEST(Transaction, JSDescriptionRandomized) { { auto jsdesc = JSDescription::Randomized( - false, *params, joinSplitPubKey, rt, inputs, outputs, inputMap, outputMap, @@ -62,7 +61,6 @@ TEST(Transaction, JSDescriptionRandomized) { { auto jsdesc = JSDescription::Randomized( - false, *params, joinSplitPubKey, rt, inputs, outputs, inputMap, outputMap, @@ -76,7 +74,6 @@ TEST(Transaction, JSDescriptionRandomized) { { auto jsdesc = JSDescription::Randomized( - false, *params, joinSplitPubKey, rt, inputs, outputs, inputMap, outputMap, diff --git a/src/gtest/test_txid.cpp b/src/gtest/test_txid.cpp index 9b4a21068..bffd24436 100644 --- a/src/gtest/test_txid.cpp +++ b/src/gtest/test_txid.cpp @@ -10,8 +10,8 @@ /* Test that removing #1144 succeeded by verifying the hash of a transaction is over the entire serialized form. */ -TEST(txid_tests, check_txid_and_hash_are_same) { - // Random zcash transaction aacaa62d40fcdd9192ed35ea9df31660ccf7f6c60566530faaa444fb5d0d410e +TEST(TxidTests, CheckTxidAndHashAreSame) { + // Random bitcoinz transaction aacaa62d40fcdd9192ed35ea9df31660ccf7f6c60566530faaa444fb5d0d410e CTransaction tx; CDataStream stream(ParseHex("01000000015ad78be5497476bbf84869d8156761ca850b6e82e48ad1315069a3726516a3d1010000006b483045022100ba5e90204e83c5f961b67c6232c1cc6c360afd36d43fcfae0de7af2e75f4cda7022012fec415a12048dbb70511fda6195b090b56735232281dc1144409833a092edc012102c322382e17c9ed4f47183f219cc5dd7853f939fb8eebae3c943622e0abf8d5e5feffffff0280969800000000001976a91430271a250e92135ce0db0783ebb63aaeb58e47f988acd694693a000000001976a9145f0d00adba6489150808feb4108d7be582cbb2e188ac0a000000"), SER_DISK, CLIENT_VERSION); stream >> tx; @@ -20,8 +20,8 @@ TEST(txid_tests, check_txid_and_hash_are_same) { ASSERT_TRUE(hash == tx.GetHash()); } -TEST(txid_tests, check_txid_and_hash_are_same_coinbase) { - // Random zcash coinbase transaction 6041357de59ba64959d1b60f93de24dfe5ea1e26ed9e8a73d35b225a1845bad5 +TEST(TxidTests, CheckTxidAndHashAreSameCoinbase) { + // Random bitcoinz coinbase transaction 6041357de59ba64959d1b60f93de24dfe5ea1e26ed9e8a73d35b225a1845bad5 CTransaction tx; CDataStream stream(ParseHex("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff03530101ffffffff02f049020000000000232102f2df427fd4f76552ed0e86b17da8cf9b07754ea23ddc05799410a4a3a5d806ccac7c9200000000000017a9146708e6670db0b950dac68031025cc5b63213a4918700000000"), SER_DISK, CLIENT_VERSION); stream >> tx; diff --git a/src/gtest/test_upgrades.cpp b/src/gtest/test_upgrades.cpp index 54fa48832..d7ff0d791 100644 --- a/src/gtest/test_upgrades.cpp +++ b/src/gtest/test_upgrades.cpp @@ -3,14 +3,14 @@ #include "chainparams.h" #include "consensus/upgrades.h" -#include +#include class UpgradesTest : public ::testing::Test { protected: - virtual void SetUp() { + void SetUp() override { } - virtual void TearDown() { + void TearDown() override { // Revert to default UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT); } @@ -148,28 +148,28 @@ TEST_F(UpgradesTest, NextEpoch) { const Consensus::Params& params = Params().GetConsensus(); // Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT - EXPECT_EQ(NextEpoch(-1, params), boost::none); - EXPECT_EQ(NextEpoch(0, params), boost::none); - EXPECT_EQ(NextEpoch(1, params), boost::none); - EXPECT_EQ(NextEpoch(1000000, params), boost::none); + EXPECT_EQ(NextEpoch(-1, params), std::nullopt); + EXPECT_EQ(NextEpoch(0, params), std::nullopt); + EXPECT_EQ(NextEpoch(1, params), std::nullopt); + EXPECT_EQ(NextEpoch(1000000, params), std::nullopt); UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); - EXPECT_EQ(NextEpoch(-1, params), boost::none); - EXPECT_EQ(NextEpoch(0, params), boost::none); - EXPECT_EQ(NextEpoch(1, params), boost::none); - EXPECT_EQ(NextEpoch(1000000, params), boost::none); + EXPECT_EQ(NextEpoch(-1, params), std::nullopt); + EXPECT_EQ(NextEpoch(0, params), std::nullopt); + EXPECT_EQ(NextEpoch(1, params), std::nullopt); + EXPECT_EQ(NextEpoch(1000000, params), std::nullopt); int nActivationHeight = 100; UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, nActivationHeight); - EXPECT_EQ(NextEpoch(-1, params), boost::none); + EXPECT_EQ(NextEpoch(-1, params), std::nullopt); EXPECT_EQ(NextEpoch(0, params), static_cast(Consensus::UPGRADE_TESTDUMMY)); EXPECT_EQ(NextEpoch(1, params), static_cast(Consensus::UPGRADE_TESTDUMMY)); EXPECT_EQ(NextEpoch(nActivationHeight - 1, params), static_cast(Consensus::UPGRADE_TESTDUMMY)); - EXPECT_EQ(NextEpoch(nActivationHeight, params), boost::none); - EXPECT_EQ(NextEpoch(nActivationHeight + 1, params), boost::none); - EXPECT_EQ(NextEpoch(1000000, params), boost::none); + EXPECT_EQ(NextEpoch(nActivationHeight, params), std::nullopt); + EXPECT_EQ(NextEpoch(nActivationHeight + 1, params), std::nullopt); + EXPECT_EQ(NextEpoch(1000000, params), std::nullopt); } TEST_F(UpgradesTest, NextActivationHeight) { @@ -177,26 +177,26 @@ TEST_F(UpgradesTest, NextActivationHeight) { const Consensus::Params& params = Params().GetConsensus(); // Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT - EXPECT_EQ(NextActivationHeight(-1, params), boost::none); - EXPECT_EQ(NextActivationHeight(0, params), boost::none); - EXPECT_EQ(NextActivationHeight(1, params), boost::none); - EXPECT_EQ(NextActivationHeight(1000000, params), boost::none); + EXPECT_EQ(NextActivationHeight(-1, params), std::nullopt); + EXPECT_EQ(NextActivationHeight(0, params), std::nullopt); + EXPECT_EQ(NextActivationHeight(1, params), std::nullopt); + EXPECT_EQ(NextActivationHeight(1000000, params), std::nullopt); UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, Consensus::NetworkUpgrade::ALWAYS_ACTIVE); - EXPECT_EQ(NextActivationHeight(-1, params), boost::none); - EXPECT_EQ(NextActivationHeight(0, params), boost::none); - EXPECT_EQ(NextActivationHeight(1, params), boost::none); - EXPECT_EQ(NextActivationHeight(1000000, params), boost::none); + EXPECT_EQ(NextActivationHeight(-1, params), std::nullopt); + EXPECT_EQ(NextActivationHeight(0, params), std::nullopt); + EXPECT_EQ(NextActivationHeight(1, params), std::nullopt); + EXPECT_EQ(NextActivationHeight(1000000, params), std::nullopt); int nActivationHeight = 100; UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, nActivationHeight); - EXPECT_EQ(NextActivationHeight(-1, params), boost::none); + EXPECT_EQ(NextActivationHeight(-1, params), std::nullopt); EXPECT_EQ(NextActivationHeight(0, params), nActivationHeight); EXPECT_EQ(NextActivationHeight(1, params), nActivationHeight); EXPECT_EQ(NextActivationHeight(nActivationHeight - 1, params), nActivationHeight); - EXPECT_EQ(NextActivationHeight(nActivationHeight, params), boost::none); - EXPECT_EQ(NextActivationHeight(nActivationHeight + 1, params), boost::none); - EXPECT_EQ(NextActivationHeight(1000000, params), boost::none); + EXPECT_EQ(NextActivationHeight(nActivationHeight, params), std::nullopt); + EXPECT_EQ(NextActivationHeight(nActivationHeight + 1, params), std::nullopt); + EXPECT_EQ(NextActivationHeight(1000000, params), std::nullopt); } diff --git a/src/gtest/test_validation.cpp b/src/gtest/test_validation.cpp index 43c42741d..e6d68fdaa 100644 --- a/src/gtest/test_validation.cpp +++ b/src/gtest/test_validation.cpp @@ -1,20 +1,23 @@ #include +#include "consensus/merkle.h" #include "consensus/upgrades.h" #include "consensus/validation.h" #include "main.h" #include "utiltest.h" +#include + extern ZCJoinSplit* params; extern bool ReceivedBlockTransactions( - const CBlock &block, - CValidationState& state, - const CChainParams& chainparams, - CBlockIndex *pindexNew, - const CDiskBlockPos& pos); + const CBlock &block, + CValidationState& state, + const CChainParams& chainparams, + CBlockIndex *pindexNew, + const CDiskBlockPos& pos); -void ExpectOptionalAmount(CAmount expected, boost::optional actual) { +void ExpectOptionalAmount(CAmount expected, std::optional actual) { EXPECT_TRUE((bool)actual); if (actual) { EXPECT_EQ(expected, *actual); @@ -98,14 +101,14 @@ TEST(Validation, ReceivedBlockTransactions) { // Create a fake genesis block CBlock block1; block1.vtx.push_back(GetValidSproutReceive(*params, sk, 5, true)); - block1.hashMerkleRoot = block1.BuildMerkleTree(); + block1.hashMerkleRoot = BlockMerkleRoot(block1); CBlockIndex fakeIndex1 {block1}; // Create a fake child block CBlock block2; block2.hashPrevBlock = block1.GetHash(); block2.vtx.push_back(GetValidSproutReceive(*params, sk, 10, true)); - block2.hashMerkleRoot = block2.BuildMerkleTree(); + block2.hashMerkleRoot = BlockMerkleRoot(block2); CBlockIndex fakeIndex2 {block2}; fakeIndex2.pprev = &fakeIndex1; diff --git a/src/gtest/test_zip32.cpp b/src/gtest/test_zip32.cpp index e7715fd03..c8ee5a335 100644 --- a/src/gtest/test_zip32.cpp +++ b/src/gtest/test_zip32.cpp @@ -109,7 +109,7 @@ TEST(ZIP32, TestVectors) { auto maybe_m_1_2hv_3 = m_1_2hv.Derive(3); EXPECT_TRUE(maybe_m_1_2hv_3); - auto m_1_2hv_3 = maybe_m_1_2hv_3.get(); + auto m_1_2hv_3 = maybe_m_1_2hv_3.value(); EXPECT_EQ(m_1_2hv_3.depth, 3); EXPECT_EQ(m_1_2hv_3.parentFVKTag, 0x7583c148); EXPECT_EQ(m_1_2hv_3.childIndex, 3); diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 10002683f..d0a43ced0 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -10,6 +10,9 @@ #include "util.h" #include "utilstrencodings.h" #include "ui_interface.h" +#include "crypto/hmac_sha256.h" +#include +#include "utilstrencodings.h" #include // boost::trim @@ -22,7 +25,7 @@ static const char* WWW_AUTH_HEADER_DATA = "Basic realm=\"jsonrpc\""; class HTTPRPCTimer : public RPCTimerBase { public: - HTTPRPCTimer(struct event_base* eventBase, boost::function& func, int64_t millis) : + HTTPRPCTimer(struct event_base* eventBase, std::function& func, int64_t millis) : ev(eventBase, false, func) { struct timeval tv; @@ -44,7 +47,7 @@ class HTTPRPCTimerInterface : public RPCTimerInterface { return "HTTP"; } - RPCTimerBase* NewTimer(boost::function& func, int64_t millis) + RPCTimerBase* NewTimer(std::function& func, int64_t millis) { return new HTTPRPCTimer(base, func, millis); } @@ -75,6 +78,50 @@ static void JSONErrorReply(HTTPRequest* req, const UniValue& objError, const Uni req->WriteReply(nStatus, strReply); } +//This function checks username and password against -rpcauth +//entries from config file. +static bool multiUserAuthorized(std::string strUserPass) +{ + if (strUserPass.find(":") == std::string::npos) { + return false; + } + std::string strUser = strUserPass.substr(0, strUserPass.find(":")); + std::string strPass = strUserPass.substr(strUserPass.find(":") + 1); + + if (mapMultiArgs.count("-rpcauth") > 0) { + //Search for multi-user login/pass "rpcauth" from config + for (std::string strRPCAuth : mapMultiArgs["-rpcauth"]) + { + std::vector vFields; + boost::split(vFields, strRPCAuth, boost::is_any_of(":$")); + if (vFields.size() != 3) { + //Incorrect formatting in config file + continue; + } + + std::string strName = vFields[0]; + if (!TimingResistantEqual(strName, strUser)) { + continue; + } + + std::string strSalt = vFields[1]; + std::string strHash = vFields[2]; + + unsigned int KEY_SIZE = 32; + unsigned char *out = new unsigned char[KEY_SIZE]; + + CHMAC_SHA256(reinterpret_cast(strSalt.c_str()), strSalt.size()).Write(reinterpret_cast(strPass.c_str()), strPass.size()).Finalize(out); + std::vector hexvec(out, out+KEY_SIZE); + std::string strHashFromPass = HexStr(hexvec); + + if (TimingResistantEqual(strHashFromPass, strHash)) { + return true; + } + } + } + return false; +} + static bool RPCAuthorized(const std::string& strAuth) { if (strRPCUserColonPass.empty()) // Belt-and-suspenders measure if InitRPCAuthentication was not called @@ -84,7 +131,12 @@ static bool RPCAuthorized(const std::string& strAuth) std::string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64); std::string strUserPass = DecodeBase64(strUserPass64); - return TimingResistantEqual(strUserPass, strRPCUserColonPass); + + //Check if authorized under single-user field + if (TimingResistantEqual(strUserPass, strRPCUserColonPass)) { + return true; + } + return multiUserAuthorized(strUserPass); } static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &) @@ -162,6 +214,7 @@ static bool InitRPCAuthentication() return false; } } else { + LogPrintf("Config options rpcuser and rpcpassword will soon be deprecated. Locally-run instances may remove rpcuser to use cookie-based auth, or may be replaced with rpcauth. Please see share/rpcuser for rpcauth auth generation.\n"); strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; } return true; diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 9227e26bb..3e21bce8e 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -12,6 +12,7 @@ #include "sync.h" #include "ui_interface.h" +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include @@ -34,16 +36,15 @@ #endif #endif -#include // for to_lower() -#include -#include +/** Maximum size of http request (request line + headers) */ +static const size_t MAX_HEADERS_SIZE = 8192; /** HTTP request work item */ class HTTPWorkItem : public HTTPClosure { public: - HTTPWorkItem(HTTPRequest* req, const std::string &path, const HTTPRequestHandler& func): - req(req), path(path), func(func) + HTTPWorkItem(std::unique_ptr req, const std::string &path, const HTTPRequestHandler& func): + req(std::move(req)), path(path), func(func) { } void operator()() @@ -51,7 +52,7 @@ class HTTPWorkItem : public HTTPClosure func(req.get(), path); } - boost::scoped_ptr req; + std::unique_ptr req; private: std::string path; @@ -66,10 +67,9 @@ class WorkQueue { private: /** Mutex protects entire object */ - CWaitableCriticalSection cs; - CConditionVariable cond; - /* XXX in C++11 we can use std::unique_ptr here and avoid manual cleanup */ - std::deque queue; + std::mutex cs; + std::condition_variable cond; + std::deque> queue; bool running; size_t maxDepth; int numThreads; @@ -81,12 +81,12 @@ class WorkQueue WorkQueue &wq; ThreadCounter(WorkQueue &w): wq(w) { - boost::lock_guard lock(wq.cs); + std::lock_guard lock(wq.cs); wq.numThreads += 1; } ~ThreadCounter() { - boost::lock_guard lock(wq.cs); + std::lock_guard lock(wq.cs); wq.numThreads -= 1; wq.cond.notify_all(); } @@ -98,24 +98,20 @@ class WorkQueue numThreads(0) { } - /*( Precondition: worker threads have all stopped + /** Precondition: worker threads have all stopped * (call WaitExit) */ ~WorkQueue() { - while (!queue.empty()) { - delete queue.front(); - queue.pop_front(); - } } /** Enqueue a work item */ bool Enqueue(WorkItem* item) { - boost::unique_lock lock(cs); + std::unique_lock lock(cs); if (queue.size() >= maxDepth) { return false; } - queue.push_back(item); + queue.emplace_back(std::unique_ptr(item)); cond.notify_one(); return true; } @@ -124,31 +120,30 @@ class WorkQueue { ThreadCounter count(*this); while (running) { - WorkItem* i = 0; + std::unique_ptr i; { - boost::unique_lock lock(cs); + std::unique_lock lock(cs); while (running && queue.empty()) cond.wait(lock); if (!running) break; - i = queue.front(); + i = std::move(queue.front()); queue.pop_front(); } (*i)(); - delete i; } } /** Interrupt and exit loops */ void Interrupt() { - boost::unique_lock lock(cs); + std::unique_lock lock(cs); running = false; cond.notify_all(); } /** Wait for worker threads to exit */ void WaitExit() { - boost::unique_lock lock(cs); + std::unique_lock lock(cs); while (numThreads > 0) cond.wait(lock); } @@ -156,7 +151,7 @@ class WorkQueue /** Return current depth of queue */ size_t Depth() { - boost::unique_lock lock(cs); + std::unique_lock lock(cs); return queue.size(); } }; @@ -193,7 +188,7 @@ static bool ClientAllowed(const CNetAddr& netaddr) { if (!netaddr.IsValid()) return false; - BOOST_FOREACH (const CSubNet& subnet, rpc_allow_subnets) + for (const CSubNet& subnet : rpc_allow_subnets) if (subnet.Match(netaddr)) return true; return false; @@ -207,7 +202,7 @@ static bool InitHTTPAllowList() rpc_allow_subnets.push_back(CSubNet("::1")); // always allow IPv6 localhost if (mapMultiArgs.count("-rpcallowip")) { const std::vector& vAllow = mapMultiArgs["-rpcallowip"]; - BOOST_FOREACH (std::string strAllow, vAllow) { + for (std::string strAllow : vAllow) { CSubNet subnet(strAllow); if (!subnet.IsValid()) { uiInterface.ThreadSafeMessageBox( @@ -219,7 +214,7 @@ static bool InitHTTPAllowList() } } std::string strAllowed; - BOOST_FOREACH (const CSubNet& subnet, rpc_allow_subnets) + for (const CSubNet& subnet : rpc_allow_subnets) strAllowed += subnet.ToString() + " "; LogPrint("http", "Allowing HTTP connections from: %s\n", strAllowed); return true; @@ -285,12 +280,15 @@ static void http_request_cb(struct evhttp_request* req, void* arg) // Dispatch to worker thread if (i != iend) { - std::unique_ptr item(new HTTPWorkItem(hreq.release(), path, i->handler)); + std::unique_ptr item(new HTTPWorkItem(std::move(hreq), path, i->handler)); assert(workQueue); if (workQueue->Enqueue(item.get())) + { item.release(); /* if true, queue took ownership */ - else - item->req->WriteReply(HTTP_INTERNAL, "Work queue depth exceeded"); + } else { + LogPrintf("WARNING: request rejected because http work queue depth exceeded, it can be increased with the -rpcworkqueue= setting\n"); + item->req->WriteReply(HTTP_SERVICE_UNAVAILABLE, "Work queue depth exceeded"); + } } else { hreq->WriteReply(HTTP_NOTFOUND); } @@ -304,13 +302,14 @@ static void http_reject_request_cb(struct evhttp_request* req, void*) } /** Event dispatcher thread */ -static void ThreadHTTP(struct event_base* base, struct evhttp* http) +static bool ThreadHTTP(struct event_base* base, struct evhttp* http) { - RenameThread("zcash-http"); + RenameThread("bitcoinz-http"); LogPrint("http", "Entering http event loop\n"); event_base_dispatch(base); // Event loop will be interrupted by InterruptHTTPServer() LogPrint("http", "Exited http event loop\n"); + return event_base_got_break(base) == 0; } /** Bind HTTP server to specified addresses */ @@ -355,7 +354,7 @@ static bool HTTPBindAddresses(struct evhttp* http) /** Simple wrapper to set thread name and run work queue */ static void HTTPWorkQueueRun(WorkQueue* queue) { - RenameThread("zcash-httpworker"); + RenameThread("bitcoinz-httpworker"); queue->Run(); } @@ -418,6 +417,7 @@ bool InitHTTPServer() } evhttp_set_timeout(http, GetArg("-rpcservertimeout", DEFAULT_HTTP_SERVER_TIMEOUT)); + evhttp_set_max_headers_size(http, MAX_HEADERS_SIZE); evhttp_set_max_body_size(http, MAX_SIZE); evhttp_set_gencb(http, http_request_cb, NULL); @@ -438,17 +438,20 @@ bool InitHTTPServer() return true; } -boost::thread threadHTTP; +std::thread threadHTTP; +std::future threadResult; bool StartHTTPServer() { LogPrint("http", "Starting HTTP server\n"); int rpcThreads = std::max((long)GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L); LogPrintf("HTTP: starting %d worker threads\n", rpcThreads); - threadHTTP = boost::thread(boost::bind(&ThreadHTTP, eventBase, eventHTTP)); + std::packaged_task task(ThreadHTTP); + threadResult = task.get_future(); + threadHTTP = std::thread(std::move(task), eventBase, eventHTTP); for (int i = 0; i < rpcThreads; i++) { - boost::thread rpc_worker(HTTPWorkQueueRun, workQueue); + std::thread rpc_worker(HTTPWorkQueueRun, workQueue); rpc_worker.detach(); } return true; @@ -459,7 +462,7 @@ void InterruptHTTPServer() LogPrint("http", "Interrupting HTTP server\n"); if (eventHTTP) { // Unlisten sockets - BOOST_FOREACH (evhttp_bound_socket *socket, boundSockets) { + for (evhttp_bound_socket *socket : boundSockets) { evhttp_del_accept_socket(eventHTTP, socket); } // Reject requests on current connections @@ -487,11 +490,11 @@ void StopHTTPServer() // master that appears to be solved, so in the future that solution // could be used again (if desirable). // (see discussion in https://github.com/bitcoin/bitcoin/pull/6990) - if (!threadHTTP.try_join_for(boost::chrono::milliseconds(2000))) { + if (threadResult.valid() && threadResult.wait_for(std::chrono::milliseconds(2000)) == std::future_status::timeout) { LogPrintf("HTTP event loop did not exit within allotted time, sending loopbreak\n"); event_base_loopbreak(eventBase); - threadHTTP.join(); } + threadHTTP.join(); } if (eventHTTP) { evhttp_free(eventHTTP); @@ -518,7 +521,7 @@ static void httpevent_callback_fn(evutil_socket_t, short, void* data) delete self; } -HTTPEvent::HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const boost::function& handler): +HTTPEvent::HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const std::function& handler): deleteWhenTriggered(deleteWhenTriggered), handler(handler) { ev = event_new(base, -1, 0, httpevent_callback_fn, this); @@ -600,7 +603,7 @@ void HTTPRequest::WriteReply(int nStatus, const std::string& strReply) assert(evb); evbuffer_add(evb, strReply.data(), strReply.size()); HTTPEvent* ev = new HTTPEvent(eventBase, true, - boost::bind(evhttp_send_reply, req, nStatus, (const char*)NULL, (struct evbuffer *)NULL)); + std::bind(evhttp_send_reply, req, nStatus, (const char*)NULL, (struct evbuffer *)NULL)); ev->trigger(0); replySent = true; req = 0; // transferred back to main thread @@ -665,4 +668,3 @@ void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch) pathHandlers.erase(i); } } - diff --git a/src/httpserver.h b/src/httpserver.h index 68d26ce2e..23c7f7f71 100644 --- a/src/httpserver.h +++ b/src/httpserver.h @@ -7,9 +7,7 @@ #include #include -#include -#include -#include +#include static const int DEFAULT_HTTP_THREADS=4; static const int DEFAULT_HTTP_WORKQUEUE=16; @@ -35,7 +33,7 @@ void InterruptHTTPServer(); void StopHTTPServer(); /** Handler for requests to a certain HTTP path */ -typedef boost::function HTTPRequestHandler; +typedef std::function HTTPRequestHandler; /** Register handler for prefix. * If multiple handlers match a prefix, the first-registered one will * be invoked. @@ -87,7 +85,7 @@ class HTTPRequest /** * Get the request header specified by hdr, or an empty string. - * Return an pair (isPresent,string). + * Return a pair (isPresent,string). */ virtual std::pair GetHeader(const std::string& hdr); @@ -126,7 +124,7 @@ class HTTPClosure virtual ~HTTPClosure() {} }; -/** Event class. This can be used either as an cross-thread trigger or as a timer. +/** Event class. This can be used either as a cross-thread trigger or as a timer. */ class HTTPEvent { @@ -135,7 +133,7 @@ class HTTPEvent * deleteWhenTriggered deletes this event object after the event is triggered (and the handler called) * handler is the handler to call when the event is triggered. */ - HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const boost::function& handler); + HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const std::function& handler); ~HTTPEvent(); /** Trigger the event. If tv is 0, trigger it immediately. Otherwise trigger it after @@ -144,7 +142,7 @@ class HTTPEvent void trigger(struct timeval* tv); bool deleteWhenTriggered; - boost::function handler; + std::function handler; private: struct event* ev; }; diff --git a/src/init.cpp b/src/init.cpp index 70c159a75..f176a20d5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -15,6 +15,7 @@ #include "compat/sanity.h" #include "consensus/upgrades.h" #include "consensus/validation.h" +#include "experimental_features.h" #include "httpserver.h" #include "httprpc.h" #include "key.h" @@ -22,13 +23,14 @@ #include "key_io.h" #endif #include "main.h" +#include "mempool_limit.h" #include "metrics.h" #include "miner.h" #include "net.h" +#include "policy/policy.h" #include "rpc/server.h" #include "rpc/register.h" #include "script/standard.h" -#include "script/sigcache.h" #include "scheduler.h" #include "txdb.h" #include "torcontrol.h" @@ -53,14 +55,10 @@ #include #include #include -#include +#include #include -#include #include #include -#include - -#include #if ENABLE_ZMQ #include "zmq/zmqnotificationinterface.h" @@ -73,15 +71,21 @@ #include "librustzcash.h" using namespace std; +using namespace boost::placeholders; extern void ThreadSendAlert(); ZCJoinSplit* pzcashParams = NULL; -#ifdef ENABLE_WALLET -CWallet* pwalletMain = NULL; -#endif bool fFeeEstimatesInitialized = false; +static const bool DEFAULT_PROXYRANDOMIZE = true; +static const bool DEFAULT_REST_ENABLE = false; +static const bool DEFAULT_DISABLE_SAFEMODE = false; +static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false; + +// The time that the wallet will wait for the block index to load +// during startup before timing out. +static const int64_t WALLET_INITIAL_SYNC_TIMEOUT = 1000 * 60 * 60 * 2; #if ENABLE_ZMQ static CZMQNotificationInterface* pzmqNotificationInterface = NULL; @@ -194,7 +198,7 @@ void Shutdown() /// for example if the data directory was found to be locked. /// Be sure that anything that writes files or flushes caches only does this if the respective /// module was initialized. - RenameThread("zcash-shutoff"); + RenameThread("bitcoinz-shutoff"); mempool.AddTransactionsUpdated(1); StopHTTPRPC(); @@ -324,7 +328,7 @@ void OnRPCPreCommand(const CRPCCommand& cmd) { // Observe safe mode string strWarning = GetWarnings("rpc"); - if (strWarning != "" && !GetBoolArg("-disablesafemode", false) && + if (strWarning != "" && !GetBoolArg("-disablesafemode", DEFAULT_DISABLE_SAFEMODE) && !cmd.okSafeMode) throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, string("Safe mode: ") + strWarning); } @@ -341,60 +345,69 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-alerts", strprintf(_("Receive and display P2P network alerts (default: %u)"), DEFAULT_ALERTS)); strUsage += HelpMessageOpt("-alertnotify=", _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)")); strUsage += HelpMessageOpt("-blocknotify=", _("Execute command when the best block changes (%s in cmd is replaced by block hash)")); - strUsage += HelpMessageOpt("-checkblocks=", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), 288)); - strUsage += HelpMessageOpt("-checklevel=", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), 3)); - strUsage += HelpMessageOpt("-conf=", strprintf(_("Specify configuration file (default: %s)"), "bitcoinz.conf")); + strUsage += HelpMessageOpt("-checkblocks=", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), DEFAULT_CHECKBLOCKS)); + strUsage += HelpMessageOpt("-checklevel=", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), DEFAULT_CHECKLEVEL)); + strUsage += HelpMessageOpt("-conf=", strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME)); if (mode == HMM_BITCOIND) { -#if !defined(WIN32) +#ifndef WIN32 strUsage += HelpMessageOpt("-daemon", _("Run in the background as a daemon and accept commands")); #endif } strUsage += HelpMessageOpt("-datadir=", _("Specify data directory")); strUsage += HelpMessageOpt("-exportdir=", _("Specify directory to be used when exporting data")); strUsage += HelpMessageOpt("-dbcache=", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache)); - strUsage += HelpMessageOpt("-loadblock=", _("Imports blocks from external blk000??.dat file") + " " + _("on startup")); + strUsage += HelpMessageOpt("-loadblock=", _("Imports blocks from external blk000??.dat file on startup")); strUsage += HelpMessageOpt("-maxorphantx=", strprintf(_("Keep at most unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS)); - strUsage += HelpMessageOpt("-mempooltxinputlimit=", _("[DEPRECATED FROM OVERWINTER] Set the maximum number of transparent inputs in a transaction that the mempool will accept (default: 0 = no limit applied)")); strUsage += HelpMessageOpt("-par=", strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), -GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS)); #ifndef WIN32 - strUsage += HelpMessageOpt("-pid=", strprintf(_("Specify pid file (default: %s)"), "bitcoinz.pid")); + strUsage += HelpMessageOpt("-pid=", strprintf(_("Specify pid file (default: %s)"), BITCOIN_PID_FILENAME)); #endif strUsage += HelpMessageOpt("-prune=", strprintf(_("Reduce storage requirements by pruning (deleting) old blocks. This mode disables wallet support and is incompatible with -txindex. " "Warning: Reverting this setting requires re-downloading the entire blockchain. " "(default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files)"), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024)); - strUsage += HelpMessageOpt("-reindex", _("Rebuild block chain index from current blk000??.dat files on startup")); -#if !defined(WIN32) +#ifdef ENABLE_WALLET + strUsage += HelpMessageOpt("-reindex-chainstate", _("Rebuild chain state from the currently indexed blocks (implies -rescan)")); + strUsage += HelpMessageOpt("-reindex", _("Rebuild chain state and block index from the blk*.dat files on disk (implies -rescan)")); +#else + strUsage += HelpMessageOpt("-reindex-chainstate", _("Rebuild chain state from the currently indexed blocks")); + strUsage += HelpMessageOpt("-reindex", _("Rebuild chain state and block index from the blk*.dat files on disk")); +#endif +#ifndef WIN32 strUsage += HelpMessageOpt("-sysperms", _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)")); #endif - strUsage += HelpMessageOpt("-txindex", strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"), 0)); + strUsage += HelpMessageOpt("-txexpirynotify=", _("Execute command when transaction expires (%s in cmd is replaced by transaction id)")); + strUsage += HelpMessageOpt("-txindex", strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"), DEFAULT_TXINDEX)); strUsage += HelpMessageGroup(_("Connection options:")); strUsage += HelpMessageOpt("-addnode=", _("Add a node to connect to and attempt to keep the connection open")); - strUsage += HelpMessageOpt("-banscore=", strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), 100)); - strUsage += HelpMessageOpt("-bantime=", strprintf(_("Number of seconds to keep misbehaving peers from reconnecting (default: %u)"), 86400)); + strUsage += HelpMessageOpt("-banscore=", strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), DEFAULT_BANSCORE_THRESHOLD)); + strUsage += HelpMessageOpt("-bantime=", strprintf(_("Number of seconds to keep misbehaving peers from reconnecting (default: %u)"), DEFAULT_MISBEHAVING_BANTIME)); strUsage += HelpMessageOpt("-bind=", _("Bind to given address and always listen on it. Use [host]:port notation for IPv6")); - strUsage += HelpMessageOpt("-connect=", _("Connect only to the specified node(s)")); + strUsage += HelpMessageOpt("-connect=", _("Connect only to the specified node(s); -noconnect or -connect=0 alone to disable automatic connections")); strUsage += HelpMessageOpt("-discover", _("Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)")); - strUsage += HelpMessageOpt("-dns", _("Allow DNS lookups for -addnode, -seednode and -connect") + " " + _("(default: 1)")); - strUsage += HelpMessageOpt("-dnsseed", _("Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect)")); + strUsage += HelpMessageOpt("-dns", _("Allow DNS lookups for -addnode, -seednode and -connect") + " " + strprintf(_("(default: %u)"), DEFAULT_NAME_LOOKUP)); + strUsage += HelpMessageOpt("-dnsseed", _("Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect/-noconnect)")); strUsage += HelpMessageOpt("-externalip=", _("Specify your own public address")); - strUsage += HelpMessageOpt("-forcednsseed", strprintf(_("Always query for peer addresses via DNS lookup (default: %u)"), 0)); - strUsage += HelpMessageOpt("-listen", _("Accept connections from outside (default: 1 if no -proxy or -connect)")); + strUsage += HelpMessageOpt("-forcednsseed", strprintf(_("Always query for peer addresses via DNS lookup (default: %u)"), DEFAULT_FORCEDNSSEED)); + strUsage += HelpMessageOpt("-listen", _("Accept connections from outside (default: 1 if no -proxy or -connect/-noconnect)")); strUsage += HelpMessageOpt("-listenonion", strprintf(_("Automatically create Tor hidden service (default: %d)"), DEFAULT_LISTEN_ONION)); strUsage += HelpMessageOpt("-maxconnections=", strprintf(_("Maintain at most connections to peers (default: %u)"), DEFAULT_MAX_PEER_CONNECTIONS)); - strUsage += HelpMessageOpt("-maxreceivebuffer=", strprintf(_("Maximum per-connection receive buffer, *1000 bytes (default: %u)"), 5000)); - strUsage += HelpMessageOpt("-maxsendbuffer=", strprintf(_("Maximum per-connection send buffer, *1000 bytes (default: %u)"), 1000)); + strUsage += HelpMessageOpt("-maxreceivebuffer=", strprintf(_("Maximum per-connection receive buffer, *1000 bytes (default: %u)"), DEFAULT_MAXRECEIVEBUFFER)); + strUsage += HelpMessageOpt("-maxsendbuffer=", strprintf(_("Maximum per-connection send buffer, *1000 bytes (default: %u)"), DEFAULT_MAXSENDBUFFER)); + strUsage += HelpMessageOpt("-mempoolevictionmemoryminutes=", strprintf(_("The number of minutes before allowing rejected transactions to re-enter the mempool. (default: %u)"), DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES)); + strUsage += HelpMessageOpt("-mempooltxcostlimit=",strprintf(_("An upper bound on the maximum size in bytes of all transactions in the mempool. (default: %s)"), DEFAULT_MEMPOOL_TOTAL_COST_LIMIT)); strUsage += HelpMessageOpt("-onion=", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy")); strUsage += HelpMessageOpt("-onlynet=", _("Only connect to nodes in network (ipv4, ipv6 or onion)")); - strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), 1)); - strUsage += HelpMessageOpt("-peerbloomfilters", strprintf(_("Support filtering of blocks and transaction with Bloom filters (default: %u)"), 1)); + strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), DEFAULT_PERMIT_BAREMULTISIG)); + strUsage += HelpMessageOpt("-peerbloomfilters", strprintf(_("Support filtering of blocks and transaction with bloom filters (default: %u)"), DEFAULT_PEERBLOOMFILTERS)); if (showDebug) - strUsage += HelpMessageOpt("-enforcenodebloom", strprintf("Enforce minimum protocol version to limit use of Bloom filters (default: %u)", 0)); - strUsage += HelpMessageOpt("-port=", strprintf(_("Listen for connections on (default: %u or testnet: %u)"), 8233, 18233)); + strUsage += HelpMessageOpt("-enforcenodebloom", strprintf("Enforce minimum protocol version to limit use of bloom filters (default: %u)", DEFAULT_ENFORCENODEBLOOM)); + strUsage += HelpMessageOpt("-port=", strprintf(_("Listen for connections on (default: %u or testnet: %u)"), + Params(CBaseChainParams::MAIN).GetDefaultPort(), Params(CBaseChainParams::TESTNET).GetDefaultPort())); strUsage += HelpMessageOpt("-proxy=", _("Connect through SOCKS5 proxy")); - strUsage += HelpMessageOpt("-proxyrandomize", strprintf(_("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)"), 1)); + strUsage += HelpMessageOpt("-proxyrandomize", strprintf(_("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)"), DEFAULT_PROXYRANDOMIZE)); strUsage += HelpMessageOpt("-seednode=", _("Connect to a node to retrieve peer addresses, and disconnect")); strUsage += HelpMessageOpt("-timeout=", strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT)); strUsage += HelpMessageOpt("-torcontrol=:", strprintf(_("Tor control port to use if onion listening enabled (default: %s)"), DEFAULT_TOR_CONTROL)); @@ -404,30 +417,7 @@ std::string HelpMessage(HelpMessageMode mode) " " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway")); #ifdef ENABLE_WALLET - strUsage += HelpMessageGroup(_("Wallet options:")); - strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls")); - strUsage += HelpMessageOpt("-keypool=", strprintf(_("Set key pool size to (default: %u)"), 100)); - strUsage += HelpMessageOpt("-migration", _("Enable the Sprout to Sapling migration")); - strUsage += HelpMessageOpt("-migrationdestaddress=", _("Set the Sapling migration address")); - if (showDebug) - strUsage += HelpMessageOpt("-mintxfee=", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)", - CURRENCY_UNIT, FormatMoney(CWallet::minTxFee.GetFeePerK()))); - strUsage += HelpMessageOpt("-paytxfee=", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"), - CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK()))); - strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions") + " " + _("on startup")); - strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup")); - strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0)); - strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1)); - strUsage += HelpMessageOpt("-txconfirmtarget=", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET)); - strUsage += HelpMessageOpt("-txexpirydelta", strprintf(_("Set the number of blocks after which a transaction that has not been mined will become invalid (min: %u, default: %u (pre-Blossom) or %u (post-Blossom))"), TX_EXPIRING_SOON_THRESHOLD + 1, DEFAULT_PRE_BLOSSOM_TX_EXPIRY_DELTA, DEFAULT_POST_BLOSSOM_TX_EXPIRY_DELTA)); - strUsage += HelpMessageOpt("-maxtxfee=", strprintf(_("Maximum total fees (in %s) to use in a single wallet transaction; setting this too low may abort large transactions (default: %s)"), - CURRENCY_UNIT, FormatMoney(maxTxFee))); - strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format") + " " + _("on startup")); - strUsage += HelpMessageOpt("-wallet=", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), "wallet.dat")); - strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), true)); - strUsage += HelpMessageOpt("-walletnotify=", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)")); - strUsage += HelpMessageOpt("-zapwallettxes=", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") + - " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)")); + strUsage += CWallet::GetWalletHelpString(showDebug); #endif #if ENABLE_ZMQ @@ -449,50 +439,49 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageGroup(_("Debugging/Testing options:")); if (showDebug) { - strUsage += HelpMessageOpt("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", 1)); - strUsage += HelpMessageOpt("-dblogsize=", strprintf("Flush database activity from memory pool to disk log every megabytes (default: %u)", 100)); - strUsage += HelpMessageOpt("-disablesafemode", strprintf("Disable safemode, override a real safe mode event (default: %u)", 0)); - strUsage += HelpMessageOpt("-testsafemode", strprintf("Force safe mode (default: %u)", 0)); + strUsage += HelpMessageOpt("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED)); + strUsage += HelpMessageOpt("-disablesafemode", strprintf("Disable safemode, override a real safe mode event (default: %u)", DEFAULT_DISABLE_SAFEMODE)); + strUsage += HelpMessageOpt("-testsafemode", strprintf("Force safe mode (default: %u)", DEFAULT_TESTSAFEMODE)); strUsage += HelpMessageOpt("-dropmessagestest=", "Randomly drop 1 of every network messages"); strUsage += HelpMessageOpt("-fuzzmessagestest=", "Randomly fuzz 1 of every network messages"); - strUsage += HelpMessageOpt("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", 1)); - strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", 0)); + strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT)); strUsage += HelpMessageOpt("-nuparams=hexBranchId:activationHeight", "Use given activation height for specified network upgrade (regtest-only)"); } string debugCategories = "addrman, alert, bench, coindb, db, estimatefee, http, libevent, lock, mempool, net, partitioncheck, pow, proxy, prune, " "rand, reindex, rpc, selectcoins, tor, zmq, zrpc, zrpcunsafe (implies zrpc)"; // Don't translate these strUsage += HelpMessageOpt("-debug=", strprintf(_("Output debugging information (default: %u, supplying is optional)"), 0) + ". " + - _("If is not supplied or if = 1, output all debugging information.") + " " + _(" can be:") + " " + debugCategories + "."); + _("If is not supplied or if = 1, output all debugging information.") + " " + _(" can be:") + " " + debugCategories + ". " + + _("For multiple specific categories use -debug= multiple times.")); strUsage += HelpMessageOpt("-experimentalfeatures", _("Enable use of experimental features")); strUsage += HelpMessageOpt("-help-debug", _("Show all debugging options (usage: --help -help-debug)")); - strUsage += HelpMessageOpt("-logips", strprintf(_("Include IP addresses in debug output (default: %u)"), 0)); - strUsage += HelpMessageOpt("-logtimestamps", strprintf(_("Prepend debug output with timestamp (default: %u)"), 1)); + strUsage += HelpMessageOpt("-logips", strprintf(_("Include IP addresses in debug output (default: %u)"), DEFAULT_LOGIPS)); + strUsage += HelpMessageOpt("-logtimestamps", strprintf(_("Prepend debug output with timestamp (default: %u)"), DEFAULT_LOGTIMESTAMPS)); if (showDebug) { - strUsage += HelpMessageOpt("-limitfreerelay=", strprintf("Continuously rate-limit free transactions to *1000 bytes per minute (default: %u)", 15)); - strUsage += HelpMessageOpt("-relaypriority", strprintf("Require high priority for relaying free or low-fee transactions (default: %u)", 0)); + strUsage += HelpMessageOpt("-limitfreerelay=", strprintf("Continuously rate-limit free transactions to *1000 bytes per minute (default: %u)", DEFAULT_LIMITFREERELAY)); + strUsage += HelpMessageOpt("-relaypriority", strprintf("Require high priority for relaying free or low-fee transactions (default: %u)", DEFAULT_RELAYPRIORITY)); strUsage += HelpMessageOpt("-maxsigcachesize=", strprintf("Limit size of signature cache to MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE)); strUsage += HelpMessageOpt("-maxtipage=", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE)); } - strUsage += HelpMessageOpt("-minrelaytxfee=", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for relaying (default: %s)"), - CURRENCY_UNIT, FormatMoney(::minRelayTxFee.GetFeePerK()))); + strUsage += HelpMessageOpt("-minrelaytxfee=", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)"), + CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE))); + strUsage += HelpMessageOpt("-maxtxfee=", strprintf(_("Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)"), + CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MAXFEE))); strUsage += HelpMessageOpt("-printtoconsole", _("Send trace/debug info to console instead of debug.log file")); if (showDebug) { - strUsage += HelpMessageOpt("-printpriority", strprintf("Log transaction priority and fee per kB when mining blocks (default: %u)", 0)); - strUsage += HelpMessageOpt("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", 1)); - strUsage += HelpMessageOpt("-regtest", "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. " - "This is intended for regression testing tools and app development."); + strUsage += HelpMessageOpt("-printpriority", strprintf("Log transaction priority and fee per kB when mining blocks (default: %u)", DEFAULT_PRINTPRIORITY)); } - // strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)")); - strUsage += HelpMessageOpt("-testnet", _("Use the test network")); + strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)")); + + AppendParamsHelpMessages(strUsage, showDebug); strUsage += HelpMessageGroup(_("Node relay options:")); - strUsage += HelpMessageOpt("-datacarrier", strprintf(_("Relay and mine data carrier transactions (default: %u)"), 1)); + strUsage += HelpMessageOpt("-datacarrier", strprintf(_("Relay and mine data carrier transactions (default: %u)"), DEFAULT_ACCEPT_DATACARRIER)); strUsage += HelpMessageOpt("-datacarriersize", strprintf(_("Maximum size of data in data carrier transactions we relay and mine (default: %u)"), MAX_OP_RETURN_RELAY)); strUsage += HelpMessageGroup(_("Block creation options:")); - strUsage += HelpMessageOpt("-blockminsize=", strprintf(_("Set minimum block size in bytes (default: %u)"), 0)); + strUsage += HelpMessageOpt("-blockminsize=", strprintf(_("Set minimum block size in bytes (default: %u)"), DEFAULT_BLOCK_MIN_SIZE)); strUsage += HelpMessageOpt("-blockmaxsize=", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE)); strUsage += HelpMessageOpt("-blockprioritysize=", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE)); if (GetBoolArg("-help-debug", false)) @@ -500,8 +489,8 @@ std::string HelpMessage(HelpMessageMode mode) #ifdef ENABLE_MINING strUsage += HelpMessageGroup(_("Mining options:")); - strUsage += HelpMessageOpt("-gen", strprintf(_("Generate coins (default: %u)"), 0)); - strUsage += HelpMessageOpt("-genproclimit=", strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), 1)); + strUsage += HelpMessageOpt("-gen", strprintf(_("Generate coins (default: %u)"), DEFAULT_GENERATE)); + strUsage += HelpMessageOpt("-genproclimit=", strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), DEFAULT_GENERATE_THREADS)); strUsage += HelpMessageOpt("-equihashsolver=", _("Specify the Equihash solver to be used if enabled (default: \"default\")")); strUsage += HelpMessageOpt("-mineraddress=", _("Send mined coins to a specific single address")); strUsage += HelpMessageOpt("-minetolocalwallet", strprintf( @@ -516,10 +505,11 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageGroup(_("RPC server options:")); strUsage += HelpMessageOpt("-server", _("Accept command line and JSON-RPC commands")); - strUsage += HelpMessageOpt("-rest", strprintf(_("Accept public REST requests (default: %u)"), 0)); + strUsage += HelpMessageOpt("-rest", strprintf(_("Accept public REST requests (default: %u)"), DEFAULT_REST_ENABLE)); strUsage += HelpMessageOpt("-rpcbind=", _("Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces)")); strUsage += HelpMessageOpt("-rpcuser=", _("Username for JSON-RPC connections")); strUsage += HelpMessageOpt("-rpcpassword=", _("Password for JSON-RPC connections")); + strUsage += HelpMessageOpt("-rpcauth=", _("Username and hashed password for JSON-RPC connections. The field comes in the format: :$. A canonical python script is included in share/rpcuser. This option can be specified multiple times")); strUsage += HelpMessageOpt("-rpcport=", strprintf(_("Listen for JSON-RPC connections on (default: %u or testnet: %u)"), 8232, 18232)); strUsage += HelpMessageOpt("-rpcallowip=", _("Allow JSON-RPC connections from specified source. Valid for are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times")); strUsage += HelpMessageOpt("-rpcthreads=", strprintf(_("Set the number of threads to service RPC calls (default: %d)"), DEFAULT_HTTP_THREADS)); @@ -528,7 +518,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-rpcservertimeout=", strprintf("Timeout during HTTP requests (default: %d)", DEFAULT_HTTP_SERVER_TIMEOUT)); } - // Disabled until we can lock notes and also tune performance of libsnark which by default uses multiple threads + // Disabled until we can lock notes and also tune performance of the prover which by default uses multiple threads //strUsage += HelpMessageOpt("-rpcasyncthreads=", strprintf(_("Set the number of threads to service Async RPC calls (default: %d)"), 1)); if (mode == HMM_BITCOIND) { @@ -541,11 +531,22 @@ std::string HelpMessage(HelpMessageMode mode) return strUsage; } -static void BlockNotifyCallback(const uint256& hashNewTip) +static void BlockNotifyCallback(bool initialSync, const CBlockIndex *pBlockIndex) { + if (initialSync || !pBlockIndex) + return; + std::string strCmd = GetArg("-blocknotify", ""); - boost::replace_all(strCmd, "%s", hashNewTip.GetHex()); + boost::replace_all(strCmd, "%s", pBlockIndex->GetBlockHash().GetHex()); + boost::thread t(runCommand, strCmd); // thread runs free +} + +static void TxExpiryNotifyCallback(const uint256& txid) +{ + std::string strCmd = GetArg("-txexpirynotify", ""); + + boost::replace_all(strCmd, "%s", txid.GetHex()); boost::thread t(runCommand, strCmd); // thread runs free } @@ -596,7 +597,7 @@ void CleanupBlockRevFiles() // keeping a separate counter. Once we hit a gap (or if 0 doesn't exist) // start removing block files. int nContigCounter = 0; - BOOST_FOREACH(const PAIRTYPE(string, path)& item, mapBlockFiles) { + for (const std::pair& item : mapBlockFiles) { if (atoi(item.first) == nContigCounter) { nContigCounter++; continue; @@ -605,14 +606,134 @@ void CleanupBlockRevFiles() } } +void ThreadStartWalletNotifier() +{ + CBlockIndex *pindexLastTip; + + // If the wallet is compiled in and enabled, we want to start notifying + // from the block which corresponds with the wallet's view of the chain + // tip. In particular, we want to handle the case where the node shuts + // down uncleanly, and on restart the chain's tip is potentially up to + // an hour of chain sync older than the wallet's tip. We assume here + // that there is only a single wallet connected to the validation + // interface, which is currently true. +#ifdef ENABLE_WALLET + if (pwalletMain) + { + std::optional walletBestBlockHash; + if (!fReindex) { + LOCK(pwalletMain->cs_wallet); + walletBestBlockHash = pwalletMain->GetPersistedBestBlock(); + } + + if (walletBestBlockHash.has_value()) { + int64_t slept; + auto timedOut = [&]() -> bool { + MilliSleep(50); + slept += 50; + if (slept > WALLET_INITIAL_SYNC_TIMEOUT) { + auto errmsg = strprintf( + "The wallet's best block hash %s was not detected in restored chain state. " + "Giving up; please restart with `-rescan`.", + walletBestBlockHash.value().GetHex()); + + LogPrintf("*** %s: %s", __func__, errmsg); + uiInterface.ThreadSafeMessageBox( + _("Error: A fatal wallet synchronization error occurred, see debug.log for details"), + "", CClientUIInterface::MSG_ERROR); + StartShutdown(); + return true; + } + + return false; + }; + + // Wait until we've found the block that the wallet identifies as its + // best block. + while (true) { + boost::this_thread::interruption_point(); + + { + LOCK(cs_main); + BlockMap::iterator mi = mapBlockIndex.find(walletBestBlockHash.value()); + if (mi != mapBlockIndex.end()) { + pindexLastTip = (*mi).second; + assert(pindexLastTip != nullptr); + break; + } + } + + if (timedOut()) { + return; + } + } + + // We cannot progress with wallet notification until the chain tip is no + // more than 100 blocks behind pindexLastTip. This can occur if the node + // shuts down abruptly without being able to write out chainActive; the + // node writes chain data out roughly hourly, while the wallet writes it + // every 10 minutes. We need to wait for ThreadImport to catch up, or any + // missing blocks to be fetched from peers. + while (true) { + boost::this_thread::interruption_point(); + + { + LOCK(cs_main); + const CBlockIndex *pindexFork = chainActive.FindFork(pindexLastTip); + // We know we have the genesis block. + assert(pindexFork != nullptr); + + if (pindexLastTip->nHeight < pindexFork->nHeight || + pindexLastTip->nHeight - pindexFork->nHeight < 100) + { + break; + } + } + + if (timedOut()) { + return; + } + } + } + } else { + LOCK(cs_main); + pindexLastTip = chainActive.Tip(); + } +#else + { + LOCK(cs_main); + pindexLastTip = chainActive.Tip(); + } +#endif + + // Become the thread that notifies listeners of transactions that have been + // recently added to the mempool, or have been added to or removed from the + // chain. + ThreadNotifyWallets(pindexLastTip); +} + void ThreadImport(std::vector vImportFiles) { const CChainParams& chainparams = Params(); - RenameThread("zcash-loadblk"); + RenameThread("bitcoinz-loadblk"); + CImportingNow imp; + // -reindex if (fReindex) { - CImportingNow imp; + nSizeReindexed = 0; // will be modified inside LoadExternalBlockFile + // Find the summary size of all block files first int nFile = 0; + size_t fullSize = 0; + while (true) { + CDiskBlockPos pos(nFile, 0); + boost::filesystem::path blkFile = GetBlockPosFilename(pos, "blk"); + if (!boost::filesystem::exists(blkFile)) + break; // No block files left to reindex + nFile++; + fullSize += boost::filesystem::file_size(blkFile); + } + nFullSizeToReindex = std::max(1, fullSize); + nFile = 0; while (true) { CDiskBlockPos pos(nFile, 0); if (!boost::filesystem::exists(GetBlockPosFilename(pos, "blk"))) @@ -626,6 +747,8 @@ void ThreadImport(std::vector vImportFiles) } pblocktree->WriteReindexing(false); fReindex = false; + nSizeReindexed = 0; + nFullSizeToReindex = 1; LogPrintf("Reindexing finished\n"); // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked): InitBlockIndex(chainparams); @@ -636,7 +759,6 @@ void ThreadImport(std::vector vImportFiles) if (boost::filesystem::exists(pathBootstrap)) { FILE *file = fopen(pathBootstrap.string().c_str(), "rb"); if (file) { - CImportingNow imp; boost::filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; LogPrintf("Importing bootstrap.dat...\n"); LoadExternalBlockFile(chainparams, file); @@ -647,10 +769,9 @@ void ThreadImport(std::vector vImportFiles) } // -loadblock= - BOOST_FOREACH(const boost::filesystem::path& path, vImportFiles) { + for (const boost::filesystem::path& path : vImportFiles) { FILE *file = fopen(path.string().c_str(), "rb"); if (file) { - CImportingNow imp; LogPrintf("Importing blocks file %s...\n", path.string()); LoadExternalBlockFile(chainparams,file); } else { @@ -658,28 +779,17 @@ void ThreadImport(std::vector vImportFiles) } } - if (GetBoolArg("-stopafterblockimport", false)) { - LogPrintf("Stopping after block import\n"); + // scan for better chains in the block chain database, that are not yet connected in the active best chain + CValidationState state; + if (!ActivateBestChain(state, chainparams)) { + LogPrintf("Failed to connect best block"); StartShutdown(); } -} -bool InitExperimentalMode() -{ - fExperimentalMode = GetBoolArg("-experimentalfeatures", false); - // Fail if user has set experimental options without the global flag - if (!fExperimentalMode) { - if (mapArgs.count("-developerencryptwallet")) { - return InitError(_("Wallet encryption requires -experimentalfeatures.")); - } else if (mapArgs.count("-developersetpoolsizezero")) { - return InitError(_("Setting the size of shielded pools to zero requires -experimentalfeatures.")); - } else if (mapArgs.count("-paymentdisclosure")) { - return InitError(_("Payment disclosure requires -experimentalfeatures.")); - } else if (mapArgs.count("-insightexplorer")) { - return InitError(_("Insight explorer requires -experimentalfeatures.")); - } + if (GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) { + LogPrintf("Stopping after block import\n"); + StartShutdown(); } - return true; } /** Sanity checks @@ -706,15 +816,11 @@ static void ZC_LoadParams( struct timeval tv_start, tv_end; float elapsed; - boost::filesystem::path pk_path = ZC_GetParamsDir() / "sprout-proving.key"; - boost::filesystem::path vk_path = ZC_GetParamsDir() / "sprout-verifying.key"; boost::filesystem::path sapling_spend = ZC_GetParamsDir() / "sapling-spend.params"; boost::filesystem::path sapling_output = ZC_GetParamsDir() / "sapling-output.params"; boost::filesystem::path sprout_groth16 = ZC_GetParamsDir() / "sprout-groth16.params"; if (!( - boost::filesystem::exists(pk_path) && - boost::filesystem::exists(vk_path) && boost::filesystem::exists(sapling_spend) && boost::filesystem::exists(sapling_output) && boost::filesystem::exists(sprout_groth16) @@ -722,21 +828,14 @@ static void ZC_LoadParams( uiInterface.ThreadSafeMessageBox(strprintf( _("Cannot find the BitcoinZ network parameters in the following directory:\n" "%s\n" - "Please run 'zcash-fetch-params' or './zcutil/fetch-params.sh' and then restart."), + "Please run 'bitcoinz-fetch-params' or './zcutil/fetch-params.sh' and then restart."), ZC_GetParamsDir()), "", CClientUIInterface::MSG_ERROR); StartShutdown(); return; } - LogPrintf("Loading verifying key from %s\n", vk_path.string().c_str()); - gettimeofday(&tv_start, 0); - - pzcashParams = ZCJoinSplit::Prepared(vk_path.string(), pk_path.string()); - - gettimeofday(&tv_end, 0); - elapsed = float(tv_end.tv_sec-tv_start.tv_sec) + (tv_end.tv_usec-tv_start.tv_usec)/float(1000000); - LogPrintf("Loaded verifying key in %fs seconds.\n", elapsed); + pzcashParams = ZCJoinSplit::Prepared(); static_assert( sizeof(boost::filesystem::path::value_type) == sizeof(codeunit), @@ -777,13 +876,81 @@ bool AppInitServers(boost::thread_group& threadGroup) return false; if (!StartHTTPRPC()) return false; - if (GetBoolArg("-rest", false) && !StartREST()) + if (GetBoolArg("-rest", DEFAULT_REST_ENABLE) && !StartREST()) return false; if (!StartHTTPServer()) return false; return true; } +// Parameter interaction based on rules +void InitParameterInteraction() +{ + // when specifying an explicit binding address, you want to listen on it + // even when -connect or -proxy is specified + if (mapArgs.count("-bind")) { + if (SoftSetBoolArg("-listen", true)) + LogPrintf("%s: parameter interaction: -bind set -> setting -listen=1\n", __func__); + } + if (mapArgs.count("-whitebind")) { + if (SoftSetBoolArg("-listen", true)) + LogPrintf("%s: parameter interaction: -whitebind set -> setting -listen=1\n", __func__); + } + + if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0) { + // when only connecting to trusted nodes, do not seed via DNS, or listen by default + if (SoftSetBoolArg("-dnsseed", false)) + LogPrintf("%s: parameter interaction: -connect set -> setting -dnsseed=0\n", __func__); + if (SoftSetBoolArg("-listen", false)) + LogPrintf("%s: parameter interaction: -connect set -> setting -listen=0\n", __func__); + } + + if (mapArgs.count("-proxy")) { + // to protect privacy, do not listen by default if a default proxy server is specified + if (SoftSetBoolArg("-listen", false)) + LogPrintf("%s: parameter interaction: -proxy set -> setting -listen=0\n", __func__); + // to protect privacy, do not discover addresses by default + if (SoftSetBoolArg("-discover", false)) + LogPrintf("%s: parameter interaction: -proxy set -> setting -discover=0\n", __func__); + } + + if (!GetBoolArg("-listen", DEFAULT_LISTEN)) { + // do not try to retrieve public IP when not listening (pointless) + if (SoftSetBoolArg("-discover", false)) + LogPrintf("%s: parameter interaction: -listen=0 -> setting -discover=0\n", __func__); + if (SoftSetBoolArg("-listenonion", false)) + LogPrintf("%s: parameter interaction: -listen=0 -> setting -listenonion=0\n", __func__); + } + + if (mapArgs.count("-externalip")) { + // if an explicit public IP is specified, do not try to find others + if (SoftSetBoolArg("-discover", false)) + LogPrintf("%s: parameter interaction: -externalip set -> setting -discover=0\n", __func__); + } + + if (GetBoolArg("-salvagewallet", false)) { + // Rewrite just private keys: rescan to find transactions + if (SoftSetBoolArg("-rescan", true)) + LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__); + } + + // -zapwallettx implies a rescan + if (GetBoolArg("-zapwallettxes", false)) { + if (SoftSetBoolArg("-rescan", true)) + LogPrintf("%s: parameter interaction: -zapwallettxes= -> setting -rescan=1\n", __func__); + } +} + +void InitLogging() +{ + fPrintToConsole = GetBoolArg("-printtoconsole", false); + fLogTimestamps = GetBoolArg("-logtimestamps", true); + fLogIPs = GetBoolArg("-logips", false); + + LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + LogPrintf("BitcoinZ version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); +} + /** Initialize bitcoin. * @pre Parameters should be parsed and config file should be read. */ @@ -814,31 +981,33 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) #endif if (!SetupNetworking()) - return InitError("Error: Initializing networking failed"); + return InitError("Initializing networking failed"); #ifndef WIN32 if (GetBoolArg("-sysperms", false)) { #ifdef ENABLE_WALLET if (!GetBoolArg("-disablewallet", false)) - return InitError("Error: -sysperms is not allowed in combination with enabled wallet functionality"); + return InitError("-sysperms is not allowed in combination with enabled wallet functionality"); #endif } else { umask(077); } // Clean shutdown on SIGTERM + assert(fRequestShutdown.is_lock_free()); struct sigaction sa; sa.sa_handler = HandleSIGTERM; sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; + sa.sa_flags = SA_RESTART; sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); // Reopen debug.log on SIGHUP + assert(fReopenDebugLog.is_lock_free()); struct sigaction sa_hup; sa_hup.sa_handler = HandleSIGHUP; sigemptyset(&sa_hup.sa_mask); - sa_hup.sa_flags = 0; + sa_hup.sa_flags = SA_RESTART; sigaction(SIGHUP, &sa_hup, NULL); // Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly @@ -851,85 +1020,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) const CChainParams& chainparams = Params(); // Set this early so that experimental features are correctly enabled/disabled - fExperimentalMode = GetBoolArg("-experimentalfeatures", false); - - // Fail early if user has set experimental options without the global flag - if (!fExperimentalMode) { - if (mapArgs.count("-developerencryptwallet")) { - return InitError(_("Wallet encryption requires -experimentalfeatures.")); - } else if (mapArgs.count("-developersetpoolsizezero")) { - return InitError(_("Setting the size of shielded pools to zero requires -experimentalfeatures.")); - } else if (mapArgs.count("-paymentdisclosure")) { - return InitError(_("Payment disclosure requires -experimentalfeatures.")); - } else if (mapArgs.count("-zmergetoaddress")) { - return InitError(_("RPC method z_mergetoaddress requires -experimentalfeatures.")); - } else if (mapArgs.count("-savesproutr1cs")) { - return InitError(_("Saving the Sprout R1CS requires -experimentalfeatures.")); - } else if (mapArgs.count("-insightexplorer")) { - return InitError(_("Insight explorer requires -experimentalfeatures.")); - } - } - - // Set this early so that parameter interactions go to console - fPrintToConsole = GetBoolArg("-printtoconsole", false); - fLogTimestamps = GetBoolArg("-logtimestamps", true); - fLogIPs = GetBoolArg("-logips", false); - - LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); - LogPrintf("BitcoinZ version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); - - // when specifying an explicit binding address, you want to listen on it - // even when -connect or -proxy is specified - if (mapArgs.count("-bind")) { - if (SoftSetBoolArg("-listen", true)) - LogPrintf("%s: parameter interaction: -bind set -> setting -listen=1\n", __func__); - } - if (mapArgs.count("-whitebind")) { - if (SoftSetBoolArg("-listen", true)) - LogPrintf("%s: parameter interaction: -whitebind set -> setting -listen=1\n", __func__); - } - - if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0) { - // when only connecting to trusted nodes, do not seed via DNS, or listen by default - if (SoftSetBoolArg("-dnsseed", false)) - LogPrintf("%s: parameter interaction: -connect set -> setting -dnsseed=0\n", __func__); - if (SoftSetBoolArg("-listen", false)) - LogPrintf("%s: parameter interaction: -connect set -> setting -listen=0\n", __func__); - } - - if (mapArgs.count("-proxy")) { - // to protect privacy, do not listen by default if a default proxy server is specified - if (SoftSetBoolArg("-listen", false)) - LogPrintf("%s: parameter interaction: -proxy set -> setting -listen=0\n", __func__); - // to protect privacy, do not discover addresses by default - if (SoftSetBoolArg("-discover", false)) - LogPrintf("%s: parameter interaction: -proxy set -> setting -discover=0\n", __func__); - } - - if (!GetBoolArg("-listen", DEFAULT_LISTEN)) { - // do not try to retrieve public IP when not listening (pointless) - if (SoftSetBoolArg("-discover", false)) - LogPrintf("%s: parameter interaction: -listen=0 -> setting -discover=0\n", __func__); - if (SoftSetBoolArg("-listenonion", false)) - LogPrintf("%s: parameter interaction: -listen=0 -> setting -listenonion=0\n", __func__); - } - - if (mapArgs.count("-externalip")) { - // if an explicit public IP is specified, do not try to find others - if (SoftSetBoolArg("-discover", false)) - LogPrintf("%s: parameter interaction: -externalip set -> setting -discover=0\n", __func__); - } - - if (GetBoolArg("-salvagewallet", false)) { - // Rewrite just private keys: rescan to find transactions - if (SoftSetBoolArg("-rescan", true)) - LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__); - } - - // -zapwallettx implies a rescan - if (GetBoolArg("-zapwallettxes", false)) { - if (SoftSetBoolArg("-rescan", true)) - LogPrintf("%s: parameter interaction: -zapwallettxes= -> setting -rescan=1\n", __func__); + auto err = InitExperimentalMode(); + if (err) { + return InitError(err.value()); } // Make sure enough file descriptors are available @@ -944,7 +1037,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // if using block pruning, then disable txindex if (GetArg("-prune", 0)) { - if (GetBoolArg("-txindex", false)) + if (GetBoolArg("-txindex", DEFAULT_TXINDEX)) return InitError(_("Prune mode is incompatible with -txindex.")); #ifdef ENABLE_WALLET if (GetBoolArg("-rescan", false)) { @@ -972,24 +1065,29 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // Check for -debugnet if (GetBoolArg("-debugnet", false)) - InitWarning(_("Warning: Unsupported argument -debugnet ignored, use -debug=net.")); + InitWarning(_("Unsupported argument -debugnet ignored, use -debug=net.")); // Check for -socks - as this is a privacy risk to continue, exit here if (mapArgs.count("-socks")) - return InitError(_("Error: Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.")); + return InitError(_("Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.")); // Check for -tor - as this is a privacy risk to continue, exit here if (GetBoolArg("-tor", false)) - return InitError(_("Error: Unsupported argument -tor found, use -onion.")); + return InitError(_("Unsupported argument -tor found, use -onion.")); if (GetBoolArg("-benchmark", false)) - InitWarning(_("Warning: Unsupported argument -benchmark ignored, use -debug=bench.")); + InitWarning(_("Unsupported argument -benchmark ignored, use -debug=bench.")); // Checkmempool and checkblockindex default to true in regtest mode int ratio = std::min(std::max(GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000); if (ratio != 0) { mempool.setSanityCheck(1.0 / ratio); } + + int64_t mempoolTotalCostLimit = GetArg("-mempooltxcostlimit", DEFAULT_MEMPOOL_TOTAL_COST_LIMIT); + int64_t mempoolEvictionMemorySeconds = GetArg("-mempoolevictionmemoryminutes", DEFAULT_MEMPOOL_EVICTION_MEMORY_MINUTES) * 60; + mempool.SetMempoolCostLimit(mempoolTotalCostLimit, mempoolEvictionMemorySeconds); + fCheckBlockIndex = GetBoolArg("-checkblockindex", chainparams.DefaultConsistencyChecks()); - fCheckpointsEnabled = GetBoolArg("-checkpoints", true); + fCheckpointsEnabled = GetBoolArg("-checkpoints", DEFAULT_CHECKPOINTS_ENABLED); // -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency nScriptCheckThreads = GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS); @@ -1002,7 +1100,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fServer = GetBoolArg("-server", false); - // block pruning; get the amount of disk space (in MB) to allot for block & undo files + // block pruning; get the amount of disk space (in MiB) to allot for block & undo files int64_t nSignedPruneTarget = GetArg("-prune", 0) * 1024 * 1024; if (nSignedPruneTarget < 0) { return InitError(_("Prune cannot be configured with a negative value.")); @@ -1010,7 +1108,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) nPruneTarget = (uint64_t) nSignedPruneTarget; if (nPruneTarget) { if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) { - return InitError(strprintf(_("Prune configured below the minimum of %d MB. Please use a higher number."), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024)); + return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024)); } LogPrintf("Prune configured to target %uMiB on disk for block and undo files.\n", nPruneTarget / 1024 / 1024); fPruneMode = true; @@ -1043,66 +1141,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } #ifdef ENABLE_WALLET - if (mapArgs.count("-mintxfee")) - { - CAmount n = 0; - if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0) - CWallet::minTxFee = CFeeRate(n); - else - return InitError(strprintf(_("Invalid amount for -mintxfee=: '%s'"), mapArgs["-mintxfee"])); - } - if (mapArgs.count("-paytxfee")) - { - CAmount nFeePerK = 0; - if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK)) - return InitError(strprintf(_("Invalid amount for -paytxfee=: '%s'"), mapArgs["-paytxfee"])); - if (nFeePerK > nHighTransactionFeeWarning) - InitWarning(_("Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.")); - payTxFee = CFeeRate(nFeePerK, 1000); - if (payTxFee < ::minRelayTxFee) - { - return InitError(strprintf(_("Invalid amount for -paytxfee=: '%s' (must be at least %s)"), - mapArgs["-paytxfee"], ::minRelayTxFee.ToString())); - } - } - if (mapArgs.count("-maxtxfee")) - { - CAmount nMaxFee = 0; - if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee)) - return InitError(strprintf(_("Invalid amount for -maxtxfee=: '%s'"), mapArgs["-maptxfee"])); - if (nMaxFee > nHighTransactionMaxFeeWarning) - InitWarning(_("Warning: -maxtxfee is set very high! Fees this large could be paid on a single transaction.")); - maxTxFee = nMaxFee; - if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee) - { - return InitError(strprintf(_("Invalid amount for -maxtxfee=: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"), - mapArgs["-maxtxfee"], ::minRelayTxFee.ToString())); - } - } - nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET); - if (mapArgs.count("-txexpirydelta")) { - int64_t expiryDelta = atoi64(mapArgs["-txexpirydelta"]); - uint32_t minExpiryDelta = TX_EXPIRING_SOON_THRESHOLD + 1; - if (expiryDelta < minExpiryDelta) { - return InitError(strprintf(_("Invalid value for -txexpirydelta='%u' (must be least %u)"), expiryDelta, minExpiryDelta)); - } - expiryDeltaArg = expiryDelta; - } - bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", true); - fSendFreeTransactions = GetBoolArg("-sendfreetransactions", false); - - std::string strWalletFile = GetArg("-wallet", "wallet.dat"); - // Check Sapling migration address if set and is a valid Sapling address - if (mapArgs.count("-migrationdestaddress")) { - std::string migrationDestAddress = mapArgs["-migrationdestaddress"]; - libzcash::PaymentAddress address = DecodePaymentAddress(migrationDestAddress); - if (boost::get(&address) == nullptr) { - return InitError(_("-migrationdestaddress must be a valid Sapling address.")); - } - } + if (!CWallet::ParameterInteraction()) + return false; #endif // ENABLE_WALLET - fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", true); + fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG); + fAcceptDatacarrier = GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER); nMaxDatacarrierBytes = GetArg("-datacarriersize", nMaxDatacarrierBytes); fAlerts = GetBoolArg("-alerts", DEFAULT_ALERTS); @@ -1110,7 +1154,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // Option to startup with mocktime set (used for regression testing): SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op - if (GetBoolArg("-peerbloomfilters", true)) + if (GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS)) nLocalServices |= NODE_BLOOM; nMaxTipAge = GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE); @@ -1126,16 +1170,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } #endif - // Default value of 0 for mempooltxinputlimit means no limit is applied - if (mapArgs.count("-mempooltxinputlimit")) { - int64_t limit = GetArg("-mempooltxinputlimit", 0); - if (limit < 0) { - return InitError(_("Mempool limit on transparent inputs to a transaction cannot be negative")); - } else if (limit > 0) { - LogPrintf("Mempool configured to reject transactions with greater than %lld transparent inputs\n", limit); - } - } - if (!mapMultiArgs["-nuparams"].empty()) { // Allow overriding network upgrade parameters for testing if (Params().NetworkIDString() != "regtest") { @@ -1185,11 +1219,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError(_("Initialization sanity check failed. BitcoinZ is shutting down.")); std::string strDataDir = GetDataDir().string(); -#ifdef ENABLE_WALLET - // Wallet file must be a plain filename without a directory - if (strWalletFile != boost::filesystem::basename(strWalletFile) + boost::filesystem::extension(strWalletFile)) - return InitError(strprintf(_("Wallet %s resides outside data directory %s"), strWalletFile, strDataDir)); -#endif + // Make sure only a single Bitcoin process is using the data directory. boost::filesystem::path pathLockFile = GetDataDir() / ".lock"; FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist. @@ -1206,13 +1236,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) #ifndef WIN32 CreatePidFile(GetPidFile(), getpid()); #endif - // if (GetBoolArg("-shrinkdebugfile", !fDebug)) - // ShrinkDebugFile(); + if (GetBoolArg("-shrinkdebugfile", !fDebug)) + ShrinkDebugFile(); if (fPrintToDebugLog) OpenDebugLog(); - LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION)); #ifdef ENABLE_WALLET LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); #endif @@ -1220,7 +1249,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime())); LogPrintf("Default data directory %s\n", GetDefaultDataDir().string()); LogPrintf("Using data directory %s\n", strDataDir); - LogPrintf("Using config file %s\n", GetConfigFile().string()); + LogPrintf("Using config file %s\n", GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)).string()); LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD); std::ostringstream strErrors; @@ -1245,22 +1274,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) threadGroup.create_thread(&ThreadShowMetricsScreen); } - // These must be disabled for now, they are buggy and we probably don't - // want any of libsnark's profiling in production anyway. - libsnark::inhibit_profiling_info = true; - libsnark::inhibit_profiling_counters = true; - // Initialize BitcoinZ circuit parameters ZC_LoadParams(chainparams); - if (GetBoolArg("-savesproutr1cs", false)) { - boost::filesystem::path r1cs_path = ZC_GetParamsDir() / "r1cs"; - - LogPrintf("Saving Sprout R1CS to %s\n", r1cs_path.string()); - - pzcashParams->saveR1CS(r1cs_path.string()); - } - /* Start the RPC server already. It will be started in "warmup" mode * and not really process calls already (but it will signify connections * that the server is there and will be ready later). Warmup mode will @@ -1278,20 +1294,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 5: verify wallet database integrity #ifdef ENABLE_WALLET if (!fDisableWallet) { - LogPrintf("Using wallet %s\n", strWalletFile); - uiInterface.InitMessage(_("Verifying wallet...")); - - std::string warningString; - std::string errorString; - - if (!CWallet::Verify(strWalletFile, warningString, errorString)) + if (!CWallet::Verify()) return false; - - if (!warningString.empty()) - InitWarning(warningString); - if (!errorString.empty()) - return InitError(warningString); - } // (!fDisableWallet) #endif // ENABLE_WALLET // ********************************************************* Step 6: network initialization @@ -1300,7 +1304,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // sanitize comments per BIP-0014, format user agent and check total size std::vector uacomments; - BOOST_FOREACH(string cmt, mapMultiArgs["-uacomment"]) + for (string cmt : mapMultiArgs["-uacomment"]) { if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT)) return InitError(strprintf("User Agent comment (%s) contains unsafe characters.", cmt)); @@ -1314,7 +1318,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (mapArgs.count("-onlynet")) { std::set nets; - BOOST_FOREACH(const std::string& snet, mapMultiArgs["-onlynet"]) { + for (const std::string& snet : mapMultiArgs["-onlynet"]) { enum Network net = ParseNetwork(snet); if (net == NET_UNROUTABLE) return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet)); @@ -1328,7 +1332,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } if (mapArgs.count("-whitelist")) { - BOOST_FOREACH(const std::string& net, mapMultiArgs["-whitelist"]) { + for (const std::string& net : mapMultiArgs["-whitelist"]) { CSubNet subnet(net); if (!subnet.IsValid()) return InitError(strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net)); @@ -1336,7 +1340,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } } - bool proxyRandomize = GetBoolArg("-proxyrandomize", true); + bool proxyRandomize = GetBoolArg("-proxyrandomize", DEFAULT_PROXYRANDOMIZE); // -proxy sets a proxy for all outgoing network traffic // -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default std::string proxyArg = GetArg("-proxy", ""); @@ -1372,18 +1376,18 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // see Step 2: parameter interactions for more information about these fListen = GetBoolArg("-listen", DEFAULT_LISTEN); fDiscover = GetBoolArg("-discover", true); - fNameLookup = GetBoolArg("-dns", true); + fNameLookup = GetBoolArg("-dns", DEFAULT_NAME_LOOKUP); bool fBound = false; if (fListen) { if (mapArgs.count("-bind") || mapArgs.count("-whitebind")) { - BOOST_FOREACH(const std::string& strBind, mapMultiArgs["-bind"]) { + for (const std::string& strBind : mapMultiArgs["-bind"]) { CService addrBind; if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind)); fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR)); } - BOOST_FOREACH(const std::string& strBind, mapMultiArgs["-whitebind"]) { + for (const std::string& strBind : mapMultiArgs["-whitebind"]) { CService addrBind; if (!Lookup(strBind.c_str(), addrBind, 0, false)) return InitError(strprintf(_("Cannot resolve -whitebind address: '%s'"), strBind)); @@ -1403,7 +1407,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } if (mapArgs.count("-externalip")) { - BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-externalip"]) { + for (const std::string& strAddr : mapMultiArgs["-externalip"]) { CService addrLocal(strAddr, GetListenPort(), fNameLookup); if (!addrLocal.IsValid()) return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr)); @@ -1411,7 +1415,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } } - BOOST_FOREACH(const std::string& strDest, mapMultiArgs["-seednode"]) + for (const std::string& strDest : mapMultiArgs["-seednode"]) AddOneShot(strDest); #if ENABLE_ZMQ @@ -1429,7 +1433,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // AMQP support is currently an experimental feature, so fail if user configured AMQP notifications // without enabling experimental features. - if (!fExperimentalMode) { + if (!GetBoolArg("-experimentalfeatures", false)) { return InitError(_("AMQP support requires -experimentalfeatures.")); } @@ -1440,45 +1444,21 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 7: load block chain fReindex = GetBoolArg("-reindex", false); + bool fReindexChainState = GetBoolArg("-reindex-chainstate", false); - // Upgrading to 0.8; hard-link the old blknnnn.dat files into /blocks/ - boost::filesystem::path blocksDir = GetDataDir() / "blocks"; - if (!boost::filesystem::exists(blocksDir)) - { - boost::filesystem::create_directories(blocksDir); - bool linked = false; - for (unsigned int i = 1; i < 10000; i++) { - boost::filesystem::path source = GetDataDir() / strprintf("blk%04u.dat", i); - if (!boost::filesystem::exists(source)) break; - boost::filesystem::path dest = blocksDir / strprintf("blk%05u.dat", i-1); - try { - boost::filesystem::create_hard_link(source, dest); - LogPrintf("Hardlinked %s -> %s\n", source.string(), dest.string()); - linked = true; - } catch (const boost::filesystem::filesystem_error& e) { - // Note: hardlink creation failing is not a disaster, it just means - // blocks will get re-downloaded from peers. - LogPrintf("Error hardlinking blk%04u.dat: %s\n", i, e.what()); - break; - } - } - if (linked) - { - fReindex = true; - } - } + boost::filesystem::create_directories(GetDataDir() / "blocks"); // cache size calculations int64_t nTotalCache = (GetArg("-dbcache", nDefaultDbCache) << 20); nTotalCache = std::max(nTotalCache, nMinDbCache << 20); // total cache cannot be less than nMinDbCache - nTotalCache = std::min(nTotalCache, nMaxDbCache << 20); // total cache cannot be greated than nMaxDbcache + nTotalCache = std::min(nTotalCache, nMaxDbCache << 20); // total cache cannot be greater than nMaxDbcache int64_t nBlockTreeDBCache = nTotalCache / 8; - if (nBlockTreeDBCache > (1 << 21) && !GetBoolArg("-txindex", false)) + if (nBlockTreeDBCache > (1 << 21) && !GetBoolArg("-txindex", DEFAULT_TXINDEX)) nBlockTreeDBCache = (1 << 21); // block tree db cache shouldn't be larger than 2 MiB // https://github.com/bitpay/bitcoin/commit/c91d78b578a8700a45be936cb5bb0931df8f4b87#diff-c865a8939105e6350a50af02766291b7R1233 if (GetBoolArg("-insightexplorer", false)) { - if (!GetBoolArg("-txindex", false)) { + if (!GetBoolArg("-txindex", DEFAULT_TXINDEX)) { return InitError(_("-insightexplorer requires -txindex.")); } // increase cache if additional indices are needed @@ -1502,6 +1482,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) uiInterface.InitMessage(_("Loading block index...")); + LOCK(cs_main); + nStart = GetTimeMillis(); do { try { @@ -1512,7 +1494,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) delete pblocktree; pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex); - pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex); + pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex || fReindexChainState); pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview); pcoinsTip = new CCoinsViewCache(pcoinscatcher); @@ -1540,21 +1522,33 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } // Check for changed -txindex state - if (fTxIndex != GetBoolArg("-txindex", false)) { + if (fTxIndex != GetBoolArg("-txindex", DEFAULT_TXINDEX)) { + // TODO: Recommend `-reindex-chainstate` instead of + // `-reindex` after #5964 and/or #5977 are fixed. strLoadError = _("You need to rebuild the database using -reindex to change -txindex"); break; } // Check for changed -insightexplorer state - if (fInsightExplorer != GetBoolArg("-insightexplorer", false)) { + bool fInsightExplorerPreviouslySet = false; + pblocktree->ReadFlag("insightexplorer", fInsightExplorerPreviouslySet); + if (fExperimentalInsightExplorer != fInsightExplorerPreviouslySet) { strLoadError = _("You need to rebuild the database using -reindex to change -insightexplorer"); break; } + // Check for changed -lightwalletd state + bool fLightWalletdPreviouslySet = false; + pblocktree->ReadFlag("lightwalletd", fLightWalletdPreviouslySet); + if (fExperimentalLightWalletd != fLightWalletdPreviouslySet) { + strLoadError = _("You need to rebuild the database using -reindex to change -lightwalletd"); + break; + } + // Check for changed -prune state. What we are concerned about is a user who has pruned blocks // in the past, but is now trying to run unpruned. if (fHavePruned && !fPruneMode) { - strLoadError = _("You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain"); + strLoadError = _("You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain"); break; } @@ -1567,12 +1561,21 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } uiInterface.InitMessage(_("Verifying blocks...")); - if (fHavePruned && GetArg("-checkblocks", 288) > MIN_BLOCKS_TO_KEEP) { + if (fHavePruned && GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) { LogPrintf("Prune: pruned datadir may not have more than %d blocks; -checkblocks=%d may fail\n", - MIN_BLOCKS_TO_KEEP, GetArg("-checkblocks", 288)); + MIN_BLOCKS_TO_KEEP, GetArg("-checkblocks", DEFAULT_CHECKBLOCKS)); + } + + CBlockIndex* tip = chainActive.Tip(); + if (tip && tip->nTime > GetTime() + MAX_FUTURE_BLOCK_TIME) { + strLoadError = _("The block database contains a block which appears to be from the future. " + "This may be due to your computer's date and time being set incorrectly. " + "Only rebuild the block database if you are sure that your computer's date and time are correct"); + break; } - if (!CVerifyDB().VerifyDB(chainparams, pcoinsdbview, GetArg("-checklevel", 3), - GetArg("-checkblocks", 288))) { + + if (!CVerifyDB().VerifyDB(chainparams, pcoinsdbview, GetArg("-checklevel", DEFAULT_CHECKLEVEL), + GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) { strLoadError = _("Corrupted block database detected"); break; } @@ -1590,6 +1593,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (!fReset) { bool fRet = uiInterface.ThreadSafeQuestion( strLoadError + ".\n\n" + _("Do you want to rebuild the block database now?"), + // TODO: Recommend `-reindex or -reindex-chainstate` after + // #5964 and/or #5977 are fixed. strLoadError + ".\nPlease restart with -reindex to recover.", "", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT); if (fRet) { @@ -1629,165 +1634,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) pwalletMain = NULL; LogPrintf("Wallet disabled!\n"); } else { - - // needed to restore wallet transaction meta data after -zapwallettxes - std::vector vWtx; - - if (GetBoolArg("-zapwallettxes", false)) { - uiInterface.InitMessage(_("Zapping all transactions from wallet...")); - - pwalletMain = new CWallet(strWalletFile); - DBErrors nZapWalletRet = pwalletMain->ZapWalletTx(vWtx); - if (nZapWalletRet != DB_LOAD_OK) { - uiInterface.InitMessage(_("Error loading wallet.dat: Wallet corrupted")); - return false; - } - - delete pwalletMain; - pwalletMain = NULL; - } - - uiInterface.InitMessage(_("Loading wallet...")); - - nStart = GetTimeMillis(); - bool fFirstRun = true; - pwalletMain = new CWallet(strWalletFile); - DBErrors nLoadWalletRet = pwalletMain->LoadWallet(fFirstRun); - if (nLoadWalletRet != DB_LOAD_OK) - { - if (nLoadWalletRet == DB_CORRUPT) - strErrors << _("Error loading wallet.dat: Wallet corrupted") << "\n"; - else if (nLoadWalletRet == DB_NONCRITICAL_ERROR) - { - string msg(_("Warning: error reading wallet.dat! All keys read correctly, but transaction data" - " or address book entries might be missing or incorrect.")); - InitWarning(msg); - } - else if (nLoadWalletRet == DB_TOO_NEW) - strErrors << _("Error loading wallet.dat: Wallet requires newer version of BitcoinZ") << "\n"; - else if (nLoadWalletRet == DB_NEED_REWRITE) - { - strErrors << _("Wallet needed to be rewritten: restart BitcoinZ to complete") << "\n"; - LogPrintf("%s", strErrors.str()); - return InitError(strErrors.str()); - } - else - strErrors << _("Error loading wallet.dat") << "\n"; - } - - if (GetBoolArg("-upgradewallet", fFirstRun)) - { - int nMaxVersion = GetArg("-upgradewallet", 0); - if (nMaxVersion == 0) // the -upgradewallet without argument case - { - LogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST); - nMaxVersion = CLIENT_VERSION; - pwalletMain->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately - } - else - LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion); - if (nMaxVersion < pwalletMain->GetVersion()) - strErrors << _("Cannot downgrade wallet") << "\n"; - pwalletMain->SetMaxVersion(nMaxVersion); - } - - if (!pwalletMain->HaveHDSeed()) - { - // We can't set the new HD seed until the wallet is decrypted. - // https://github.com/zcash/zcash/issues/3607 - if (!pwalletMain->IsCrypted()) { - // generate a new HD seed - pwalletMain->GenerateNewSeed(); - } - } - - // Set sapling migration status - pwalletMain->fSaplingMigrationEnabled = GetBoolArg("-migration", false); - - if (fFirstRun) - { - // Create new keyUser and set as default key - CPubKey newDefaultKey; - if (pwalletMain->GetKeyFromPool(newDefaultKey)) { - pwalletMain->SetDefaultKey(newDefaultKey); - if (!pwalletMain->SetAddressBook(pwalletMain->vchDefaultKey.GetID(), "", "receive")) - strErrors << _("Cannot write default address") << "\n"; - } - - pwalletMain->SetBestChain(chainActive.GetLocator()); - } - - LogPrintf("%s", strErrors.str()); - LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart); - - RegisterValidationInterface(pwalletMain); - - CBlockIndex *pindexRescan = chainActive.Tip(); - if (clearWitnessCaches || GetBoolArg("-rescan", false)) - { - pwalletMain->ClearNoteWitnessCache(); - pindexRescan = chainActive.Genesis(); - } - else - { - CWalletDB walletdb(strWalletFile); - CBlockLocator locator; - if (walletdb.ReadBestBlock(locator)) - pindexRescan = FindForkInGlobalIndex(chainActive, locator); - else - pindexRescan = chainActive.Genesis(); - } - if (chainActive.Tip() && chainActive.Tip() != pindexRescan) - { - - // We can't rescan beyond non-pruned blocks, so stop and throw an error. - // This might happen if a user uses a old wallet within a pruned node, - // or if they ran -disablewallet for a longer time, then decided to re-enable. - if (fPruneMode) - { - CBlockIndex *block = chainActive.Tip(); - while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA) && block->pprev->nTx > 0 && pindexRescan != block) - block = block->pprev; - - if (pindexRescan != block) - return InitError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)")); - } - - uiInterface.InitMessage(_("Rescanning...")); - LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight); - nStart = GetTimeMillis(); - pwalletMain->ScanForWalletTransactions(pindexRescan, true); - LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); - pwalletMain->SetBestChain(chainActive.GetLocator()); - nWalletDBUpdated++; - - // Restore wallet transaction metadata after -zapwallettxes=1 - if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2") - { - CWalletDB walletdb(strWalletFile); - - BOOST_FOREACH(const CWalletTx& wtxOld, vWtx) - { - uint256 hash = wtxOld.GetHash(); - std::map::iterator mi = pwalletMain->mapWallet.find(hash); - if (mi != pwalletMain->mapWallet.end()) - { - const CWalletTx* copyFrom = &wtxOld; - CWalletTx* copyTo = &mi->second; - copyTo->mapValue = copyFrom->mapValue; - copyTo->vOrderForm = copyFrom->vOrderForm; - copyTo->nTimeReceived = copyFrom->nTimeReceived; - copyTo->nTimeSmart = copyFrom->nTimeSmart; - copyTo->fFromMe = copyFrom->fFromMe; - copyTo->strFromAccount = copyFrom->strFromAccount; - copyTo->nOrderPos = copyFrom->nOrderPos; - copyTo->WriteToDisk(&walletdb); - } - } - } - } - pwalletMain->SetBroadcastTransactions(GetBoolArg("-walletbroadcast", true)); - } // (!fDisableWallet) + CWallet::InitLoadWallet(clearWitnessCaches || fReindex); + if (!pwalletMain) + return false; + } #else // ENABLE_WALLET LogPrintf("No wallet support compiled in!\n"); #endif // !ENABLE_WALLET @@ -1808,7 +1658,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (pwalletMain) { // Address has already been validated CTxDestination addr = DecodeDestination(mapArgs["-mineraddress"]); - CKeyID keyID = boost::get(addr); + CKeyID keyID = std::get(addr); minerAddressInLocalWallet = pwalletMain->HaveKey(keyID); } if (GetBoolArg("-minetolocalwallet", true) && !minerAddressInLocalWallet) { @@ -1834,6 +1684,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } #endif // ENABLE_MINING + // Spawn a thread that will wait for the chain state needed for + // ThreadNotifyWallets to become available. + threadGroup.create_thread( + std::bind(&TraceThread, "txnotify", &ThreadStartWalletNotifier) + ); + // ********************************************************* Step 9: data directory maintenance // if pruning, unset the service bit and perform the initial blockstore prune @@ -1852,23 +1708,31 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (mapArgs.count("-blocknotify")) uiInterface.NotifyBlockTip.connect(BlockNotifyCallback); - uiInterface.InitMessage(_("Activating best chain...")); - // scan for better chains in the block chain database, that are not yet connected in the active best chain - CValidationState state; - if (!ActivateBestChain(state, chainparams)) - strErrors << "Failed to connect best block"; + if (mapArgs.count("-txexpirynotify")) + uiInterface.NotifyTxExpiration.connect(TxExpiryNotifyCallback); std::vector vImportFiles; if (mapArgs.count("-loadblock")) { - BOOST_FOREACH(const std::string& strFile, mapMultiArgs["-loadblock"]) + for (const std::string& strFile : mapMultiArgs["-loadblock"]) vImportFiles.push_back(strFile); } threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles)); - if (chainActive.Tip() == NULL) { - LogPrintf("Waiting for genesis block to be imported...\n"); - while (!fRequestShutdown && chainActive.Tip() == NULL) + + // Wait for genesis block to be processed + bool fHaveGenesis = false; + while (!fHaveGenesis && !fRequestShutdown) { + { + LOCK(cs_main); + fHaveGenesis = (chainActive.Tip() != NULL); + } + + if (!fHaveGenesis) { MilliSleep(10); + } + } + if (!fHaveGenesis) { + return false; } // ********************************************************* Step 11: start node @@ -1880,36 +1744,32 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError(strErrors.str()); //// debug print - LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size()); - LogPrintf("nBestHeight = %d\n", chainActive.Height()); + { + LOCK(cs_main); + LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size()); + LogPrintf("nBestHeight = %d\n", chainActive.Height()); + } #ifdef ENABLE_WALLET - LogPrintf("setKeyPool.size() = %u\n", pwalletMain ? pwalletMain->setKeyPool.size() : 0); - LogPrintf("mapWallet.size() = %u\n", pwalletMain ? pwalletMain->mapWallet.size() : 0); - LogPrintf("mapAddressBook.size() = %u\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0); + if (pwalletMain) + { + LOCK(pwalletMain->cs_wallet); + LogPrintf("setKeyPool.size() = %u\n", pwalletMain->setKeyPool.size()); + LogPrintf("mapWallet.size() = %u\n", pwalletMain->mapWallet.size()); + LogPrintf("mapAddressBook.size() = %u\n", pwalletMain->mapAddressBook.size()); + } #endif - // Start the thread that notifies listeners of transactions that have been - // recently added to the mempool. - // recently added to the mempool, or have been added to or removed from the - // chain. - threadGroup.create_thread(boost::bind(&TraceThread, "txnotify", &ThreadNotifyWallets)); - if (GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) StartTorControl(threadGroup, scheduler); StartNode(threadGroup, scheduler); - // Monitor the chain every minute, and alert if we get blocks much quicker or slower than expected. - //CScheduler::Function frecBlock = boost::bind(&PartitionCheck, &IsInitialBlockDownload, - // boost::ref(cs_main), boost::cref(pindexBestHeader)); - //scheduler.scheduleEvery(frecBlock, 60); - #ifdef ENABLE_MINING // Generate coins in the background - GenerateBitcoins(GetBoolArg("-gen", false), GetArg("-genproclimit", 1), chainparams); + GenerateBitcoins(GetBoolArg("-gen", DEFAULT_GENERATE), GetArg("-genproclimit", DEFAULT_GENERATE_THREADS), chainparams); #endif - // ********************************************************* Step 11: finished + // ********************************************************* Step 12: finished SetRPCWarmupFinished(); uiInterface.InitMessage(_("Done loading")); diff --git a/src/init.h b/src/init.h index 134620519..1f3b1aea2 100644 --- a/src/init.h +++ b/src/init.h @@ -18,7 +18,6 @@ namespace boost class thread_group; } // namespace boost -extern CWallet* pwalletMain; extern ZCJoinSplit* pzcashParams; void StartShutdown(); @@ -26,6 +25,10 @@ bool ShutdownRequested(); /** Interrupt threads */ void Interrupt(boost::thread_group& threadGroup); void Shutdown(); +//!Initialize the logging infrastructure +void InitLogging(); +//!Parameter interaction: change current parameters depending on various rules +void InitParameterInteraction(); bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler); /** The help message mode determines what help message to show */ diff --git a/src/key.cpp b/src/key.cpp index 3508b5e9d..6e693921d 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -219,7 +219,7 @@ bool CKey::VerifyPubKey(const CPubKey& pubkey) const { return false; } unsigned char rnd[8]; - std::string str = "Zcash key verification\n"; + std::string str = "BitcoinZ key verification\n"; GetRandBytes(rnd, sizeof(rnd)); uint256 hash; CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize(hash.begin()); diff --git a/src/key.h b/src/key.h index 762fd1ecb..623458752 100644 --- a/src/key.h +++ b/src/key.h @@ -108,14 +108,14 @@ class CKey //! Check whether the public key corresponding to this private key is (to be) compressed. bool IsCompressed() const { return fCompressed; } - //! Initialize from a CPrivKey (serialized OpenSSL private key data). + //! Initialize from a CPrivKey (serialized OpenSSL-format private key data). bool SetPrivKey(const CPrivKey& vchPrivKey, bool fCompressed); //! Generate a new private key using a cryptographic PRNG. void MakeNewKey(bool fCompressed); /** - * Convert the private key to a CPrivKey (serialized OpenSSL private key data). + * Convert the private key to a CPrivKey (serialized OpenSSL-format private key data). * This is expensive. */ CPrivKey GetPrivKey() const; diff --git a/src/key_io.cpp b/src/key_io.cpp index 4f41c16b8..5cc0c59e9 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -10,16 +10,13 @@ #include