aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml73
-rw-r--r--Makefile.am3
-rw-r--r--README.md2
-rw-r--r--configure.ac70
-rw-r--r--contrib/devtools/README.md23
-rwxr-xr-xcontrib/devtools/lint-includes.sh32
-rwxr-xr-xcontrib/gitian-build.sh1
-rw-r--r--contrib/init/README.md2
-rw-r--r--depends/README.md6
-rw-r--r--depends/description.md2
-rw-r--r--doc/README.md4
-rw-r--r--doc/README_osx.md10
-rw-r--r--doc/bips.md2
-rw-r--r--doc/build-freebsd.md46
-rw-r--r--doc/build-openbsd.md16
-rw-r--r--doc/build-osx.md6
-rw-r--r--doc/build-unix.md33
-rw-r--r--doc/build-windows.md41
-rw-r--r--doc/developer-notes.md4
-rw-r--r--doc/init.md6
-rw-r--r--doc/release-notes-pr10740.md11
-rw-r--r--doc/release-notes-pr12924.md12
-rw-r--r--doc/release-process.md26
-rw-r--r--src/Makefile.am30
-rw-r--r--src/Makefile.bench.include3
-rw-r--r--src/Makefile.qt.include2
-rw-r--r--src/Makefile.qttest.include2
-rw-r--r--src/Makefile.test.include9
-rw-r--r--src/bench/bench.h12
-rw-r--r--src/bench/bench_bitcoin.cpp49
-rw-r--r--src/bench/crypto_hash.cpp9
-rw-r--r--src/bench/merkle_root.cpp26
-rw-r--r--src/bitcoin-cli.cpp59
-rw-r--r--src/bitcoin-tx.cpp82
-rw-r--r--src/bitcoind.cpp21
-rw-r--r--src/chainparamsbase.cpp2
-rw-r--r--src/consensus/merkle.cpp133
-rw-r--r--src/consensus/merkle.h11
-rw-r--r--src/crypto/sha256.cpp498
-rw-r--r--src/crypto/sha256.h7
-rw-r--r--src/crypto/sha256_avx2.cpp329
-rw-r--r--src/crypto/sha256_sse41.cpp321
-rw-r--r--src/index/txindex.cpp4
-rw-r--r--src/init.cpp213
-rw-r--r--src/interfaces/node.cpp12
-rw-r--r--src/interfaces/node.h4
-rw-r--r--src/interfaces/wallet.cpp5
-rw-r--r--src/interfaces/wallet.h2
-rw-r--r--src/key.cpp2
-rw-r--r--src/key.h2
-rw-r--r--src/net_processing.cpp136
-rw-r--r--src/net_processing.h5
-rw-r--r--src/primitives/transaction.cpp10
-rw-r--r--src/primitives/transaction.h12
-rw-r--r--src/pubkey.h8
-rw-r--r--src/qt/README.md8
-rw-r--r--src/qt/bitcoin.cpp49
-rw-r--r--src/qt/bitcoinamountfield.cpp2
-rw-r--r--src/qt/bitcoingui.cpp11
-rw-r--r--src/qt/bitcoingui.h1
-rw-r--r--src/qt/rpcconsole.cpp9
-rw-r--r--src/qt/test/addressbooktests.cpp18
-rw-r--r--src/qt/test/wallettests.cpp24
-rw-r--r--src/qt/utilitydialog.cpp4
-rw-r--r--src/random.cpp1
-rw-r--r--src/rpc/blockchain.cpp312
-rw-r--r--src/rpc/client.cpp2
-rw-r--r--src/rpc/rawtransaction.cpp7
-rw-r--r--src/script/interpreter.cpp48
-rw-r--r--src/script/interpreter.h25
-rw-r--r--src/script/ismine.cpp96
-rw-r--r--src/script/ismine.h8
-rw-r--r--src/script/script.cpp5
-rw-r--r--src/script/script.h7
-rw-r--r--src/script/sign.cpp15
-rw-r--r--src/script/sign.h16
-rw-r--r--src/script/standard.cpp150
-rw-r--r--src/sync.cpp19
-rw-r--r--src/test/bip32_tests.cpp2
-rw-r--r--src/test/coins_tests.cpp4
-rw-r--r--src/test/crypto_tests.cpp16
-rw-r--r--src/test/getarg_tests.cpp16
-rw-r--r--src/test/merkle_tests.cpp117
-rw-r--r--src/test/script_standard_tests.cpp26
-rw-r--r--src/test/script_tests.cpp8
-rw-r--r--src/test/torcontrol_tests.cpp10
-rw-r--r--src/test/transaction_tests.cpp8
-rw-r--r--src/test/txvalidationcache_tests.cpp6
-rw-r--r--src/test/util_tests.cpp67
-rw-r--r--src/test/validation_block_tests.cpp6
-rw-r--r--src/torcontrol.cpp5
-rw-r--r--src/ui_interface.h3
-rw-r--r--src/util.cpp173
-rw-r--r--src/util.h36
-rw-r--r--src/validation.cpp46
-rw-r--r--src/validation.h2
-rw-r--r--src/wallet/coincontrol.h2
-rw-r--r--src/wallet/feebumper.cpp2
-rw-r--r--src/wallet/init.cpp51
-rw-r--r--src/wallet/rpcdump.cpp52
-rw-r--r--src/wallet/rpcwallet.cpp276
-rw-r--r--src/wallet/rpcwallet.h2
-rw-r--r--src/wallet/test/wallet_tests.cpp30
-rw-r--r--src/wallet/wallet.cpp140
-rw-r--r--src/wallet/wallet.h41
-rw-r--r--src/wallet/walletdb.cpp2
-rw-r--r--src/wallet/walletdb.h12
-rw-r--r--test/functional/README.md2
-rw-r--r--test/functional/data/rpc_getblockstats.json204
-rwxr-xr-xtest/functional/feature_help.py11
-rwxr-xr-xtest/functional/feature_includeconf.py19
-rwxr-xr-xtest/functional/p2p_invalid_tx.py9
-rwxr-xr-xtest/functional/rpc_getblockstats.py180
-rwxr-xr-xtest/functional/test_framework/test_framework.py8
-rwxr-xr-xtest/functional/test_runner.py1
-rwxr-xr-xtest/functional/wallet_dump.py4
-rwxr-xr-xtest/functional/wallet_hd.py15
-rwxr-xr-xtest/functional/wallet_keypool.py8
-rwxr-xr-xtest/functional/wallet_listreceivedby.py12
-rwxr-xr-xtest/functional/wallet_multiwallet.py23
-rw-r--r--test/lint/README.md29
-rwxr-xr-xtest/lint/check-doc.py (renamed from contrib/devtools/check-doc.py)0
-rwxr-xr-xtest/lint/check-rpc-mappings.py (renamed from contrib/devtools/check-rpc-mappings.py)0
-rwxr-xr-xtest/lint/commit-script-check.sh (renamed from contrib/devtools/commit-script-check.sh)0
-rwxr-xr-xtest/lint/git-subtree-check.sh (renamed from contrib/devtools/git-subtree-check.sh)0
-rwxr-xr-xtest/lint/lint-all.sh (renamed from contrib/devtools/lint-all.sh)0
-rwxr-xr-xtest/lint/lint-include-guards.sh (renamed from contrib/devtools/lint-include-guards.sh)0
-rwxr-xr-xtest/lint/lint-includes.sh100
-rwxr-xr-xtest/lint/lint-logs.sh (renamed from contrib/devtools/lint-logs.sh)0
-rwxr-xr-xtest/lint/lint-python-shebang.sh (renamed from contrib/devtools/lint-python-shebang.sh)0
-rwxr-xr-xtest/lint/lint-python.sh (renamed from contrib/devtools/lint-python.sh)0
-rwxr-xr-xtest/lint/lint-shell.sh (renamed from contrib/devtools/lint-shell.sh)0
-rwxr-xr-xtest/lint/lint-tests.sh (renamed from contrib/devtools/lint-tests.sh)0
-rwxr-xr-xtest/lint/lint-whitespace.sh (renamed from contrib/devtools/lint-whitespace.sh)0
134 files changed, 3755 insertions, 1319 deletions
diff --git a/.travis.yml b/.travis.yml
index af5553f3b7..7cbe0b83f1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,58 +19,62 @@ env:
- CCACHE_SIZE=100M
- CCACHE_TEMPDIR=/tmp/.ccache-temp
- CCACHE_COMPRESS=1
+ - CCACHE_DIR=$HOME/.ccache
- BASE_OUTDIR=$TRAVIS_BUILD_DIR/out
- SDK_URL=https://bitcoincore.org/depends-sources/sdks
- WINEDEBUG=fixme-all
+ - DOCKER_PACKAGES="build-essential libtool autotools-dev automake pkg-config bsdmainutils curl git ca-certificates ccache"
matrix:
# ARM
- HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports"
# Win32
- - HOST=i686-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-i686 wine1.6" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports"
+ - HOST=i686-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-i686 wine-binfmt wine32" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports"
# Win64
- - HOST=x86_64-w64-mingw32 DPKG_ADD_ARCH="i386" DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine1.6" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports"
+ - HOST=x86_64-w64-mingw32 DEP_OPTS="NO_QT=1" PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine-binfmt wine64" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-reduce-exports"
# 32-bit + dash
- - HOST=i686-pc-linux-gnu PACKAGES="g++-multilib python3-zmq" DEP_OPTS="NO_QT=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" USE_SHELL="/bin/dash"
+ - HOST=i686-pc-linux-gnu PACKAGES="g++-multilib python3-zmq" DEP_OPTS="NO_QT=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++" CONFIG_SHELL="/bin/dash"
# x86_64 Linux (uses qt5 dev package instead of depends Qt to speed up build and avoid timeout)
- - HOST=x86_64-unknown-linux-gnu PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools protobuf-compiler libdbus-1-dev libharfbuzz-dev" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER"
+ - HOST=x86_64-unknown-linux-gnu PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools protobuf-compiler libdbus-1-dev libharfbuzz-dev libprotobuf-dev" DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports CPPFLAGS=-DDEBUG_LOCKORDER"
# Qt4 & system libs
- - HOST=x86_64-unknown-linux-gnu PACKAGES="python3-zmq qt4-dev-tools libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libdb5.1++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev xvfb" NO_DEPENDS=1 NEED_XVFB=1 RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --enable-glibc-back-compat --enable-reduce-exports --with-gui=qt4 CPPFLAGS=-DDEBUG_LOCKORDER"
+ - HOST=x86_64-unknown-linux-gnu PACKAGES="python3-zmq qt4-dev-tools libssl1.0-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev xvfb libqt4-dev" NO_DEPENDS=1 NEED_XVFB=1 RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --enable-glibc-back-compat --enable-reduce-exports --with-gui=qt4 CPPFLAGS=-DDEBUG_LOCKORDER" DISPLAY=:99.0
# x86_64 Linux, No wallet
- HOST=x86_64-unknown-linux-gnu PACKAGES="python3" DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports"
# Cross-Mac
- - HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports --enable-werror" OSX_SDK=10.11 GOAL="deploy"
+ - HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev python3-setuptools-git" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports --enable-werror" OSX_SDK=10.11 GOAL="deploy"
before_install:
- export PATH=$(echo $PATH | tr ':' "\n" | sed '/\/opt\/python/d' | tr "\n" ":" | sed "s|::|:|g")
install:
- - if [ -n "$DPKG_ADD_ARCH" ]; then sudo dpkg --add-architecture "$DPKG_ADD_ARCH" ; 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
+ - env | grep -E '^(CCACHE_|WINEDEBUG|DISPLAY|BOOST_TEST_RANDOM|CONFIG_SHELL)' | tee /tmp/env
+ - if [[ $HOST = *-mingw32 ]]; then DOCKER_ADMIN="--cap-add SYS_ADMIN"; fi
+ - DOCKER_ID=$(docker run $DOCKER_ADMIN -idt --mount type=bind,src=$TRAVIS_BUILD_DIR,dst=$TRAVIS_BUILD_DIR --mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR -w $TRAVIS_BUILD_DIR --env-file /tmp/env ubuntu:18.04)
+ - DOCKER_EXEC () { docker exec $DOCKER_ID bash -c "cd $PWD && $*"; }
+ - if [ -n "$DPKG_ADD_ARCH" ]; then DOCKER_EXEC dpkg --add-architecture "$DPKG_ADD_ARCH" ; fi
+ - travis_retry DOCKER_EXEC apt-get update
+ - travis_retry DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES $DOCKER_PACKAGES
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
- - if [ -z "$NO_DEPENDS" ]; then make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS; fi
+ - if [[ $HOST = *-mingw32 ]]; then DOCKER_EXEC update-alternatives --set $HOST-g++ \$\(which $HOST-g++-posix\); fi
+ - if [ -z "$NO_DEPENDS" ]; then DOCKER_EXEC CONFIG_SHELL= make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS; fi
# Start xvfb if needed, as documented at https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-xvfb-to-Run-Tests-That-Require-a-GUI
- - if [ "$NEED_XVFB" = 1 ]; then export DISPLAY=:99.0; /sbin/start-stop-daemon --start --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac; fi
+ - if [ "$NEED_XVFB" = 1 ]; then DOCKER_EXEC /sbin/start-stop-daemon --start --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac; fi
script:
- export TRAVIS_COMMIT_LOG=`git log --format=fuller -1`
- - 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"
- - if [ -z "$NO_DEPENDS" ]; then ccache --max-size=$CCACHE_SIZE; fi
- - test -n "$USE_SHELL" && eval '"$USE_SHELL" -c "./autogen.sh"' || ./autogen.sh
+ - if [ -z "$NO_DEPENDS" ]; then DOCKER_EXEC ccache --max-size=$CCACHE_SIZE; fi
+ - test -n "$CONFIG_SHELL" && DOCKER_EXEC "$CONFIG_SHELL" -c "./autogen.sh" || DOCKER_EXEC ./autogen.sh
- mkdir build && cd build
- - ../configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false)
- - make distdir VERSION=$HOST
+ - DOCKER_EXEC ../configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false)
+ - DOCKER_EXEC make distdir 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 travis_wait 50 make $MAKEJOBS check VERBOSE=1; fi
+ - DOCKER_EXEC ./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false)
+ - DOCKER_EXEC make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && DOCKER_EXEC make $GOAL V=1 ; false )
+ - if [ "$RUN_TESTS" = "true" ]; then DOCKER_EXEC LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib make $MAKEJOBS check VERBOSE=1; fi
- if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then extended="--extended --exclude feature_pruning,feature_dbcrash"; fi
- - if [ "$RUN_TESTS" = "true" ]; then test/functional/test_runner.py --combinedlogslen=4000 --coverage --quiet --failfast ${extended}; fi
+ - if [ "$RUN_TESTS" = "true" ]; then DOCKER_EXEC test/functional/test_runner.py --combinedlogslen=4000 --coverage --quiet --failfast ${extended}; fi
after_script:
- echo $TRAVIS_COMMIT_RANGE
- echo $TRAVIS_COMMIT_LOG
@@ -79,23 +83,26 @@ jobs:
include:
- stage: lint
sudo: false
+ cache: false
addons:
apt:
packages:
- python3-pip
- shellcheck
install:
- - if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then travis_retry pip3 install flake8 --user; fi
+ - travis_retry pip3 install flake8 --user
before_script:
- git fetch --unshallow
- - if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then contrib/devtools/commit-script-check.sh $TRAVIS_COMMIT_RANGE; fi
- - contrib/devtools/git-subtree-check.sh src/crypto/ctaes
- - contrib/devtools/git-subtree-check.sh src/secp256k1
- - contrib/devtools/git-subtree-check.sh src/univalue
- - contrib/devtools/git-subtree-check.sh src/leveldb
- - contrib/devtools/check-doc.py
- - contrib/devtools/check-rpc-mappings.py .
- - if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then contrib/devtools/lint-all.sh; fi
script:
- - if [ "$TRAVIS_REPO_SLUG" = "bitcoin/bitcoin" -a "$TRAVIS_PULL_REQUEST" = "false" ]; then while read LINE; do travis_retry gpg --keyserver hkp://subset.pool.sks-keyservers.net --recv-keys $LINE; done < contrib/verify-commits/trusted-keys; fi
- - if [ "$TRAVIS_REPO_SLUG" = "bitcoin/bitcoin" -a "$TRAVIS_EVENT_TYPE" = "cron" ]; then travis_wait 30 contrib/verify-commits/verify-commits.sh; fi
+ - if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then test/lint/commit-script-check.sh $TRAVIS_COMMIT_RANGE; fi
+ - test/lint/git-subtree-check.sh src/crypto/ctaes
+ - test/lint/git-subtree-check.sh src/secp256k1
+ - test/lint/git-subtree-check.sh src/univalue
+ - test/lint/git-subtree-check.sh src/leveldb
+ - test/lint/check-doc.py
+ - test/lint/check-rpc-mappings.py .
+ - test/lint/lint-all.sh
+ - if [ "$TRAVIS_REPO_SLUG" = "bitcoin/bitcoin" -a "$TRAVIS_EVENT_TYPE" = "cron" ]; then
+ while read LINE; do travis_retry gpg --keyserver hkp://subset.pool.sks-keyservers.net --recv-keys $LINE; done < contrib/verify-commits/trusted-keys &&
+ travis_wait 30 contrib/verify-commits/verify-commits.sh;
+ fi
diff --git a/Makefile.am b/Makefile.am
index 8a8debb079..0ed3dd289a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -294,5 +294,6 @@ clean-docs:
rm -rf doc/doxygen
clean-local: clean-docs
- rm -rf coverage_percent.txt test_bitcoin.coverage/ total.coverage/ test/tmp/ cache/ $(OSX_APP) src/qt/moc_*
+ rm -rf coverage_percent.txt test_bitcoin.coverage/ total.coverage/ test/tmp/ cache/ $(OSX_APP)
rm -rf test/functional/__pycache__ test/functional/test_framework/__pycache__ test/cache
+
diff --git a/README.md b/README.md
index acdbe46104..4e830109c2 100644
--- a/README.md
+++ b/README.md
@@ -52,7 +52,7 @@ There are also [regression and integration tests](/test), written
in Python, that are run automatically on the build server.
These tests can be run (if the [test dependencies](/test) are installed) with: `test/functional/test_runner.py`
-The Travis CI system makes sure that every pull request is built for Windows, Linux, and OS X, and that unit/sanity tests are run automatically.
+The Travis CI system makes sure that every pull request is built for Windows, Linux, and macOS, and that unit/sanity tests are run automatically.
### Manual Quality Assurance (QA) Testing
diff --git a/configure.ac b/configure.ac
index 95acd2bd86..af60b28c71 100644
--- a/configure.ac
+++ b/configure.ac
@@ -291,27 +291,29 @@ if test "x$enable_werror" = "xyes"; then
fi
if test "x$CXXFLAGS_overridden" = "xno"; then
- AX_CHECK_COMPILE_FLAG([-Wall],[CXXFLAGS="$CXXFLAGS -Wall"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wextra],[CXXFLAGS="$CXXFLAGS -Wextra"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wformat],[CXXFLAGS="$CXXFLAGS -Wformat"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wvla],[CXXFLAGS="$CXXFLAGS -Wvla"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wformat-security],[CXXFLAGS="$CXXFLAGS -Wformat-security"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wthread-safety-analysis],[CXXFLAGS="$CXXFLAGS -Wthread-safety-analysis"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wall],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wall"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wextra],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wextra"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wformat],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wformat"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wvla],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wvla"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wformat-security],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wformat-security"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wthread-safety-analysis],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wthread-safety-analysis"],,[[$CXXFLAG_WERROR]])
## Some compilers (gcc) ignore unknown -Wno-* options, but warn about all
## unknown options if any other warning is produced. Test the -Wfoo case, and
## set the -Wno-foo case if it works.
- AX_CHECK_COMPILE_FLAG([-Wunused-parameter],[CXXFLAGS="$CXXFLAGS -Wno-unused-parameter"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wself-assign],[CXXFLAGS="$CXXFLAGS -Wno-self-assign"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wunused-local-typedef],[CXXFLAGS="$CXXFLAGS -Wno-unused-local-typedef"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wdeprecated-register],[CXXFLAGS="$CXXFLAGS -Wno-deprecated-register"],,[[$CXXFLAG_WERROR]])
- AX_CHECK_COMPILE_FLAG([-Wimplicit-fallthrough],[CXXFLAGS="$CXXFLAGS -Wno-implicit-fallthrough"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wunused-parameter],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-unused-parameter"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wself-assign],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-self-assign"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wunused-local-typedef],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-unused-local-typedef"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wdeprecated-register],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-deprecated-register"],,[[$CXXFLAG_WERROR]])
+ AX_CHECK_COMPILE_FLAG([-Wimplicit-fallthrough],[NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-implicit-fallthrough"],,[[$CXXFLAG_WERROR]])
fi
# Check for optional instruction set support. Enabling these does _not_ imply that all code will
# be compiled with them, rather that specific objects/libs may use them after checking for runtime
# compatibility.
AX_CHECK_COMPILE_FLAG([-msse4.2],[[SSE42_CXXFLAGS="-msse4.2"]],,[[$CXXFLAG_WERROR]])
+AX_CHECK_COMPILE_FLAG([-msse4.1],[[SSE41_CXXFLAGS="-msse4.1"]],,[[$CXXFLAG_WERROR]])
+AX_CHECK_COMPILE_FLAG([-mavx -mavx2],[[AVX2_CXXFLAGS="-mavx -mavx2"]],,[[$CXXFLAG_WERROR]])
TEMP_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $SSE42_CXXFLAGS"
@@ -335,6 +337,44 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
)
CXXFLAGS="$TEMP_CXXFLAGS"
+TEMP_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS $SSE41_CXXFLAGS"
+AC_MSG_CHECKING(for SSE4.1 intrinsics)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <stdint.h>
+ #if defined(_MSC_VER)
+ #include <immintrin.h>
+ #elif defined(__GNUC__)
+ #include <x86intrin.h>
+ #endif
+ ]],[[
+ __m128i l = _mm_set1_epi32(0);
+ return _mm_extract_epi32(l, 3);
+ ]])],
+ [ AC_MSG_RESULT(yes); enable_sse41=yes; AC_DEFINE(ENABLE_SSE41, 1, [Define this symbol to build code that uses SSE4.1 intrinsics]) ],
+ [ AC_MSG_RESULT(no)]
+)
+CXXFLAGS="$TEMP_CXXFLAGS"
+
+TEMP_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS $AVX2_CXXFLAGS"
+AC_MSG_CHECKING(for AVX2 intrinsics)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <stdint.h>
+ #if defined(_MSC_VER)
+ #include <immintrin.h>
+ #elif defined(__GNUC__) && defined(__AVX2__)
+ #include <x86intrin.h>
+ #endif
+ ]],[[
+ __m256i l = _mm256_set1_epi32(0);
+ return _mm256_extract_epi32(l, 7);
+ ]])],
+ [ AC_MSG_RESULT(yes); enable_avx2=yes; AC_DEFINE(ENABLE_AVX2, 1, [Define this symbol to build code that uses AVX2 intrinsics]) ],
+ [ AC_MSG_RESULT(no)]
+)
+CXXFLAGS="$TEMP_CXXFLAGS"
+
CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS"
AC_ARG_WITH([utils],
@@ -1253,6 +1293,8 @@ 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([ENABLE_HWCRC32],[test x$enable_hwcrc32 = xyes])
+AM_CONDITIONAL([ENABLE_SSE41],[test x$enable_sse41 = xyes])
+AM_CONDITIONAL([ENABLE_AVX2],[test x$enable_avx2 = xyes])
AM_CONDITIONAL([USE_ASM],[test x$use_asm = xyes])
AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version])
@@ -1281,6 +1323,8 @@ AC_SUBST(BITCOIN_TX_NAME)
AC_SUBST(RELDFLAGS)
AC_SUBST(DEBUG_CPPFLAGS)
+AC_SUBST(WARN_CXXFLAGS)
+AC_SUBST(NOWARN_CXXFLAGS)
AC_SUBST(DEBUG_CXXFLAGS)
AC_SUBST(ERROR_CXXFLAGS)
AC_SUBST(GPROF_CXXFLAGS)
@@ -1293,6 +1337,8 @@ AC_SUBST(PIE_FLAGS)
AC_SUBST(SANITIZER_CXXFLAGS)
AC_SUBST(SANITIZER_LDFLAGS)
AC_SUBST(SSE42_CXXFLAGS)
+AC_SUBST(SSE41_CXXFLAGS)
+AC_SUBST(AVX2_CXXFLAGS)
AC_SUBST(LIBTOOL_APP_LDFLAGS)
AC_SUBST(USE_UPNP)
AC_SUBST(USE_QRCODE)
@@ -1392,7 +1438,7 @@ echo " CC = $CC"
echo " CFLAGS = $CFLAGS"
echo " CPPFLAGS = $DEBUG_CPPFLAGS $HARDENED_CPPFLAGS $CPPFLAGS"
echo " CXX = $CXX"
-echo " CXXFLAGS = $DEBUG_CXXFLAGS $HARDENED_CXXFLAGS $ERROR_CXXFLAGS $GPROF_CXXFLAGS $CXXFLAGS"
+echo " CXXFLAGS = $DEBUG_CXXFLAGS $HARDENED_CXXFLAGS $WARN_CXXFLAGS $NOWARN_CXXFLAGS $ERROR_CXXFLAGS $GPROF_CXXFLAGS $CXXFLAGS"
echo " LDFLAGS = $PTHREAD_CFLAGS $HARDENED_LDFLAGS $GPROF_LDFLAGS $LDFLAGS"
echo " ARFLAGS = $ARFLAGS"
echo
diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md
index 7ac8aa39d3..a0b6225345 100644
--- a/contrib/devtools/README.md
+++ b/contrib/devtools/README.md
@@ -2,12 +2,6 @@ Contents
========
This directory contains tools for developers working on this repository.
-check-doc.py
-============
-
-Check if all command line args are documented. The return value indicates the
-number of undocumented args.
-
clang-format-diff.py
===================
@@ -93,23 +87,6 @@ example:
BUILDDIR=$PWD/build contrib/devtools/gen-manpages.sh
```
-git-subtree-check.sh
-====================
-
-Run this script from the root of the repository to verify that a subtree matches the contents of
-the commit it claims to have been updated to.
-
-To use, make sure that you have fetched the upstream repository branch in which the subtree is
-maintained:
-* for `src/secp256k1`: https://github.com/bitcoin-core/secp256k1.git (branch master)
-* for `src/leveldb`: https://github.com/bitcoin-core/leveldb.git (branch bitcoin-fork)
-* for `src/univalue`: https://github.com/bitcoin-core/univalue.git (branch master)
-* for `src/crypto/ctaes`: https://github.com/bitcoin-core/ctaes.git (branch master)
-
-Usage: `git-subtree-check.sh DIR (COMMIT)`
-
-`COMMIT` may be omitted, in which case `HEAD` is used.
-
github-merge.py
===============
diff --git a/contrib/devtools/lint-includes.sh b/contrib/devtools/lint-includes.sh
deleted file mode 100755
index f54be46b52..0000000000
--- a/contrib/devtools/lint-includes.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/bash
-#
-# Copyright (c) 2018 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#
-# Check for duplicate includes.
-
-filter_suffix() {
- git ls-files | grep -E "^src/.*\.${1}"'$' | grep -Ev "/(leveldb|secp256k1|univalue)/"
-}
-
-EXIT_CODE=0
-for HEADER_FILE in $(filter_suffix h); do
- DUPLICATE_INCLUDES_IN_HEADER_FILE=$(grep -E "^#include " < "${HEADER_FILE}" | sort | uniq -d)
- if [[ ${DUPLICATE_INCLUDES_IN_HEADER_FILE} != "" ]]; then
- echo "Duplicate include(s) in ${HEADER_FILE}:"
- echo "${DUPLICATE_INCLUDES_IN_HEADER_FILE}"
- echo
- EXIT_CODE=1
- fi
-done
-for CPP_FILE in $(filter_suffix cpp); do
- DUPLICATE_INCLUDES_IN_CPP_FILE=$(grep -E "^#include " < "${CPP_FILE}" | sort | uniq -d)
- if [[ ${DUPLICATE_INCLUDES_IN_CPP_FILE} != "" ]]; then
- echo "Duplicate include(s) in ${CPP_FILE}:"
- echo "${DUPLICATE_INCLUDES_IN_CPP_FILE}"
- echo
- EXIT_CODE=1
- fi
-done
-exit ${EXIT_CODE}
diff --git a/contrib/gitian-build.sh b/contrib/gitian-build.sh
index 94d6a89c7b..5a925f2282 100755
--- a/contrib/gitian-build.sh
+++ b/contrib/gitian-build.sh
@@ -1,3 +1,4 @@
+#!/bin/bash
# Copyright (c) 2016 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/contrib/init/README.md b/contrib/init/README.md
index 1a949f3c07..8d3e57c526 100644
--- a/contrib/init/README.md
+++ b/contrib/init/README.md
@@ -5,7 +5,7 @@ Upstart: bitcoind.conf
OpenRC: bitcoind.openrc
bitcoind.openrcconf
CentOS: bitcoind.init
-OS X: org.bitcoin.bitcoind.plist
+macOS: org.bitcoin.bitcoind.plist
```
have been made available to assist packagers in creating node packages here.
diff --git a/depends/README.md b/depends/README.md
index 99eef1952c..482b94a64f 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-darwin11` for macOS
- `arm-linux-gnueabihf` for Linux ARM 32 bit
- `aarch64-linux-gnu` for Linux ARM 64 bit
@@ -49,7 +49,7 @@ The following can be set when running make: make FOO=bar
SOURCES_PATH: downloaded sources will be placed here
BASE_CACHE: built packages will be placed here
- SDK_PATH: Path where sdk's can be found (used by OSX)
+ SDK_PATH: Path where sdk's can be found (used by macOS)
FALLBACK_DOWNLOAD_PATH: If a source file can't be fetched, try here before giving up
NO_QT: Don't download/build/cache qt and its dependencies
NO_WALLET: Don't download/build/cache libs needed to enable the wallet
@@ -64,7 +64,7 @@ options will be passed to bitcoin's configure. In this case, `--disable-wallet`.
Additional targets:
download: run 'make download' to fetch all sources without building them
- download-osx: run 'make download-osx' to fetch all sources needed for osx builds
+ download-osx: run 'make download-osx' to fetch all sources needed for macOS builds
download-win: run 'make download-win' to fetch all sources needed for win builds
download-linux: run 'make download-linux' to fetch all sources needed for linux builds
diff --git a/depends/description.md b/depends/description.md
index 74f9ef3f20..9fc7093be4 100644
--- a/depends/description.md
+++ b/depends/description.md
@@ -7,7 +7,7 @@ In theory, binaries for any target OS/architecture can be created, from a
builder running any OS/architecture. In practice, build-side tools must be
specified when the defaults don't fit, and packages must be amended to work
on new hosts. For now, a build architecture of x86_64 is assumed, either on
-Linux or OSX.
+Linux or macOS.
### No reliance on timestamps
diff --git a/doc/README.md b/doc/README.md
index ddb239f60c..45762b2374 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -22,7 +22,7 @@ Unpack the files into a directory and run:
Unpack the files into a directory, and then run bitcoin-qt.exe.
-### OS X
+### macOS
Drag Bitcoin-Core to your applications folder, and then run Bitcoin-Core.
@@ -38,7 +38,7 @@ Building
The following are developer notes on how to build Bitcoin on your native platform. They are not complete guides, but include notes on the necessary libraries, compile flags, etc.
- [Dependencies](dependencies.md)
-- [OS X Build Notes](build-osx.md)
+- [macOS Build Notes](build-osx.md)
- [Unix Build Notes](build-unix.md)
- [Windows Build Notes](build-windows.md)
- [OpenBSD Build Notes](build-openbsd.md)
diff --git a/doc/README_osx.md b/doc/README_osx.md
index 975be4be9e..739e22d634 100644
--- a/doc/README_osx.md
+++ b/doc/README_osx.md
@@ -1,12 +1,12 @@
-Deterministic OS X DMG Notes.
+Deterministic macOS DMG Notes.
-Working OS X DMGs are created in Linux by combining a recent clang,
+Working macOS DMGs are created in Linux by combining a recent clang,
the Apple binutils (ld, ar, etc) and DMG authoring tools.
Apple uses clang extensively for development and has upstreamed the necessary
functionality so that a vanilla clang can take advantage. It supports the use
of -F, -target, -mmacosx-version-min, and --sysroot, which are all necessary
-when building for OS X.
+when building for macOS.
Apple's version of binutils (called cctools) contains lots of functionality
missing in the FSF's binutils. In addition to extra linker options for
@@ -38,7 +38,7 @@ Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.1
Unfortunately, the usual linux tools (7zip, hpmount, loopback mount) are incapable of opening this file.
To create a tarball suitable for Gitian input, there are two options:
-Using Mac OS X, you can mount the dmg, and then create it with:
+Using macOS, you can mount the dmg, and then create it with:
```
$ hdiutil attach Xcode_7.3.1.dmg
$ tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.11.sdk.tar.gz MacOSX10.11.sdk
@@ -81,7 +81,7 @@ Background images and other features can be added to DMG files by inserting a
.DS_Store before creation. This is generated by the script
contrib/macdeploy/custom_dsstore.py.
-As of OS X Mavericks (10.9), using an Apple-blessed key to sign binaries is a
+As of OS X 10.9 Mavericks, using an Apple-blessed key to sign binaries is a
requirement in order to satisfy the new Gatekeeper requirements. Because this
private key cannot be shared, we'll have to be a bit creative in order for the
build process to remain somewhat deterministic. Here's how it works:
diff --git a/doc/bips.md b/doc/bips.md
index 5b8eabd6df..272cf4de29 100644
--- a/doc/bips.md
+++ b/doc/bips.md
@@ -15,7 +15,7 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.16.0**):
* [`BIP 35`](https://github.com/bitcoin/bips/blob/master/bip-0035.mediawiki): The 'mempool' protocol message (and the protocol version bump to 60002) has been implemented since **v0.7.0** ([PR #1641](https://github.com/bitcoin/bitcoin/pull/1641)).
* [`BIP 37`](https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki): The bloom filtering for transaction relaying, partial merkle trees for blocks, and the protocol version bump to 70001 (enabling low-bandwidth SPV clients) has been implemented since **v0.8.0** ([PR #1795](https://github.com/bitcoin/bitcoin/pull/1795)).
* [`BIP 42`](https://github.com/bitcoin/bips/blob/master/bip-0042.mediawiki): The bug that would have caused the subsidy schedule to resume after block 13440000 was fixed in **v0.9.2** ([PR #3842](https://github.com/bitcoin/bitcoin/pull/3842)).
-* [`BIP 61`](https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki): The 'reject' protocol message (and the protocol version bump to 70002) was added in **v0.9.0** ([PR #3185](https://github.com/bitcoin/bitcoin/pull/3185)).
+* [`BIP 61`](https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki): The 'reject' protocol message (and the protocol version bump to 70002) was added in **v0.9.0** ([PR #3185](https://github.com/bitcoin/bitcoin/pull/3185)). Starting *v0.17.0*, whether to send reject messages can be configured with the `-enablebip61` option.
* [`BIP 65`](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki): The CHECKLOCKTIMEVERIFY softfork was merged in **v0.12.0** ([PR #6351](https://github.com/bitcoin/bitcoin/pull/6351)), and backported to **v0.11.2** and **v0.10.4**. Mempool-only CLTV was added in [PR #6124](https://github.com/bitcoin/bitcoin/pull/6124).
* [`BIP 66`](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki): The strict DER rules and associated version 3 blocks have been implemented since **v0.10.0** ([PR #5713](https://github.com/bitcoin/bitcoin/pull/5713)).
* [`BIP 68`](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki): Sequence locks have been implemented as of **v0.12.1** ([PR #7184](https://github.com/bitcoin/bitcoin/pull/7184)), and have been activated since *block 419328*.
diff --git a/doc/build-freebsd.md b/doc/build-freebsd.md
new file mode 100644
index 0000000000..c2e4e36dff
--- /dev/null
+++ b/doc/build-freebsd.md
@@ -0,0 +1,46 @@
+FreeBSD build guide
+======================
+(updated for FreeBSD 11.1)
+
+This guide describes how to build bitcoind and command-line utilities on FreeBSD.
+
+This guide does not contain instructions for building the GUI.
+
+## Preparation
+
+You will need the following dependencies, which can be installed as root via pkg:
+
+```
+pkg install autoconf automake boost-libs git gmake libevent libtool openssl pkgconf
+```
+
+For the wallet (optional):
+```
+./contrib/install_db4.sh `pwd`
+export BDB_PREFIX='$PWD/db4'
+```
+
+See [dependencies.md](dependencies.md) for a complete overview.
+
+Download the source code:
+```
+git clone https://github.com/bitcoin/bitcoin
+```
+
+## Building Bitcoin Core
+
+**Important**: Use `gmake` (the non-GNU `make` will exit with an error).
+
+```
+./autogen.sh
+
+./configure # to build with wallet OR
+./configure --disable-wallet # to build without wallet
+
+gmake
+```
+
+*Note on debugging*: The version of `gdb` installed by default is [ancient and considered harmful](https://wiki.freebsd.org/GdbRetirement).
+It is not suitable for debugging a multi-threaded C++ program, not even for getting backtraces. Please install the package `gdb` and
+use the versioned gdb command (e.g. `gdb7111`).
+
diff --git a/doc/build-openbsd.md b/doc/build-openbsd.md
index 0817821221..63288acf16 100644
--- a/doc/build-openbsd.md
+++ b/doc/build-openbsd.md
@@ -1,6 +1,6 @@
OpenBSD build guide
======================
-(updated for OpenBSD 6.2)
+(updated for OpenBSD 6.3)
This guide describes how to build bitcoind and command-line utilities on OpenBSD.
@@ -12,11 +12,10 @@ Preparation
Run the following as root to install the base dependencies for building:
```bash
-pkg_add git gmake libevent libtool
+pkg_add git gmake libevent libtool boost
pkg_add autoconf # (select highest version, e.g. 2.69)
pkg_add automake # (select highest version, e.g. 1.15)
pkg_add python # (select highest version, e.g. 3.6)
-pkg_add boost
git clone https://github.com/bitcoin/bitcoin.git
```
@@ -55,8 +54,15 @@ export BDB_PREFIX="$PWD/db4"
Preparation:
```bash
-export AUTOCONF_VERSION=2.69 # replace this with the autoconf version that you installed
-export AUTOMAKE_VERSION=1.15 # replace this with the automake version that you installed
+
+# Replace this with the autoconf version that you installed. Include only
+# the major and minor parts of the version: use "2.69" for "autoconf-2.69p2".
+export AUTOCONF_VERSION=2.69
+
+# Replace this with the automake version that you installed. Include only
+# the major and minor parts of the version: use "1.15" for "automake-1.15.1".
+export AUTOMAKE_VERSION=1.15
+
./autogen.sh
```
Make sure `BDB_PREFIX` is set to the appropriate path from the above steps.
diff --git a/doc/build-osx.md b/doc/build-osx.md
index e52a770ced..abd305cf9a 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -1,11 +1,11 @@
-Mac OS X Build Instructions and Notes
+macOS Build Instructions and Notes
====================================
The commands in this guide should be executed in a Terminal application.
The built-in one is located in `/Applications/Utilities/Terminal.app`.
Preparation
-----------
-Install the OS X command line tools:
+Install the macOS command line tools:
`xcode-select --install`
@@ -93,6 +93,6 @@ Other commands:
Notes
-----
-* Tested on OS X 10.8 through 10.13 on 64-bit Intel processors only.
+* Tested on OS X 10.8 Mountain Lion through macOS 10.13 High Sierra on 64-bit Intel processors only.
* Building with downloaded Qt binaries is not officially supported. See the notes in [#7714](https://github.com/bitcoin/bitcoin/issues/7714)
diff --git a/doc/build-unix.md b/doc/build-unix.md
index 2d10484a65..60d888a297 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -2,8 +2,7 @@ UNIX BUILD NOTES
====================
Some notes on how to build Bitcoin Core in Unix.
-(For BSD specific instructions, see [build-openbsd.md](build-openbsd.md) and/or
-[build-netbsd.md](build-netbsd.md))
+(For BSD specific instructions, see `build-*bsd.md` in this directory.)
Note
---------------------
@@ -303,33 +302,3 @@ To build executables for ARM:
For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory.
-Building on FreeBSD
---------------------
-
-(Updated as of FreeBSD 11.0)
-
-Clang is installed by default as `cc` compiler, this makes it easier to get
-started than on [OpenBSD](build-openbsd.md). Installing dependencies:
-
- pkg install autoconf automake libtool pkgconf
- pkg install boost-libs openssl libevent
- pkg install gmake
-
-You need to use GNU make (`gmake`) instead of `make`.
-(`libressl` instead of `openssl` will also work)
-
-For the wallet (optional):
-
- ./contrib/install_db4.sh `pwd`
- setenv BDB_PREFIX $PWD/db4
-
-Then build using:
-
- ./autogen.sh
- ./configure --disable-wallet # OR
- ./configure BDB_CFLAGS="-I${BDB_PREFIX}/include" BDB_LIBS="-L${BDB_PREFIX}/lib -ldb_cxx"
- gmake
-
-*Note on debugging*: The version of `gdb` installed by default is [ancient and considered harmful](https://wiki.freebsd.org/GdbRetirement).
-It is not suitable for debugging a multi-threaded C++ program, not even for getting backtraces. Please install the package `gdb` and
-use the versioned gdb command e.g. `gdb7111`.
diff --git a/doc/build-windows.md b/doc/build-windows.md
index 07bb0c096a..935e29ce1c 100644
--- a/doc/build-windows.md
+++ b/doc/build-windows.md
@@ -5,7 +5,7 @@ Below are some notes on how to build Bitcoin Core for Windows.
The options known to work for building Bitcoin Core on Windows are:
-* On Linux using the [Mingw-w64](https://mingw-w64.org/doku.php) cross compiler tool chain. Ubuntu Trusty 14.04 is recommended
+* On Linux using the [Mingw-w64](https://mingw-w64.org/doku.php) cross compiler tool chain. Ubuntu Bionic 18.04 is required
and is the platform used to build the Bitcoin Core Windows release binaries.
* On Windows using [Windows
Subsystem for Linux (WSL)](https://msdn.microsoft.com/commandline/wsl/about) and the Mingw-w64 cross compiler tool chain.
@@ -38,10 +38,10 @@ To install WSL on Windows 10 with Fall Creators Update installed (version >= 162
* Enable 'Windows Subsystem for Linux'
* Click 'OK' and restart if necessary
2. Install Ubuntu
- * Open Microsoft Store and search for Ubuntu or use [this link](https://www.microsoft.com/store/productId/9NBLGGH4MSV6)
+ * Open Microsoft Store and search for "Ubuntu 18.04" or use [this link](https://www.microsoft.com/store/productId/9N9TNGVNDL3Q)
* Click Install
3. Complete Installation
- * Open a cmd prompt and type "Ubuntu"
+ * Open a cmd prompt and type "Ubuntu1804"
* Create a new UNIX user account (this is a separate account from your Windows account)
After the bash shell is active, you can follow the instructions below, starting
@@ -51,11 +51,6 @@ recommended but it is possible to compile the 32-bit version.
Cross-compilation for Ubuntu and Windows Subsystem for Linux
------------------------------------------------------------
-At the time of writing the Windows Subsystem for Linux installs Ubuntu Xenial 16.04. The Mingw-w64 package
-for Ubuntu Xenial does not produce working executables for some of the Bitcoin Core applications.
-It is possible to build on Ubuntu Xenial by installing the cross compiler packages from Ubuntu Artful, see the steps below.
-Building on Ubuntu Artful 17.10 has been verified to work.
-
The steps below can be performed on Ubuntu (including in a VM) or WSL. The depends system
will also work on other Linux distributions, however the commands for
installing the toolchain will be different.
@@ -74,26 +69,11 @@ See also: [dependencies.md](dependencies.md).
## Building for 64-bit Windows
-The first step is to install the mingw-w64 cross-compilation tool chain. Due to different Ubuntu
-packages for each distribution and problems with the Xenial packages the steps for each are different.
-
-Common steps to install mingw32 cross compiler tool chain:
+The first step is to install the mingw-w64 cross-compilation tool chain.
sudo apt install g++-mingw-w64-x86-64
-Ubuntu Trusty 14.04:
-
- No further steps required
-
-Ubuntu Xenial 16.04 and Windows Subsystem for Linux <sup>[1](#footnote1),[2](#footnote2)</sup>:
-
- sudo apt install software-properties-common
- sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu artful universe"
- sudo apt update
- sudo apt upgrade
- sudo update-alternatives --config x86_64-w64-mingw32-g++ # Set the default mingw32 g++ compiler option to posix.
-
-Ubuntu Artful 17.10 <sup>[2](#footnote2)</sup>:
+Ubuntu Bionic 18.04 <sup>[1](#footnote1)</sup>:
sudo update-alternatives --config x86_64-w64-mingw32-g++ # Set the default mingw32 g++ compiler option to posix.
@@ -123,7 +103,7 @@ To build executables for Windows 32-bit, install the following dependencies:
sudo apt install g++-mingw-w64-i686 mingw-w64-i686-dev
-For Ubuntu Xenial 16.04, Ubuntu Artful 17.10 and Windows Subsystem for Linux <sup>[2](#footnote2)</sup>:
+For Ubuntu Bionic 18.04 and Windows Subsystem for Linux <sup>[1](#footnote1)</sup>:
sudo update-alternatives --config i686-w64-mingw32-g++ # Set the default mingw32 g++ compiler option to posix.
@@ -162,14 +142,7 @@ way. This will install to `c:\workspace\bitcoin`, for example:
Footnotes
---------
-<a name="footnote1">1</a>: There is currently a bug in the 64 bit Mingw-w64 cross compiler packaged for WSL/Ubuntu Xenial 16.04 that
-causes two of the bitcoin executables to crash shortly after start up. The bug is related to the
--fstack-protector-all g++ compiler flag which is used to mitigate buffer overflows.
-Installing the Mingw-w64 packages from the Ubuntu 17.10 distribution solves the issue, however, this is not
-an officially supported approach and it's only recommended if you are prepared to reinstall WSL/Ubuntu should
-something break.
-
-<a name="footnote2">2</a>: Starting from Ubuntu Xenial 16.04 both the 32 and 64 bit Mingw-w64 packages install two different
+<a name="footnote1">1</a>: Starting from Ubuntu Xenial 16.04 both the 32 and 64 bit Mingw-w64 packages install two different
compiler options to allow a choice between either posix or win32 threads. The default option is win32 threads which is the more
efficient since it will result in binary code that links directly with the Windows kernel32.lib. Unfortunately, the headers
required to support win32 threads conflict with some of the classes in the C++11 standard library in particular std::mutex.
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 1f237b750e..9081cab911 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -647,7 +647,7 @@ Others are external projects without a tight relationship with our project. Cha
be sent upstream but bugfixes may also be prudent to PR against Bitcoin Core so that they can be integrated
quickly. Cosmetic changes should be purely taken upstream.
-There is a tool in contrib/devtools/git-subtree-check.sh to check a subtree directory for consistency with
+There is a tool in `test/lint/git-subtree-check.sh` to check a subtree directory for consistency with
its upstream repository.
Current subtrees include:
@@ -778,7 +778,7 @@ To create a scripted-diff:
- `-BEGIN VERIFY SCRIPT-`
- `-END VERIFY SCRIPT-`
-The scripted-diff is verified by the tool `contrib/devtools/commit-script-check.sh`
+The scripted-diff is verified by the tool `test/lint/commit-script-check.sh`
Commit [`bb81e173`](https://github.com/bitcoin/bitcoin/commit/bb81e173) is an example of a scripted-diff.
diff --git a/doc/init.md b/doc/init.md
index ffd13ae1f9..d04f7d186a 100644
--- a/doc/init.md
+++ b/doc/init.md
@@ -15,7 +15,7 @@ Service User
All three Linux startup configurations assume the existence of a "bitcoin" user
and group. They must be created before attempting to use these scripts.
-The OS X configuration assumes bitcoind will be set up for the current user.
+The macOS configuration assumes bitcoind will be set up for the current user.
Configuration
---------------------------------
@@ -65,7 +65,7 @@ reasons to make the configuration file and data directory only readable by the
bitcoin user and group. Access to bitcoin-cli and other bitcoind rpc clients
can then be controlled by group membership.
-### Mac OS X
+### macOS
Binary: `/usr/local/bin/bitcoind`
Configuration file: `~/Library/Application Support/Bitcoin/bitcoin.conf`
@@ -111,7 +111,7 @@ Using this script, you can adjust the path and flags to the bitcoind program by
setting the BITCOIND and FLAGS environment variables in the file
/etc/sysconfig/bitcoind. You can also use the DAEMONOPTS environment variable here.
-### Mac OS X
+### macOS
Copy org.bitcoin.bitcoind.plist into ~/Library/LaunchAgents. Load the launch agent by
running `launchctl load ~/Library/LaunchAgents/org.bitcoin.bitcoind.plist`.
diff --git a/doc/release-notes-pr10740.md b/doc/release-notes-pr10740.md
index f286216b6e..c81ea6a4db 100644
--- a/doc/release-notes-pr10740.md
+++ b/doc/release-notes-pr10740.md
@@ -1,8 +1,9 @@
-Dynamic loading of wallets
---------------------------
+Dynamic loading and creation of wallets
+---------------------------------------
-Previously, wallets could only be loaded at startup, by specifying `-wallet` parameters on the command line or in the bitcoin.conf file. It is now possible to load wallets dynamically at runtime by calling the `loadwallet` RPC.
+Previously, wallets could only be loaded or created at startup, by specifying `-wallet` parameters on the command line or in the bitcoin.conf file. It is now possible to load and create wallets dynamically at runtime:
-The wallet can be specified as file/directory basename (which must be located in the `walletdir` directory), or as an absolute path to a file/directory.
+- Existing wallets can be loaded by calling the `loadwallet` RPC. The wallet can be specified as file/directory basename (which must be located in the `walletdir` directory), or as an absolute path to a file/directory.
+- New wallets can be created (and loaded) by calling the `createwallet` RPC. The provided name must not match a wallet file in the `walletdir` directory or the name of a wallet that is currently loaded.
-This feature is currently only available through the RPC interface. Wallets loaded in this way will display in the bitcoin-qt GUI.
+This feature is currently only available through the RPC interface.
diff --git a/doc/release-notes-pr12924.md b/doc/release-notes-pr12924.md
new file mode 100644
index 0000000000..92e7e23217
--- /dev/null
+++ b/doc/release-notes-pr12924.md
@@ -0,0 +1,12 @@
+RPC changes
+------------
+
+### Low-level changes
+
+- The `getwalletinfo` RPC method now returns an `hdseedid` value, which is always the same as the incorrectly-named `hdmasterkeyid` value. `hdmasterkeyid` will be removed in V0.18.
+- The `getaddressinfo` RPC method now returns an `hdseedid` value, which is always the same as the incorrectly-named `hdmasterkeyid` value. `hdmasterkeyid` will be removed in V0.18.
+
+Other API changes
+-----------------
+
+- The `inactivehdmaster` property in the `dumpwallet` output has been corrected to `inactivehdseed`
diff --git a/doc/release-process.md b/doc/release-process.md
index a988c74ba5..912b620794 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -89,7 +89,7 @@ Ensure gitian-builder is up-to-date:
wget -P inputs http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz
popd
-Create the OS X SDK tarball, see the [OS X readme](README_osx.md) for details, and copy it into the inputs directory.
+Create the macOS SDK tarball, see the [macOS readme](README_osx.md) for details, and copy it into the inputs directory.
### Optional: Seed the Gitian sources cache and offline git repositories
@@ -111,7 +111,7 @@ NOTE: Offline builds must use the --url flag to ensure Gitian fetches only from
The gbuild invocations below <b>DO NOT DO THIS</b> by default.
-### Build and sign Bitcoin Core for Linux, Windows, and OS X:
+### Build and sign Bitcoin Core for Linux, Windows, and macOS:
pushd ./gitian-builder
./bin/gbuild --num-make 2 --memory 3000 --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml
@@ -134,7 +134,7 @@ Build output expected:
1. source tarball (`bitcoin-${VERSION}.tar.gz`)
2. linux 32-bit and 64-bit dist tarballs (`bitcoin-${VERSION}-linux[32|64].tar.gz`)
3. windows 32-bit and 64-bit unsigned installers and dist zips (`bitcoin-${VERSION}-win[32|64]-setup-unsigned.exe`, `bitcoin-${VERSION}-win[32|64].zip`)
- 4. OS X unsigned installer and dist tarball (`bitcoin-${VERSION}-osx-unsigned.dmg`, `bitcoin-${VERSION}-osx64.tar.gz`)
+ 4. macOS unsigned installer and dist tarball (`bitcoin-${VERSION}-osx-unsigned.dmg`, `bitcoin-${VERSION}-osx64.tar.gz`)
5. Gitian signatures (in `gitian.sigs/${VERSION}-<linux|{win,osx}-unsigned>/(your Gitian key)/`)
### Verify other gitian builders signatures to your own. (Optional)
@@ -161,13 +161,13 @@ Commit your signature to gitian.sigs:
git push # Assuming you can push to the gitian.sigs tree
popd
-Codesigner only: Create Windows/OS X detached signatures:
+Codesigner only: Create Windows/macOS detached signatures:
- Only one person handles codesigning. Everyone else should skip to the next step.
-- Only once the Windows/OS X builds each have 3 matching signatures may they be signed with their respective release keys.
+- Only once the Windows/macOS builds each have 3 matching signatures may they be signed with their respective release keys.
-Codesigner only: Sign the osx binary:
+Codesigner only: Sign the macOS binary:
- transfer bitcoin-osx-unsigned.tar.gz to osx for signing
+ transfer bitcoin-osx-unsigned.tar.gz to macOS for signing
tar xf bitcoin-osx-unsigned.tar.gz
./detached-sig-create.sh -s "Key ID"
Enter the keychain password and authorize the signature
@@ -192,12 +192,12 @@ Codesigner only: Commit the detached codesign payloads:
git tag -s v${VERSION} HEAD
git push the current branch and new tag
-Non-codesigners: wait for Windows/OS X detached signatures:
+Non-codesigners: wait for Windows/macOS detached signatures:
-- Once the Windows/OS X builds each have 3 matching signatures, they will be signed with their respective release keys.
+- Once the Windows/macOS builds each have 3 matching signatures, they will be signed with their respective release keys.
- Detached signatures will then be committed to the [bitcoin-detached-sigs](https://github.com/bitcoin-core/bitcoin-detached-sigs) repository, which can be combined with the unsigned apps to create signed binaries.
-Create (and optionally verify) the signed OS X binary:
+Create (and optionally verify) the signed macOS binary:
pushd ./gitian-builder
./bin/gbuild -i --commit signature=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml
@@ -216,7 +216,7 @@ Create (and optionally verify) the signed Windows binaries:
mv build/out/bitcoin-*win32-setup.exe ../bitcoin-${VERSION}-win32-setup.exe
popd
-Commit your signature for the signed OS X/Windows binaries:
+Commit your signature for the signed macOS/Windows binaries:
pushd gitian.sigs
git add ${VERSION}-osx-signed/"${SIGNER}"
@@ -276,14 +276,14 @@ bitcoin.org (see below for bitcoin.org update instructions).
- Update bitcoin.org version
- First, check to see if the Bitcoin.org maintainers have prepared a
- release: https://github.com/bitcoin-dot-org/bitcoin.org/labels/Releases
+ release: https://github.com/bitcoin-dot-org/bitcoin.org/labels/Core
- If they have, it will have previously failed their Travis CI
checks because the final release files weren't uploaded.
Trigger a Travis CI rebuild---if it passes, merge.
- If they have not prepared a release, follow the Bitcoin.org release
- instructions: https://github.com/bitcoin-dot-org/bitcoin.org#release-notes
+ instructions: https://github.com/bitcoin-dot-org/bitcoin.org/blob/master/docs/adding-events-release-notes-and-alerts.md#release-notes
- After the pull request is merged, the website will automatically show the newest version within 15 minutes, as well
as update the OS download links. Ping @saivann/@harding (saivann/harding on Freenode) in case anything goes wrong
diff --git a/src/Makefile.am b/src/Makefile.am
index 5dbf4bef8c..96e56915a6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,7 +5,7 @@
DIST_SUBDIRS = secp256k1 univalue
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_CXXFLAGS = $(DEBUG_CXXFLAGS) $(HARDENED_CXXFLAGS) $(WARN_CXXFLAGS) $(NOWARN_CXXFLAGS) $(ERROR_CXXFLAGS) $(GPROF_CXXFLAGS) $(SANITIZER_CXXFLAGS)
AM_CPPFLAGS = $(DEBUG_CPPFLAGS) $(HARDENED_CPPFLAGS)
AM_LIBTOOLFLAGS = --preserve-dup-deps
EXTRA_LIBRARIES =
@@ -30,6 +30,8 @@ LIBBITCOIN_CONSENSUS=libbitcoin_consensus.a
LIBBITCOIN_CLI=libbitcoin_cli.a
LIBBITCOIN_UTIL=libbitcoin_util.a
LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a
+LIBBITCOIN_CRYPTO_SSE41=crypto/libbitcoin_crypto_sse41.a
+LIBBITCOIN_CRYPTO_AVX2=crypto/libbitcoin_crypto_avx2.a
LIBBITCOINQT=qt/libbitcoinqt.a
LIBSECP256K1=secp256k1/libsecp256k1.la
@@ -50,6 +52,8 @@ $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
# But to build the less dependent modules first, we manually select their order here:
EXTRA_LIBRARIES += \
$(LIBBITCOIN_CRYPTO) \
+ $(LIBBITCOIN_CRYPTO_SSE41) \
+ $(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_CONSENSUS) \
@@ -289,6 +293,22 @@ if USE_ASM
crypto_libbitcoin_crypto_a_SOURCES += crypto/sha256_sse4.cpp
endif
+crypto_libbitcoin_crypto_sse41_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+crypto_libbitcoin_crypto_sse41_a_CPPFLAGS = $(AM_CPPFLAGS)
+if ENABLE_SSE41
+crypto_libbitcoin_crypto_sse41_a_CXXFLAGS += $(SSE41_CXXFLAGS)
+crypto_libbitcoin_crypto_sse41_a_CPPFLAGS += -DENABLE_SSE41
+endif
+crypto_libbitcoin_crypto_sse41_a_SOURCES = crypto/sha256_sse41.cpp
+
+crypto_libbitcoin_crypto_avx2_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
+crypto_libbitcoin_crypto_avx2_a_CPPFLAGS = $(AM_CPPFLAGS)
+if ENABLE_AVX2
+crypto_libbitcoin_crypto_avx2_a_CXXFLAGS += $(AVX2_CXXFLAGS)
+crypto_libbitcoin_crypto_avx2_a_CPPFLAGS += -DENABLE_AVX2
+endif
+crypto_libbitcoin_crypto_avx2_a_SOURCES = crypto/sha256_avx2.cpp
+
# consensus: shared between all executables that validate any consensus rules.
libbitcoin_consensus_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
libbitcoin_consensus_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
@@ -411,6 +431,8 @@ bitcoind_LDADD = \
$(LIBBITCOIN_ZMQ) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
+ $(LIBBITCOIN_CRYPTO_SSE41) \
+ $(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBLEVELDB) \
$(LIBLEVELDB_SSE42) \
$(LIBMEMENV) \
@@ -432,7 +454,9 @@ bitcoin_cli_LDADD = \
$(LIBBITCOIN_CLI) \
$(LIBUNIVALUE) \
$(LIBBITCOIN_UTIL) \
- $(LIBBITCOIN_CRYPTO)
+ $(LIBBITCOIN_CRYPTO) \
+ $(LIBBITCOIN_CRYPTO_SSE41) \
+ $(LIBBITCOIN_CRYPTO_AVX2)
bitcoin_cli_LDADD += $(BOOST_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_LIBS)
#
@@ -453,6 +477,8 @@ bitcoin_tx_LDADD = \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
+ $(LIBBITCOIN_CRYPTO_SSE41) \
+ $(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBSECP256K1)
bitcoin_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index 3306dcf598..804df3bf21 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -21,6 +21,7 @@ bench_bench_bitcoin_SOURCES = \
bench/rollingbloom.cpp \
bench/crypto_hash.cpp \
bench/ccoins_caching.cpp \
+ bench/merkle_root.cpp \
bench/mempool_eviction.cpp \
bench/verify_script.cpp \
bench/base58.cpp \
@@ -38,6 +39,8 @@ bench_bench_bitcoin_LDADD = \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
+ $(LIBBITCOIN_CRYPTO_SSE41) \
+ $(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBLEVELDB) \
$(LIBLEVELDB_SSE42) \
$(LIBMEMENV) \
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index a84a11ac45..f8c31be3d4 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -408,7 +408,7 @@ endif
if ENABLE_ZMQ
qt_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif
-qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \
+qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_CRYPTO_SSE41) $(LIBBITCOIN_CRYPTO_AVX2) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include
index 4b14212b2e..a4356f1cbd 100644
--- a/src/Makefile.qttest.include
+++ b/src/Makefile.qttest.include
@@ -62,7 +62,7 @@ endif
if ENABLE_ZMQ
qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
endif
-qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) \
+qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_CRYPTO_SSE41) $(LIBBITCOIN_CRYPTO_AVX2) $(LIBUNIVALUE) $(LIBLEVELDB) \
$(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
$(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \
$(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 7174b3e8df..cbd63cd53d 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -109,7 +109,8 @@ test_test_bitcoin_LDADD =
if ENABLE_WALLET
test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
endif
-test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \
+
+test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_CRYPTO_SSE41) $(LIBBITCOIN_CRYPTO_AVX2) $(LIBUNIVALUE) \
$(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS)
test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
@@ -134,6 +135,8 @@ test_test_bitcoin_fuzzy_LDADD = \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
+ $(LIBBITCOIN_CRYPTO_SSE41) \
+ $(LIBBITCOIN_CRYPTO_AVX2) \
$(LIBSECP256K1)
test_test_bitcoin_fuzzy_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
@@ -166,8 +169,8 @@ if EMBEDDED_UNIVALUE
endif
%.cpp.test: %.cpp
- @echo Running tests: `cat $< | grep "BOOST_FIXTURE_TEST_SUITE(\|BOOST_AUTO_TEST_SUITE(" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1` from $<
- $(AM_V_at)$(TEST_BINARY) -l test_suite -t "`cat $< | grep "BOOST_FIXTURE_TEST_SUITE(\|BOOST_AUTO_TEST_SUITE(" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1`" > $<.log 2>&1 || (cat $<.log && false)
+ @echo Running tests: `cat $< | grep -E "(BOOST_FIXTURE_TEST_SUITE\\(|BOOST_AUTO_TEST_SUITE\\()" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1` from $<
+ $(AM_V_at)$(TEST_BINARY) -l test_suite -t "`cat $< | grep -E "(BOOST_FIXTURE_TEST_SUITE\\(|BOOST_AUTO_TEST_SUITE\\()" | cut -d '(' -f 2 | cut -d ',' -f 1 | cut -d ')' -f 1`" > $<.log 2>&1 || (cat $<.log && false)
%.json.h: %.json
@$(MKDIR_P) $(@D)
diff --git a/src/bench/bench.h b/src/bench/bench.h
index e15cb81869..5d131c2aa8 100644
--- a/src/bench/bench.h
+++ b/src/bench/bench.h
@@ -111,9 +111,9 @@ public:
class ConsolePrinter : public Printer
{
public:
- void header();
- void result(const State& state);
- void footer();
+ void header() override;
+ void result(const State& state) override;
+ void footer() override;
};
// creates box plot with plotly.js
@@ -121,9 +121,9 @@ class PlotlyPrinter : public Printer
{
public:
PlotlyPrinter(std::string plotly_url, int64_t width, int64_t height);
- void header();
- void result(const State& state);
- void footer();
+ void header() override;
+ void result(const State& state) override;
+ void footer() override;
private:
std::string m_plotly_url;
diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp
index 81648f534c..f3302bfe5a 100644
--- a/src/bench/bench_bitcoin.cpp
+++ b/src/bench/bench_bitcoin.cpp
@@ -6,11 +6,10 @@
#include <crypto/sha256.h>
#include <key.h>
-#include <validation.h>
-#include <util.h>
#include <random.h>
-
-#include <boost/lexical_cast.hpp>
+#include <util.h>
+#include <utilstrencodings.h>
+#include <validation.h>
#include <memory>
@@ -24,27 +23,34 @@ static const int64_t DEFAULT_PLOT_HEIGHT = 768;
static void SetupBenchArgs()
{
- gArgs.AddArg("-?", _("Print this help message and exit"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-list", _("List benchmarks without executing them. Can be combined with -scaling and -filter"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-evals=<n>", strprintf(_("Number of measurement evaluations to perform. (default: %u)"), DEFAULT_BENCH_EVALUATIONS), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-filter=<regex>", strprintf(_("Regular expression filter to select benchmark by name (default: %s)"), DEFAULT_BENCH_FILTER), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-scaling=<n>", strprintf(_("Scaling factor for benchmark's runtime (default: %u)"), DEFAULT_BENCH_SCALING), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-printer=(console|plot)", strprintf(_("Choose printer format. console: print data to console. plot: Print results as HTML graph (default: %s)"), DEFAULT_BENCH_PRINTER), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-plot-plotlyurl=<uri>", strprintf(_("URL to use for plotly.js (default: %s)"), DEFAULT_PLOT_PLOTLYURL), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-plot-width=<x>", strprintf(_("Plot width in pixel (default: %u)"), DEFAULT_PLOT_WIDTH), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-plot-height=<x>", strprintf(_("Plot height in pixel (default: %u)"), DEFAULT_PLOT_HEIGHT), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-?", "Print this help message and exit", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-list", "List benchmarks without executing them. Can be combined with -scaling and -filter", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-evals=<n>", strprintf("Number of measurement evaluations to perform. (default: %u)", DEFAULT_BENCH_EVALUATIONS), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-filter=<regex>", strprintf("Regular expression filter to select benchmark by name (default: %s)", DEFAULT_BENCH_FILTER), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-scaling=<n>", strprintf("Scaling factor for benchmark's runtime (default: %u)", DEFAULT_BENCH_SCALING), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-printer=(console|plot)", strprintf("Choose printer format. console: print data to console. plot: Print results as HTML graph (default: %s)", DEFAULT_BENCH_PRINTER), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-plot-plotlyurl=<uri>", strprintf("URL to use for plotly.js (default: %s)", DEFAULT_PLOT_PLOTLYURL), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-plot-width=<x>", strprintf("Plot width in pixel (default: %u)", DEFAULT_PLOT_WIDTH), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-plot-height=<x>", strprintf("Plot height in pixel (default: %u)", DEFAULT_PLOT_HEIGHT), false, OptionsCategory::OPTIONS);
+
+ // Hidden
+ gArgs.AddArg("-h", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-help", "", false, OptionsCategory::HIDDEN);
}
-int
-main(int argc, char** argv)
+int main(int argc, char** argv)
{
SetupBenchArgs();
- gArgs.ParseParameters(argc, argv);
+ std::string error;
+ if (!gArgs.ParseParameters(argc, argv, error)) {
+ fprintf(stderr, "Error parsing command line arguments: %s\n", error.c_str());
+ return EXIT_FAILURE;
+ }
if (HelpRequested(gArgs)) {
std::cout << gArgs.GetHelpMessage();
- return 0;
+ return EXIT_SUCCESS;
}
SHA256AutoDetect();
@@ -57,8 +63,11 @@ main(int argc, char** argv)
std::string scaling_str = gArgs.GetArg("-scaling", DEFAULT_BENCH_SCALING);
bool is_list_only = gArgs.GetBoolArg("-list", false);
- double scaling_factor = boost::lexical_cast<double>(scaling_str);
-
+ double scaling_factor;
+ if (!ParseDouble(scaling_str, &scaling_factor)) {
+ fprintf(stderr, "Error parsing scaling factor as double: %s\n", scaling_str.c_str());
+ return EXIT_FAILURE;
+ }
std::unique_ptr<benchmark::Printer> printer(new benchmark::ConsolePrinter());
std::string printer_arg = gArgs.GetArg("-printer", DEFAULT_BENCH_PRINTER);
@@ -72,4 +81,6 @@ main(int argc, char** argv)
benchmark::BenchRunner::RunAll(*printer, evaluations, scaling_factor, regex_filter, is_list_only);
ECC_Stop();
+
+ return EXIT_SUCCESS;
}
diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp
index adb69bc6c3..7d907eaf10 100644
--- a/src/bench/crypto_hash.cpp
+++ b/src/bench/crypto_hash.cpp
@@ -52,6 +52,14 @@ static void SHA256_32b(benchmark::State& state)
}
}
+static void SHA256D64_1024(benchmark::State& state)
+{
+ std::vector<uint8_t> in(64 * 1024, 0);
+ while (state.KeepRunning()) {
+ SHA256D64(in.data(), in.data(), 1024);
+ }
+}
+
static void SHA512(benchmark::State& state)
{
uint8_t hash[CSHA512::OUTPUT_SIZE];
@@ -94,5 +102,6 @@ BENCHMARK(SHA512, 330);
BENCHMARK(SHA256_32b, 4700 * 1000);
BENCHMARK(SipHash_32b, 40 * 1000 * 1000);
+BENCHMARK(SHA256D64_1024, 7400);
BENCHMARK(FastRandom_32bit, 110 * 1000 * 1000);
BENCHMARK(FastRandom_1bit, 440 * 1000 * 1000);
diff --git a/src/bench/merkle_root.cpp b/src/bench/merkle_root.cpp
new file mode 100644
index 0000000000..ae2a0a28dc
--- /dev/null
+++ b/src/bench/merkle_root.cpp
@@ -0,0 +1,26 @@
+// Copyright (c) 2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "bench.h"
+
+#include "uint256.h"
+#include "random.h"
+#include "consensus/merkle.h"
+
+static void MerkleRoot(benchmark::State& state)
+{
+ FastRandomContext rng(true);
+ std::vector<uint256> leaves;
+ leaves.resize(9001);
+ for (auto& item : leaves) {
+ item = rng.rand256();
+ }
+ while (state.KeepRunning()) {
+ bool mutation = false;
+ uint256 hash = ComputeMerkleRoot(std::vector<uint256>(leaves), &mutation);
+ leaves[mutation] = hash;
+ }
+}
+
+BENCHMARK(MerkleRoot, 800);
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index b26b172305..be5ce14480 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -34,21 +34,26 @@ static void SetupCliArgs()
const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
- gArgs.AddArg("-?", _("This help message"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-conf=<file>", strprintf(_("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)"), BITCOIN_CONF_FILENAME), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-datadir=<dir>", _("Specify data directory"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-getinfo", _("Get general information from the remote server. Note that unlike server-side RPC calls, the results of -getinfo is the result of multiple non-atomic requests. Some entries in the result may represent results from different states (e.g. wallet balance may be as of a different block from the chain state reported)"), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-?", "This help message", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-conf=<file>", strprintf("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-datadir=<dir>", "Specify data directory", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-getinfo", "Get general information from the remote server. Note that unlike server-side RPC calls, the results of -getinfo is the result of multiple non-atomic requests. Some entries in the result may represent results from different states (e.g. wallet balance may be as of a different block from the chain state reported)", false, OptionsCategory::OPTIONS);
SetupChainParamsBaseOptions();
- gArgs.AddArg("-named", strprintf(_("Pass named instead of positional arguments (default: %s)"), DEFAULT_NAMED), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-rpcclienttimeout=<n>", strprintf(_("Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)"), DEFAULT_HTTP_CLIENT_TIMEOUT), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-rpcconnect=<ip>", strprintf(_("Send commands to node running on <ip> (default: %s)"), DEFAULT_RPCCONNECT), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-rpcpassword=<pw>", _("Password for JSON-RPC connections"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-rpcuser=<user>", _("Username for JSON-RPC connections"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-rpcwait", _("Wait for RPC server to start"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-rpcwallet=<walletname>", _("Send RPC for non-default wallet on RPC server (needs to exactly match corresponding -wallet option passed to bitcoind)"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-stdin", _("Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases). When combined with -stdinrpcpass, the first line from standard input is used for the RPC password."), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-stdinrpcpass", strprintf(_("Read RPC password from standard input as a single line. When combined with -stdin, the first line from standard input is used for the RPC password.")), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-named", strprintf("Pass named instead of positional arguments (default: %s)", DEFAULT_NAMED), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-rpcclienttimeout=<n>", strprintf("Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)", DEFAULT_HTTP_CLIENT_TIMEOUT), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-rpcconnect=<ip>", strprintf("Send commands to node running on <ip> (default: %s)", DEFAULT_RPCCONNECT), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-rpccookiefile=<loc>", _("Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)"), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-rpcport=<port>", strprintf("Connect to JSON-RPC on <port> (default: %u or testnet: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-rpcuser=<user>", "Username for JSON-RPC connections", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-rpcwait", "Wait for RPC server to start", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-rpcwallet=<walletname>", "Send RPC for non-default wallet on RPC server (needs to exactly match corresponding -wallet option passed to bitcoind)", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-stdin", "Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases). When combined with -stdinrpcpass, the first line from standard input is used for the RPC password.", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-stdinrpcpass", strprintf("Read RPC password from standard input as a single line. When combined with -stdin, the first line from standard input is used for the RPC password."), false, OptionsCategory::OPTIONS);
+
+ // Hidden
+ gArgs.AddArg("-h", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-help", "", false, OptionsCategory::HIDDEN);
}
//////////////////////////////////////////////////////////////////////////////
@@ -80,15 +85,19 @@ static int AppInitRPC(int argc, char* argv[])
// Parameters
//
SetupCliArgs();
- gArgs.ParseParameters(argc, argv);
+ std::string error;
+ if (!gArgs.ParseParameters(argc, argv, error)) {
+ fprintf(stderr, "Error parsing command line arguments: %s\n", error.c_str());
+ return EXIT_FAILURE;
+ }
if (argc < 2 || HelpRequested(gArgs) || gArgs.IsArgSet("-version")) {
- std::string strUsage = strprintf(_("%s RPC client version"), _(PACKAGE_NAME)) + " " + FormatFullVersion() + "\n";
+ std::string strUsage = strprintf("%s RPC client version", PACKAGE_NAME) + " " + FormatFullVersion() + "\n";
if (!gArgs.IsArgSet("-version")) {
- strUsage += "\n" + _("Usage:") + "\n" +
- " bitcoin-cli [options] <command> [params] " + strprintf(_("Send command to %s"), _(PACKAGE_NAME)) + "\n" +
- " bitcoin-cli [options] -named <command> [name=value] ... " + strprintf(_("Send command to %s (with named arguments)"), _(PACKAGE_NAME)) + "\n" +
- " bitcoin-cli [options] help " + _("List commands") + "\n" +
- " bitcoin-cli [options] help <command> " + _("Get help for a command") + "\n";
+ strUsage += "\nUsage:\n"
+ " bitcoin-cli [options] <command> [params] " + strprintf("Send command to %s", PACKAGE_NAME) + "\n" +
+ " bitcoin-cli [options] -named <command> [name=value] ... " + strprintf("Send command to %s (with named arguments)", PACKAGE_NAME) + "\n" +
+ " bitcoin-cli [options] help List commands\n" +
+ " bitcoin-cli [options] help <command> Get help for a command\n";
strUsage += "\n" + gArgs.GetHelpMessage();
}
@@ -104,10 +113,8 @@ static int AppInitRPC(int argc, char* argv[])
fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str());
return EXIT_FAILURE;
}
- try {
- gArgs.ReadConfigFiles();
- } catch (const std::exception& e) {
- fprintf(stderr,"Error reading configuration file: %s\n", e.what());
+ if (!gArgs.ReadConfigFiles(error, true)) {
+ fprintf(stderr, "Error reading configuration file: %s\n", error.c_str());
return EXIT_FAILURE;
}
// Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
@@ -364,7 +371,7 @@ static UniValue CallRPC(BaseRequestHandler *rh, const std::string& strMethod, co
} else if (response.status == HTTP_UNAUTHORIZED) {
if (failedToGetAuthCookie) {
throw std::runtime_error(strprintf(
- _("Could not locate RPC credentials. No authentication cookie could be found, and RPC password is not set. See -rpcpassword and -stdinrpcpass. Configuration file: (%s)"),
+ "Could not locate RPC credentials. No authentication cookie could be found, and RPC password is not set. See -rpcpassword and -stdinrpcpass. Configuration file: (%s)",
GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string().c_str()));
} else {
throw std::runtime_error("Authorization failed: Incorrect rpcuser or rpcpassword");
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index bf42307df5..2a594c3051 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -33,37 +33,41 @@ static const int CONTINUE_EXECUTION=-1;
static void SetupBitcoinTxArgs()
{
- gArgs.AddArg("-?", _("This help message"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-create", _("Create new, empty TX."), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-json", _("Select JSON output"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-txid", _("Output only the hex-encoded transaction id of the resultant transaction."), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-?", "This help message", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-create", "Create new, empty TX.", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-json", "Select JSON output", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-txid", "Output only the hex-encoded transaction id of the resultant transaction.", false, OptionsCategory::OPTIONS);
SetupChainParamsBaseOptions();
- gArgs.AddArg("delin=N", _("Delete input N from TX"), false, OptionsCategory::COMMANDS);
- gArgs.AddArg("delout=N", _("Delete output N from TX"), false, OptionsCategory::COMMANDS);
- gArgs.AddArg("in=TXID:VOUT(:SEQUENCE_NUMBER)", _("Add input to TX"), false, OptionsCategory::COMMANDS);
- gArgs.AddArg("locktime=N", _("Set TX lock time to N"), false, OptionsCategory::COMMANDS);
- gArgs.AddArg("nversion=N", _("Set TX version to N"), false, OptionsCategory::COMMANDS);
- gArgs.AddArg("outaddr=VALUE:ADDRESS", _("Add address-based output to TX"), false, OptionsCategory::COMMANDS);
- gArgs.AddArg("outdata=[VALUE:]DATA", _("Add data-based output to TX"), false, OptionsCategory::COMMANDS);
- gArgs.AddArg("outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]", _("Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS") + ". " +
- _("Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output") + ". " +
- _("Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash."), false, OptionsCategory::COMMANDS);
- gArgs.AddArg("outpubkey=VALUE:PUBKEY[:FLAGS]", _("Add pay-to-pubkey output to TX") + ". " +
- _("Optionally add the \"W\" flag to produce a pay-to-witness-pubkey-hash output") + ". " +
- _("Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash."), false, OptionsCategory::COMMANDS);
- gArgs.AddArg("outscript=VALUE:SCRIPT[:FLAGS]", _("Add raw script output to TX") + ". " +
- _("Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output") + ". " +
- _("Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash."), false, OptionsCategory::COMMANDS);
- gArgs.AddArg("replaceable(=N)", _("Set RBF opt-in sequence number for input N (if not provided, opt-in all available inputs)"), false, OptionsCategory::COMMANDS);
- gArgs.AddArg("sign=SIGHASH-FLAGS", _("Add zero or more signatures to transaction") + ". " +
- _("This command requires JSON registers:") +
- _("prevtxs=JSON object") + ", " +
- _("privatekeys=JSON object") + ". " +
- _("See signrawtransaction docs for format of sighash flags, JSON objects."), false, OptionsCategory::COMMANDS);
-
- gArgs.AddArg("load=NAME:FILENAME", _("Load JSON file FILENAME into register NAME"), false, OptionsCategory::REGISTER_COMMANDS);
- gArgs.AddArg("set=NAME:JSON-STRING", _("Set register NAME to given JSON-STRING"), false, OptionsCategory::REGISTER_COMMANDS);
+ gArgs.AddArg("delin=N", "Delete input N from TX", false, OptionsCategory::COMMANDS);
+ gArgs.AddArg("delout=N", "Delete output N from TX", false, OptionsCategory::COMMANDS);
+ gArgs.AddArg("in=TXID:VOUT(:SEQUENCE_NUMBER)", "Add input to TX", false, OptionsCategory::COMMANDS);
+ gArgs.AddArg("locktime=N", "Set TX lock time to N", false, OptionsCategory::COMMANDS);
+ gArgs.AddArg("nversion=N", "Set TX version to N", false, OptionsCategory::COMMANDS);
+ gArgs.AddArg("outaddr=VALUE:ADDRESS", "Add address-based output to TX", false, OptionsCategory::COMMANDS);
+ gArgs.AddArg("outdata=[VALUE:]DATA", "Add data-based output to TX", false, OptionsCategory::COMMANDS);
+ gArgs.AddArg("outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]", "Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS. "
+ "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. "
+ "Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash.", false, OptionsCategory::COMMANDS);
+ gArgs.AddArg("outpubkey=VALUE:PUBKEY[:FLAGS]", "Add pay-to-pubkey output to TX. "
+ "Optionally add the \"W\" flag to produce a pay-to-witness-pubkey-hash output. "
+ "Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash.", false, OptionsCategory::COMMANDS);
+ gArgs.AddArg("outscript=VALUE:SCRIPT[:FLAGS]", "Add raw script output to TX. "
+ "Optionally add the \"W\" flag to produce a pay-to-witness-script-hash output. "
+ "Optionally add the \"S\" flag to wrap the output in a pay-to-script-hash.", false, OptionsCategory::COMMANDS);
+ gArgs.AddArg("replaceable(=N)", "Set RBF opt-in sequence number for input N (if not provided, opt-in all available inputs)", false, OptionsCategory::COMMANDS);
+ gArgs.AddArg("sign=SIGHASH-FLAGS", "Add zero or more signatures to transaction. "
+ "This command requires JSON registers:"
+ "prevtxs=JSON object, "
+ "privatekeys=JSON object. "
+ "See signrawtransaction docs for format of sighash flags, JSON objects.", false, OptionsCategory::COMMANDS);
+
+ gArgs.AddArg("load=NAME:FILENAME", "Load JSON file FILENAME into register NAME", false, OptionsCategory::REGISTER_COMMANDS);
+ gArgs.AddArg("set=NAME:JSON-STRING", "Set register NAME to given JSON-STRING", false, OptionsCategory::REGISTER_COMMANDS);
+
+ // Hidden
+ gArgs.AddArg("-h", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-help", "", false, OptionsCategory::HIDDEN);
}
//
@@ -76,7 +80,11 @@ static int AppInitRawTx(int argc, char* argv[])
// Parameters
//
SetupBitcoinTxArgs();
- gArgs.ParseParameters(argc, argv);
+ std::string error;
+ if (!gArgs.ParseParameters(argc, argv, error)) {
+ fprintf(stderr, "Error parsing command line arguments: %s\n", error.c_str());
+ return EXIT_FAILURE;
+ }
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
try {
@@ -90,10 +98,10 @@ static int AppInitRawTx(int argc, char* argv[])
if (argc < 2 || HelpRequested(gArgs)) {
// First part of help message is specific to this utility
- std::string strUsage = strprintf(_("%s bitcoin-tx utility version"), _(PACKAGE_NAME)) + " " + FormatFullVersion() + "\n\n" +
- _("Usage:") + "\n" +
- " bitcoin-tx [options] <hex-tx> [commands] " + _("Update hex-encoded bitcoin transaction") + "\n" +
- " bitcoin-tx [options] -create [commands] " + _("Create hex-encoded bitcoin transaction") + "\n" +
+ std::string strUsage = strprintf("%s bitcoin-tx utility version", PACKAGE_NAME) + " " + FormatFullVersion() + "\n\n" +
+ "Usage:\n"
+ " bitcoin-tx [options] <hex-tx> [commands] Update hex-encoded bitcoin transaction\n" +
+ " bitcoin-tx [options] -create [commands] Create hex-encoded bitcoin transaction\n" +
"\n";
strUsage += gArgs.GetHelpMessage();
@@ -546,7 +554,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
// mergedTx will end up with all the signatures; it
// starts as a clone of the raw tx:
CMutableTransaction mergedTx{tx};
- const CTransaction txv{tx};
+ const CMutableTransaction txv{tx};
CCoinsView viewDummy;
CCoinsViewCache view(&viewDummy);
@@ -629,7 +637,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
// Sign what we can:
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
- const CTxIn& txin = mergedTx.vin[i];
+ CTxIn& txin = mergedTx.vin[i];
const Coin& coin = view.AccessCoin(txin.prevout);
if (coin.IsSpent()) {
continue;
@@ -644,7 +652,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
// ... and merge in other signatures:
sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i));
- UpdateTransaction(mergedTx, i, sigdata);
+ UpdateInput(txin, sigdata);
}
tx = mergedTx;
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 1539e4025a..a9b952e5a4 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -63,13 +63,17 @@ static bool AppInit(int argc, char* argv[])
// If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
SetupServerArgs();
#if HAVE_DECL_DAEMON
- gArgs.AddArg("-daemon", _("Run in the background as a daemon and accept commands"), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-daemon", "Run in the background as a daemon and accept commands", false, OptionsCategory::OPTIONS);
#endif
- gArgs.ParseParameters(argc, argv);
+ std::string error;
+ if (!gArgs.ParseParameters(argc, argv, error)) {
+ fprintf(stderr, "Error parsing command line arguments: %s\n", error.c_str());
+ return false;
+ }
// Process help and version before taking care about datadir
if (HelpRequested(gArgs) || gArgs.IsArgSet("-version")) {
- std::string strUsage = strprintf(_("%s Daemon"), _(PACKAGE_NAME)) + " " + _("version") + " " + FormatFullVersion() + "\n";
+ std::string strUsage = strprintf("%s Daemon", PACKAGE_NAME) + " version " + FormatFullVersion() + "\n";
if (gArgs.IsArgSet("-version"))
{
@@ -77,8 +81,8 @@ static bool AppInit(int argc, char* argv[])
}
else
{
- strUsage += "\n" + _("Usage:") + "\n" +
- " bitcoind [options] " + strprintf(_("Start %s Daemon"), _(PACKAGE_NAME)) + "\n";
+ strUsage += "\nUsage:\n"
+ " bitcoind [options] " + strprintf("Start %s Daemon", PACKAGE_NAME) + "\n";
strUsage += "\n" + gArgs.GetHelpMessage();
}
@@ -94,11 +98,8 @@ static bool AppInit(int argc, char* argv[])
fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str());
return false;
}
- try
- {
- gArgs.ReadConfigFiles();
- } catch (const std::exception& e) {
- fprintf(stderr,"Error reading configuration file: %s\n", e.what());
+ if (!gArgs.ReadConfigFiles(error)) {
+ fprintf(stderr, "Error reading configuration file: %s\n", error.c_str());
return false;
}
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp
index 91ba3ac9d9..787d8d8f6a 100644
--- a/src/chainparamsbase.cpp
+++ b/src/chainparamsbase.cpp
@@ -18,7 +18,7 @@ void SetupChainParamsBaseOptions()
{
gArgs.AddArg("-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.", true, OptionsCategory::CHAINPARAMS);
- gArgs.AddArg("-testnet", _("Use the test chain"), false, OptionsCategory::CHAINPARAMS);
+ gArgs.AddArg("-testnet", "Use the test chain", false, OptionsCategory::CHAINPARAMS);
}
static std::unique_ptr<CBaseChainParams> globalChainBaseParams;
diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp
index 74a9ebb2e3..07cd109cc1 100644
--- a/src/consensus/merkle.cpp
+++ b/src/consensus/merkle.cpp
@@ -42,118 +42,26 @@
root.
*/
-/* This implements a constant-space merkle root/path calculator, limited to 2^32 leaves. */
-static void MerkleComputation(const std::vector<uint256>& leaves, uint256* proot, bool* pmutated, uint32_t branchpos, std::vector<uint256>* 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;
- }
+
+uint256 ComputeMerkleRoot(std::vector<uint256> hashes, bool* mutated) {
+ bool mutation = false;
+ while (hashes.size() > 1) {
+ if (mutated) {
+ for (size_t pos = 0; pos + 1 < hashes.size(); pos += 2) {
+ if (hashes[pos] == hashes[pos + 1]) mutation = 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;
+ if (hashes.size() & 1) {
+ hashes.push_back(hashes.back());
}
+ SHA256D64(hashes[0].begin(), hashes[0].begin(), hashes.size() / 2);
+ hashes.resize(hashes.size() / 2);
}
- // 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;
+ if (mutated) *mutated = mutation;
+ if (hashes.size() == 0) return uint256();
+ return hashes[0];
}
-uint256 ComputeMerkleRoot(const std::vector<uint256>& leaves, bool* mutated) {
- uint256 hash;
- MerkleComputation(leaves, &hash, mutated, -1, nullptr);
- return hash;
-}
-
-std::vector<uint256> ComputeMerkleBranch(const std::vector<uint256>& leaves, uint32_t position) {
- std::vector<uint256> ret;
- MerkleComputation(leaves, nullptr, nullptr, position, &ret);
- return ret;
-}
-
-uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector<uint256>& vMerkleBranch, uint32_t nIndex) {
- uint256 hash = leaf;
- for (std::vector<uint256>::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)
{
@@ -162,7 +70,7 @@ uint256 BlockMerkleRoot(const CBlock& block, bool* mutated)
for (size_t s = 0; s < block.vtx.size(); s++) {
leaves[s] = block.vtx[s]->GetHash();
}
- return ComputeMerkleRoot(leaves, mutated);
+ return ComputeMerkleRoot(std::move(leaves), mutated);
}
uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated)
@@ -173,15 +81,6 @@ uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated)
for (size_t s = 1; s < block.vtx.size(); s++) {
leaves[s] = block.vtx[s]->GetWitnessHash();
}
- return ComputeMerkleRoot(leaves, mutated);
+ return ComputeMerkleRoot(std::move(leaves), mutated);
}
-std::vector<uint256> BlockMerkleBranch(const CBlock& block, uint32_t position)
-{
- std::vector<uint256> 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
index 0afb73adb5..01d75b1329 100644
--- a/src/consensus/merkle.h
+++ b/src/consensus/merkle.h
@@ -12,9 +12,7 @@
#include <primitives/block.h>
#include <uint256.h>
-uint256 ComputeMerkleRoot(const std::vector<uint256>& leaves, bool* mutated = nullptr);
-std::vector<uint256> ComputeMerkleBranch(const std::vector<uint256>& leaves, uint32_t position);
-uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector<uint256>& branch, uint32_t position);
+uint256 ComputeMerkleRoot(std::vector<uint256> hashes, bool* mutated = nullptr);
/*
* Compute the Merkle root of the transactions in a block.
@@ -28,11 +26,4 @@ uint256 BlockMerkleRoot(const CBlock& block, bool* mutated = nullptr);
*/
uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated = nullptr);
-/*
- * Compute the Merkle branch for the tree of transactions in a block, for a
- * given position.
- * This can be verified using ComputeMerkleRootFromBranch.
- */
-std::vector<uint256> BlockMerkleBranch(const CBlock& block, uint32_t position);
-
#endif // BITCOIN_CONSENSUS_MERKLE_H
diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp
index f3245b8dea..6ac51d11cd 100644
--- a/src/crypto/sha256.cpp
+++ b/src/crypto/sha256.cpp
@@ -19,6 +19,16 @@ void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks);
#endif
#endif
+namespace sha256d64_sse41
+{
+void Transform_4way(unsigned char* out, const unsigned char* in);
+}
+
+namespace sha256d64_avx2
+{
+void Transform_8way(unsigned char* out, const unsigned char* in);
+}
+
// Internal implementation code.
namespace
{
@@ -33,9 +43,9 @@ uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x <<
uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); }
/** One round of SHA-256. */
-void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t& d, uint32_t e, uint32_t f, uint32_t g, uint32_t& h, uint32_t k, uint32_t w)
+void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t& d, uint32_t e, uint32_t f, uint32_t g, uint32_t& h, uint32_t k)
{
- uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w;
+ uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k;
uint32_t t2 = Sigma0(a) + Maj(a, b, c);
d += t1;
h = t1 + t2;
@@ -61,73 +71,73 @@ void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks)
uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7];
uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
- Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0));
- Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4));
- Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8));
- Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12));
- Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16));
- Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20));
- Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24));
- Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28));
- Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32));
- Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36));
- Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40));
- Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44));
- Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48));
- Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52));
- Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56));
- Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60));
-
- Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1));
- Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2));
- Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3));
- Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4));
- Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5));
- Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6));
- Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7));
- Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8));
- Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9));
- Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10));
- Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11));
- Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12));
- Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13));
- Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14));
- Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15));
- Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0));
-
- Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1));
- Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2));
- Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3));
- Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4));
- Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5));
- Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6));
- Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7));
- Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8));
- Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9));
- Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10));
- Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11));
- Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12));
- Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13));
- Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14));
- Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15));
- Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0));
-
- Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1));
- Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2));
- Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3));
- Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4));
- Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5));
- Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6));
- Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7));
- Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8));
- Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9));
- Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10));
- Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11));
- Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12));
- Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13));
- Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14));
- Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15));
- Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0));
+ Round(a, b, c, d, e, f, g, h, 0x428a2f98 + (w0 = ReadBE32(chunk + 0)));
+ Round(h, a, b, c, d, e, f, g, 0x71374491 + (w1 = ReadBE32(chunk + 4)));
+ Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf + (w2 = ReadBE32(chunk + 8)));
+ Round(f, g, h, a, b, c, d, e, 0xe9b5dba5 + (w3 = ReadBE32(chunk + 12)));
+ Round(e, f, g, h, a, b, c, d, 0x3956c25b + (w4 = ReadBE32(chunk + 16)));
+ Round(d, e, f, g, h, a, b, c, 0x59f111f1 + (w5 = ReadBE32(chunk + 20)));
+ Round(c, d, e, f, g, h, a, b, 0x923f82a4 + (w6 = ReadBE32(chunk + 24)));
+ Round(b, c, d, e, f, g, h, a, 0xab1c5ed5 + (w7 = ReadBE32(chunk + 28)));
+ Round(a, b, c, d, e, f, g, h, 0xd807aa98 + (w8 = ReadBE32(chunk + 32)));
+ Round(h, a, b, c, d, e, f, g, 0x12835b01 + (w9 = ReadBE32(chunk + 36)));
+ Round(g, h, a, b, c, d, e, f, 0x243185be + (w10 = ReadBE32(chunk + 40)));
+ Round(f, g, h, a, b, c, d, e, 0x550c7dc3 + (w11 = ReadBE32(chunk + 44)));
+ Round(e, f, g, h, a, b, c, d, 0x72be5d74 + (w12 = ReadBE32(chunk + 48)));
+ Round(d, e, f, g, h, a, b, c, 0x80deb1fe + (w13 = ReadBE32(chunk + 52)));
+ Round(c, d, e, f, g, h, a, b, 0x9bdc06a7 + (w14 = ReadBE32(chunk + 56)));
+ Round(b, c, d, e, f, g, h, a, 0xc19bf174 + (w15 = ReadBE32(chunk + 60)));
+
+ Round(a, b, c, d, e, f, g, h, 0xe49b69c1 + (w0 += sigma1(w14) + w9 + sigma0(w1)));
+ Round(h, a, b, c, d, e, f, g, 0xefbe4786 + (w1 += sigma1(w15) + w10 + sigma0(w2)));
+ Round(g, h, a, b, c, d, e, f, 0x0fc19dc6 + (w2 += sigma1(w0) + w11 + sigma0(w3)));
+ Round(f, g, h, a, b, c, d, e, 0x240ca1cc + (w3 += sigma1(w1) + w12 + sigma0(w4)));
+ Round(e, f, g, h, a, b, c, d, 0x2de92c6f + (w4 += sigma1(w2) + w13 + sigma0(w5)));
+ Round(d, e, f, g, h, a, b, c, 0x4a7484aa + (w5 += sigma1(w3) + w14 + sigma0(w6)));
+ Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc + (w6 += sigma1(w4) + w15 + sigma0(w7)));
+ Round(b, c, d, e, f, g, h, a, 0x76f988da + (w7 += sigma1(w5) + w0 + sigma0(w8)));
+ Round(a, b, c, d, e, f, g, h, 0x983e5152 + (w8 += sigma1(w6) + w1 + sigma0(w9)));
+ Round(h, a, b, c, d, e, f, g, 0xa831c66d + (w9 += sigma1(w7) + w2 + sigma0(w10)));
+ Round(g, h, a, b, c, d, e, f, 0xb00327c8 + (w10 += sigma1(w8) + w3 + sigma0(w11)));
+ Round(f, g, h, a, b, c, d, e, 0xbf597fc7 + (w11 += sigma1(w9) + w4 + sigma0(w12)));
+ Round(e, f, g, h, a, b, c, d, 0xc6e00bf3 + (w12 += sigma1(w10) + w5 + sigma0(w13)));
+ Round(d, e, f, g, h, a, b, c, 0xd5a79147 + (w13 += sigma1(w11) + w6 + sigma0(w14)));
+ Round(c, d, e, f, g, h, a, b, 0x06ca6351 + (w14 += sigma1(w12) + w7 + sigma0(w15)));
+ Round(b, c, d, e, f, g, h, a, 0x14292967 + (w15 += sigma1(w13) + w8 + sigma0(w0)));
+
+ Round(a, b, c, d, e, f, g, h, 0x27b70a85 + (w0 += sigma1(w14) + w9 + sigma0(w1)));
+ Round(h, a, b, c, d, e, f, g, 0x2e1b2138 + (w1 += sigma1(w15) + w10 + sigma0(w2)));
+ Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc + (w2 += sigma1(w0) + w11 + sigma0(w3)));
+ Round(f, g, h, a, b, c, d, e, 0x53380d13 + (w3 += sigma1(w1) + w12 + sigma0(w4)));
+ Round(e, f, g, h, a, b, c, d, 0x650a7354 + (w4 += sigma1(w2) + w13 + sigma0(w5)));
+ Round(d, e, f, g, h, a, b, c, 0x766a0abb + (w5 += sigma1(w3) + w14 + sigma0(w6)));
+ Round(c, d, e, f, g, h, a, b, 0x81c2c92e + (w6 += sigma1(w4) + w15 + sigma0(w7)));
+ Round(b, c, d, e, f, g, h, a, 0x92722c85 + (w7 += sigma1(w5) + w0 + sigma0(w8)));
+ Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1 + (w8 += sigma1(w6) + w1 + sigma0(w9)));
+ Round(h, a, b, c, d, e, f, g, 0xa81a664b + (w9 += sigma1(w7) + w2 + sigma0(w10)));
+ Round(g, h, a, b, c, d, e, f, 0xc24b8b70 + (w10 += sigma1(w8) + w3 + sigma0(w11)));
+ Round(f, g, h, a, b, c, d, e, 0xc76c51a3 + (w11 += sigma1(w9) + w4 + sigma0(w12)));
+ Round(e, f, g, h, a, b, c, d, 0xd192e819 + (w12 += sigma1(w10) + w5 + sigma0(w13)));
+ Round(d, e, f, g, h, a, b, c, 0xd6990624 + (w13 += sigma1(w11) + w6 + sigma0(w14)));
+ Round(c, d, e, f, g, h, a, b, 0xf40e3585 + (w14 += sigma1(w12) + w7 + sigma0(w15)));
+ Round(b, c, d, e, f, g, h, a, 0x106aa070 + (w15 += sigma1(w13) + w8 + sigma0(w0)));
+
+ Round(a, b, c, d, e, f, g, h, 0x19a4c116 + (w0 += sigma1(w14) + w9 + sigma0(w1)));
+ Round(h, a, b, c, d, e, f, g, 0x1e376c08 + (w1 += sigma1(w15) + w10 + sigma0(w2)));
+ Round(g, h, a, b, c, d, e, f, 0x2748774c + (w2 += sigma1(w0) + w11 + sigma0(w3)));
+ Round(f, g, h, a, b, c, d, e, 0x34b0bcb5 + (w3 += sigma1(w1) + w12 + sigma0(w4)));
+ Round(e, f, g, h, a, b, c, d, 0x391c0cb3 + (w4 += sigma1(w2) + w13 + sigma0(w5)));
+ Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a + (w5 += sigma1(w3) + w14 + sigma0(w6)));
+ Round(c, d, e, f, g, h, a, b, 0x5b9cca4f + (w6 += sigma1(w4) + w15 + sigma0(w7)));
+ Round(b, c, d, e, f, g, h, a, 0x682e6ff3 + (w7 += sigma1(w5) + w0 + sigma0(w8)));
+ Round(a, b, c, d, e, f, g, h, 0x748f82ee + (w8 += sigma1(w6) + w1 + sigma0(w9)));
+ Round(h, a, b, c, d, e, f, g, 0x78a5636f + (w9 += sigma1(w7) + w2 + sigma0(w10)));
+ Round(g, h, a, b, c, d, e, f, 0x84c87814 + (w10 += sigma1(w8) + w3 + sigma0(w11)));
+ Round(f, g, h, a, b, c, d, e, 0x8cc70208 + (w11 += sigma1(w9) + w4 + sigma0(w12)));
+ Round(e, f, g, h, a, b, c, d, 0x90befffa + (w12 += sigma1(w10) + w5 + sigma0(w13)));
+ Round(d, e, f, g, h, a, b, c, 0xa4506ceb + (w13 += sigma1(w11) + w6 + sigma0(w14)));
+ Round(c, d, e, f, g, h, a, b, 0xbef9a3f7 + (w14 + sigma1(w12) + w7 + sigma0(w15)));
+ Round(b, c, d, e, f, g, h, a, 0xc67178f2 + (w15 + sigma1(w13) + w8 + sigma0(w0)));
s[0] += a;
s[1] += b;
@@ -141,9 +151,300 @@ void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks)
}
}
+void TransformD64(unsigned char* out, const unsigned char* in)
+{
+ // Transform 1
+ uint32_t a = 0x6a09e667ul;
+ uint32_t b = 0xbb67ae85ul;
+ uint32_t c = 0x3c6ef372ul;
+ uint32_t d = 0xa54ff53aul;
+ uint32_t e = 0x510e527ful;
+ uint32_t f = 0x9b05688cul;
+ uint32_t g = 0x1f83d9abul;
+ uint32_t h = 0x5be0cd19ul;
+
+ uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
+
+ Round(a, b, c, d, e, f, g, h, 0x428a2f98ul + (w0 = ReadBE32(in + 0)));
+ Round(h, a, b, c, d, e, f, g, 0x71374491ul + (w1 = ReadBE32(in + 4)));
+ Round(g, h, a, b, c, d, e, f, 0xb5c0fbcful + (w2 = ReadBE32(in + 8)));
+ Round(f, g, h, a, b, c, d, e, 0xe9b5dba5ul + (w3 = ReadBE32(in + 12)));
+ Round(e, f, g, h, a, b, c, d, 0x3956c25bul + (w4 = ReadBE32(in + 16)));
+ Round(d, e, f, g, h, a, b, c, 0x59f111f1ul + (w5 = ReadBE32(in + 20)));
+ Round(c, d, e, f, g, h, a, b, 0x923f82a4ul + (w6 = ReadBE32(in + 24)));
+ Round(b, c, d, e, f, g, h, a, 0xab1c5ed5ul + (w7 = ReadBE32(in + 28)));
+ Round(a, b, c, d, e, f, g, h, 0xd807aa98ul + (w8 = ReadBE32(in + 32)));
+ Round(h, a, b, c, d, e, f, g, 0x12835b01ul + (w9 = ReadBE32(in + 36)));
+ Round(g, h, a, b, c, d, e, f, 0x243185beul + (w10 = ReadBE32(in + 40)));
+ Round(f, g, h, a, b, c, d, e, 0x550c7dc3ul + (w11 = ReadBE32(in + 44)));
+ Round(e, f, g, h, a, b, c, d, 0x72be5d74ul + (w12 = ReadBE32(in + 48)));
+ Round(d, e, f, g, h, a, b, c, 0x80deb1feul + (w13 = ReadBE32(in + 52)));
+ Round(c, d, e, f, g, h, a, b, 0x9bdc06a7ul + (w14 = ReadBE32(in + 56)));
+ Round(b, c, d, e, f, g, h, a, 0xc19bf174ul + (w15 = ReadBE32(in + 60)));
+ Round(a, b, c, d, e, f, g, h, 0xe49b69c1ul + (w0 += sigma1(w14) + w9 + sigma0(w1)));
+ Round(h, a, b, c, d, e, f, g, 0xefbe4786ul + (w1 += sigma1(w15) + w10 + sigma0(w2)));
+ Round(g, h, a, b, c, d, e, f, 0x0fc19dc6ul + (w2 += sigma1(w0) + w11 + sigma0(w3)));
+ Round(f, g, h, a, b, c, d, e, 0x240ca1ccul + (w3 += sigma1(w1) + w12 + sigma0(w4)));
+ Round(e, f, g, h, a, b, c, d, 0x2de92c6ful + (w4 += sigma1(w2) + w13 + sigma0(w5)));
+ Round(d, e, f, g, h, a, b, c, 0x4a7484aaul + (w5 += sigma1(w3) + w14 + sigma0(w6)));
+ Round(c, d, e, f, g, h, a, b, 0x5cb0a9dcul + (w6 += sigma1(w4) + w15 + sigma0(w7)));
+ Round(b, c, d, e, f, g, h, a, 0x76f988daul + (w7 += sigma1(w5) + w0 + sigma0(w8)));
+ Round(a, b, c, d, e, f, g, h, 0x983e5152ul + (w8 += sigma1(w6) + w1 + sigma0(w9)));
+ Round(h, a, b, c, d, e, f, g, 0xa831c66dul + (w9 += sigma1(w7) + w2 + sigma0(w10)));
+ Round(g, h, a, b, c, d, e, f, 0xb00327c8ul + (w10 += sigma1(w8) + w3 + sigma0(w11)));
+ Round(f, g, h, a, b, c, d, e, 0xbf597fc7ul + (w11 += sigma1(w9) + w4 + sigma0(w12)));
+ Round(e, f, g, h, a, b, c, d, 0xc6e00bf3ul + (w12 += sigma1(w10) + w5 + sigma0(w13)));
+ Round(d, e, f, g, h, a, b, c, 0xd5a79147ul + (w13 += sigma1(w11) + w6 + sigma0(w14)));
+ Round(c, d, e, f, g, h, a, b, 0x06ca6351ul + (w14 += sigma1(w12) + w7 + sigma0(w15)));
+ Round(b, c, d, e, f, g, h, a, 0x14292967ul + (w15 += sigma1(w13) + w8 + sigma0(w0)));
+ Round(a, b, c, d, e, f, g, h, 0x27b70a85ul + (w0 += sigma1(w14) + w9 + sigma0(w1)));
+ Round(h, a, b, c, d, e, f, g, 0x2e1b2138ul + (w1 += sigma1(w15) + w10 + sigma0(w2)));
+ Round(g, h, a, b, c, d, e, f, 0x4d2c6dfcul + (w2 += sigma1(w0) + w11 + sigma0(w3)));
+ Round(f, g, h, a, b, c, d, e, 0x53380d13ul + (w3 += sigma1(w1) + w12 + sigma0(w4)));
+ Round(e, f, g, h, a, b, c, d, 0x650a7354ul + (w4 += sigma1(w2) + w13 + sigma0(w5)));
+ Round(d, e, f, g, h, a, b, c, 0x766a0abbul + (w5 += sigma1(w3) + w14 + sigma0(w6)));
+ Round(c, d, e, f, g, h, a, b, 0x81c2c92eul + (w6 += sigma1(w4) + w15 + sigma0(w7)));
+ Round(b, c, d, e, f, g, h, a, 0x92722c85ul + (w7 += sigma1(w5) + w0 + sigma0(w8)));
+ Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1ul + (w8 += sigma1(w6) + w1 + sigma0(w9)));
+ Round(h, a, b, c, d, e, f, g, 0xa81a664bul + (w9 += sigma1(w7) + w2 + sigma0(w10)));
+ Round(g, h, a, b, c, d, e, f, 0xc24b8b70ul + (w10 += sigma1(w8) + w3 + sigma0(w11)));
+ Round(f, g, h, a, b, c, d, e, 0xc76c51a3ul + (w11 += sigma1(w9) + w4 + sigma0(w12)));
+ Round(e, f, g, h, a, b, c, d, 0xd192e819ul + (w12 += sigma1(w10) + w5 + sigma0(w13)));
+ Round(d, e, f, g, h, a, b, c, 0xd6990624ul + (w13 += sigma1(w11) + w6 + sigma0(w14)));
+ Round(c, d, e, f, g, h, a, b, 0xf40e3585ul + (w14 += sigma1(w12) + w7 + sigma0(w15)));
+ Round(b, c, d, e, f, g, h, a, 0x106aa070ul + (w15 += sigma1(w13) + w8 + sigma0(w0)));
+ Round(a, b, c, d, e, f, g, h, 0x19a4c116ul + (w0 += sigma1(w14) + w9 + sigma0(w1)));
+ Round(h, a, b, c, d, e, f, g, 0x1e376c08ul + (w1 += sigma1(w15) + w10 + sigma0(w2)));
+ Round(g, h, a, b, c, d, e, f, 0x2748774cul + (w2 += sigma1(w0) + w11 + sigma0(w3)));
+ Round(f, g, h, a, b, c, d, e, 0x34b0bcb5ul + (w3 += sigma1(w1) + w12 + sigma0(w4)));
+ Round(e, f, g, h, a, b, c, d, 0x391c0cb3ul + (w4 += sigma1(w2) + w13 + sigma0(w5)));
+ Round(d, e, f, g, h, a, b, c, 0x4ed8aa4aul + (w5 += sigma1(w3) + w14 + sigma0(w6)));
+ Round(c, d, e, f, g, h, a, b, 0x5b9cca4ful + (w6 += sigma1(w4) + w15 + sigma0(w7)));
+ Round(b, c, d, e, f, g, h, a, 0x682e6ff3ul + (w7 += sigma1(w5) + w0 + sigma0(w8)));
+ Round(a, b, c, d, e, f, g, h, 0x748f82eeul + (w8 += sigma1(w6) + w1 + sigma0(w9)));
+ Round(h, a, b, c, d, e, f, g, 0x78a5636ful + (w9 += sigma1(w7) + w2 + sigma0(w10)));
+ Round(g, h, a, b, c, d, e, f, 0x84c87814ul + (w10 += sigma1(w8) + w3 + sigma0(w11)));
+ Round(f, g, h, a, b, c, d, e, 0x8cc70208ul + (w11 += sigma1(w9) + w4 + sigma0(w12)));
+ Round(e, f, g, h, a, b, c, d, 0x90befffaul + (w12 += sigma1(w10) + w5 + sigma0(w13)));
+ Round(d, e, f, g, h, a, b, c, 0xa4506cebul + (w13 += sigma1(w11) + w6 + sigma0(w14)));
+ Round(c, d, e, f, g, h, a, b, 0xbef9a3f7ul + (w14 + sigma1(w12) + w7 + sigma0(w15)));
+ Round(b, c, d, e, f, g, h, a, 0xc67178f2ul + (w15 + sigma1(w13) + w8 + sigma0(w0)));
+
+ a += 0x6a09e667ul;
+ b += 0xbb67ae85ul;
+ c += 0x3c6ef372ul;
+ d += 0xa54ff53aul;
+ e += 0x510e527ful;
+ f += 0x9b05688cul;
+ g += 0x1f83d9abul;
+ h += 0x5be0cd19ul;
+
+ uint32_t t0 = a, t1 = b, t2 = c, t3 = d, t4 = e, t5 = f, t6 = g, t7 = h;
+
+ // Transform 2
+ Round(a, b, c, d, e, f, g, h, 0xc28a2f98ul);
+ Round(h, a, b, c, d, e, f, g, 0x71374491ul);
+ Round(g, h, a, b, c, d, e, f, 0xb5c0fbcful);
+ Round(f, g, h, a, b, c, d, e, 0xe9b5dba5ul);
+ Round(e, f, g, h, a, b, c, d, 0x3956c25bul);
+ Round(d, e, f, g, h, a, b, c, 0x59f111f1ul);
+ Round(c, d, e, f, g, h, a, b, 0x923f82a4ul);
+ Round(b, c, d, e, f, g, h, a, 0xab1c5ed5ul);
+ Round(a, b, c, d, e, f, g, h, 0xd807aa98ul);
+ Round(h, a, b, c, d, e, f, g, 0x12835b01ul);
+ Round(g, h, a, b, c, d, e, f, 0x243185beul);
+ Round(f, g, h, a, b, c, d, e, 0x550c7dc3ul);
+ Round(e, f, g, h, a, b, c, d, 0x72be5d74ul);
+ Round(d, e, f, g, h, a, b, c, 0x80deb1feul);
+ Round(c, d, e, f, g, h, a, b, 0x9bdc06a7ul);
+ Round(b, c, d, e, f, g, h, a, 0xc19bf374ul);
+ Round(a, b, c, d, e, f, g, h, 0x649b69c1ul);
+ Round(h, a, b, c, d, e, f, g, 0xf0fe4786ul);
+ Round(g, h, a, b, c, d, e, f, 0x0fe1edc6ul);
+ Round(f, g, h, a, b, c, d, e, 0x240cf254ul);
+ Round(e, f, g, h, a, b, c, d, 0x4fe9346ful);
+ Round(d, e, f, g, h, a, b, c, 0x6cc984beul);
+ Round(c, d, e, f, g, h, a, b, 0x61b9411eul);
+ Round(b, c, d, e, f, g, h, a, 0x16f988faul);
+ Round(a, b, c, d, e, f, g, h, 0xf2c65152ul);
+ Round(h, a, b, c, d, e, f, g, 0xa88e5a6dul);
+ Round(g, h, a, b, c, d, e, f, 0xb019fc65ul);
+ Round(f, g, h, a, b, c, d, e, 0xb9d99ec7ul);
+ Round(e, f, g, h, a, b, c, d, 0x9a1231c3ul);
+ Round(d, e, f, g, h, a, b, c, 0xe70eeaa0ul);
+ Round(c, d, e, f, g, h, a, b, 0xfdb1232bul);
+ Round(b, c, d, e, f, g, h, a, 0xc7353eb0ul);
+ Round(a, b, c, d, e, f, g, h, 0x3069bad5ul);
+ Round(h, a, b, c, d, e, f, g, 0xcb976d5ful);
+ Round(g, h, a, b, c, d, e, f, 0x5a0f118ful);
+ Round(f, g, h, a, b, c, d, e, 0xdc1eeefdul);
+ Round(e, f, g, h, a, b, c, d, 0x0a35b689ul);
+ Round(d, e, f, g, h, a, b, c, 0xde0b7a04ul);
+ Round(c, d, e, f, g, h, a, b, 0x58f4ca9dul);
+ Round(b, c, d, e, f, g, h, a, 0xe15d5b16ul);
+ Round(a, b, c, d, e, f, g, h, 0x007f3e86ul);
+ Round(h, a, b, c, d, e, f, g, 0x37088980ul);
+ Round(g, h, a, b, c, d, e, f, 0xa507ea32ul);
+ Round(f, g, h, a, b, c, d, e, 0x6fab9537ul);
+ Round(e, f, g, h, a, b, c, d, 0x17406110ul);
+ Round(d, e, f, g, h, a, b, c, 0x0d8cd6f1ul);
+ Round(c, d, e, f, g, h, a, b, 0xcdaa3b6dul);
+ Round(b, c, d, e, f, g, h, a, 0xc0bbbe37ul);
+ Round(a, b, c, d, e, f, g, h, 0x83613bdaul);
+ Round(h, a, b, c, d, e, f, g, 0xdb48a363ul);
+ Round(g, h, a, b, c, d, e, f, 0x0b02e931ul);
+ Round(f, g, h, a, b, c, d, e, 0x6fd15ca7ul);
+ Round(e, f, g, h, a, b, c, d, 0x521afacaul);
+ Round(d, e, f, g, h, a, b, c, 0x31338431ul);
+ Round(c, d, e, f, g, h, a, b, 0x6ed41a95ul);
+ Round(b, c, d, e, f, g, h, a, 0x6d437890ul);
+ Round(a, b, c, d, e, f, g, h, 0xc39c91f2ul);
+ Round(h, a, b, c, d, e, f, g, 0x9eccabbdul);
+ Round(g, h, a, b, c, d, e, f, 0xb5c9a0e6ul);
+ Round(f, g, h, a, b, c, d, e, 0x532fb63cul);
+ Round(e, f, g, h, a, b, c, d, 0xd2c741c6ul);
+ Round(d, e, f, g, h, a, b, c, 0x07237ea3ul);
+ Round(c, d, e, f, g, h, a, b, 0xa4954b68ul);
+ Round(b, c, d, e, f, g, h, a, 0x4c191d76ul);
+
+ w0 = t0 + a;
+ w1 = t1 + b;
+ w2 = t2 + c;
+ w3 = t3 + d;
+ w4 = t4 + e;
+ w5 = t5 + f;
+ w6 = t6 + g;
+ w7 = t7 + h;
+
+ // Transform 3
+ a = 0x6a09e667ul;
+ b = 0xbb67ae85ul;
+ c = 0x3c6ef372ul;
+ d = 0xa54ff53aul;
+ e = 0x510e527ful;
+ f = 0x9b05688cul;
+ g = 0x1f83d9abul;
+ h = 0x5be0cd19ul;
+
+ Round(a, b, c, d, e, f, g, h, 0x428a2f98ul + w0);
+ Round(h, a, b, c, d, e, f, g, 0x71374491ul + w1);
+ Round(g, h, a, b, c, d, e, f, 0xb5c0fbcful + w2);
+ Round(f, g, h, a, b, c, d, e, 0xe9b5dba5ul + w3);
+ Round(e, f, g, h, a, b, c, d, 0x3956c25bul + w4);
+ Round(d, e, f, g, h, a, b, c, 0x59f111f1ul + w5);
+ Round(c, d, e, f, g, h, a, b, 0x923f82a4ul + w6);
+ Round(b, c, d, e, f, g, h, a, 0xab1c5ed5ul + w7);
+ Round(a, b, c, d, e, f, g, h, 0x5807aa98ul);
+ Round(h, a, b, c, d, e, f, g, 0x12835b01ul);
+ Round(g, h, a, b, c, d, e, f, 0x243185beul);
+ Round(f, g, h, a, b, c, d, e, 0x550c7dc3ul);
+ Round(e, f, g, h, a, b, c, d, 0x72be5d74ul);
+ Round(d, e, f, g, h, a, b, c, 0x80deb1feul);
+ Round(c, d, e, f, g, h, a, b, 0x9bdc06a7ul);
+ Round(b, c, d, e, f, g, h, a, 0xc19bf274ul);
+ Round(a, b, c, d, e, f, g, h, 0xe49b69c1ul + (w0 += sigma0(w1)));
+ Round(h, a, b, c, d, e, f, g, 0xefbe4786ul + (w1 += 0xa00000ul + sigma0(w2)));
+ Round(g, h, a, b, c, d, e, f, 0x0fc19dc6ul + (w2 += sigma1(w0) + sigma0(w3)));
+ Round(f, g, h, a, b, c, d, e, 0x240ca1ccul + (w3 += sigma1(w1) + sigma0(w4)));
+ Round(e, f, g, h, a, b, c, d, 0x2de92c6ful + (w4 += sigma1(w2) + sigma0(w5)));
+ Round(d, e, f, g, h, a, b, c, 0x4a7484aaul + (w5 += sigma1(w3) + sigma0(w6)));
+ Round(c, d, e, f, g, h, a, b, 0x5cb0a9dcul + (w6 += sigma1(w4) + 0x100ul + sigma0(w7)));
+ Round(b, c, d, e, f, g, h, a, 0x76f988daul + (w7 += sigma1(w5) + w0 + 0x11002000ul));
+ Round(a, b, c, d, e, f, g, h, 0x983e5152ul + (w8 = 0x80000000ul + sigma1(w6) + w1));
+ Round(h, a, b, c, d, e, f, g, 0xa831c66dul + (w9 = sigma1(w7) + w2));
+ Round(g, h, a, b, c, d, e, f, 0xb00327c8ul + (w10 = sigma1(w8) + w3));
+ Round(f, g, h, a, b, c, d, e, 0xbf597fc7ul + (w11 = sigma1(w9) + w4));
+ Round(e, f, g, h, a, b, c, d, 0xc6e00bf3ul + (w12 = sigma1(w10) + w5));
+ Round(d, e, f, g, h, a, b, c, 0xd5a79147ul + (w13 = sigma1(w11) + w6));
+ Round(c, d, e, f, g, h, a, b, 0x06ca6351ul + (w14 = sigma1(w12) + w7 + 0x400022ul));
+ Round(b, c, d, e, f, g, h, a, 0x14292967ul + (w15 = 0x100ul + sigma1(w13) + w8 + sigma0(w0)));
+ Round(a, b, c, d, e, f, g, h, 0x27b70a85ul + (w0 += sigma1(w14) + w9 + sigma0(w1)));
+ Round(h, a, b, c, d, e, f, g, 0x2e1b2138ul + (w1 += sigma1(w15) + w10 + sigma0(w2)));
+ Round(g, h, a, b, c, d, e, f, 0x4d2c6dfcul + (w2 += sigma1(w0) + w11 + sigma0(w3)));
+ Round(f, g, h, a, b, c, d, e, 0x53380d13ul + (w3 += sigma1(w1) + w12 + sigma0(w4)));
+ Round(e, f, g, h, a, b, c, d, 0x650a7354ul + (w4 += sigma1(w2) + w13 + sigma0(w5)));
+ Round(d, e, f, g, h, a, b, c, 0x766a0abbul + (w5 += sigma1(w3) + w14 + sigma0(w6)));
+ Round(c, d, e, f, g, h, a, b, 0x81c2c92eul + (w6 += sigma1(w4) + w15 + sigma0(w7)));
+ Round(b, c, d, e, f, g, h, a, 0x92722c85ul + (w7 += sigma1(w5) + w0 + sigma0(w8)));
+ Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1ul + (w8 += sigma1(w6) + w1 + sigma0(w9)));
+ Round(h, a, b, c, d, e, f, g, 0xa81a664bul + (w9 += sigma1(w7) + w2 + sigma0(w10)));
+ Round(g, h, a, b, c, d, e, f, 0xc24b8b70ul + (w10 += sigma1(w8) + w3 + sigma0(w11)));
+ Round(f, g, h, a, b, c, d, e, 0xc76c51a3ul + (w11 += sigma1(w9) + w4 + sigma0(w12)));
+ Round(e, f, g, h, a, b, c, d, 0xd192e819ul + (w12 += sigma1(w10) + w5 + sigma0(w13)));
+ Round(d, e, f, g, h, a, b, c, 0xd6990624ul + (w13 += sigma1(w11) + w6 + sigma0(w14)));
+ Round(c, d, e, f, g, h, a, b, 0xf40e3585ul + (w14 += sigma1(w12) + w7 + sigma0(w15)));
+ Round(b, c, d, e, f, g, h, a, 0x106aa070ul + (w15 += sigma1(w13) + w8 + sigma0(w0)));
+ Round(a, b, c, d, e, f, g, h, 0x19a4c116ul + (w0 += sigma1(w14) + w9 + sigma0(w1)));
+ Round(h, a, b, c, d, e, f, g, 0x1e376c08ul + (w1 += sigma1(w15) + w10 + sigma0(w2)));
+ Round(g, h, a, b, c, d, e, f, 0x2748774cul + (w2 += sigma1(w0) + w11 + sigma0(w3)));
+ Round(f, g, h, a, b, c, d, e, 0x34b0bcb5ul + (w3 += sigma1(w1) + w12 + sigma0(w4)));
+ Round(e, f, g, h, a, b, c, d, 0x391c0cb3ul + (w4 += sigma1(w2) + w13 + sigma0(w5)));
+ Round(d, e, f, g, h, a, b, c, 0x4ed8aa4aul + (w5 += sigma1(w3) + w14 + sigma0(w6)));
+ Round(c, d, e, f, g, h, a, b, 0x5b9cca4ful + (w6 += sigma1(w4) + w15 + sigma0(w7)));
+ Round(b, c, d, e, f, g, h, a, 0x682e6ff3ul + (w7 += sigma1(w5) + w0 + sigma0(w8)));
+ Round(a, b, c, d, e, f, g, h, 0x748f82eeul + (w8 += sigma1(w6) + w1 + sigma0(w9)));
+ Round(h, a, b, c, d, e, f, g, 0x78a5636ful + (w9 += sigma1(w7) + w2 + sigma0(w10)));
+ Round(g, h, a, b, c, d, e, f, 0x84c87814ul + (w10 += sigma1(w8) + w3 + sigma0(w11)));
+ Round(f, g, h, a, b, c, d, e, 0x8cc70208ul + (w11 += sigma1(w9) + w4 + sigma0(w12)));
+ Round(e, f, g, h, a, b, c, d, 0x90befffaul + (w12 += sigma1(w10) + w5 + sigma0(w13)));
+ Round(d, e, f, g, h, a, b, c, 0xa4506cebul + (w13 += sigma1(w11) + w6 + sigma0(w14)));
+ Round(c, d, e, f, g, h, a, b, 0xbef9a3f7ul + (w14 + sigma1(w12) + w7 + sigma0(w15)));
+ Round(b, c, d, e, f, g, h, a, 0xc67178f2ul + (w15 + sigma1(w13) + w8 + sigma0(w0)));
+
+ // Output
+ WriteBE32(out + 0, a + 0x6a09e667ul);
+ WriteBE32(out + 4, b + 0xbb67ae85ul);
+ WriteBE32(out + 8, c + 0x3c6ef372ul);
+ WriteBE32(out + 12, d + 0xa54ff53aul);
+ WriteBE32(out + 16, e + 0x510e527ful);
+ WriteBE32(out + 20, f + 0x9b05688cul);
+ WriteBE32(out + 24, g + 0x1f83d9abul);
+ WriteBE32(out + 28, h + 0x5be0cd19ul);
+}
+
} // namespace sha256
typedef void (*TransformType)(uint32_t*, const unsigned char*, size_t);
+typedef void (*TransformD64Type)(unsigned char*, const unsigned char*);
+
+template<TransformType tr>
+void TransformD64Wrapper(unsigned char* out, const unsigned char* in)
+{
+ uint32_t s[8];
+ static const unsigned char padding1[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0
+ };
+ unsigned char buffer2[64] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0
+ };
+ sha256::Initialize(s);
+ tr(s, in, 1);
+ tr(s, padding1, 1);
+ WriteBE32(buffer2 + 0, s[0]);
+ WriteBE32(buffer2 + 4, s[1]);
+ WriteBE32(buffer2 + 8, s[2]);
+ WriteBE32(buffer2 + 12, s[3]);
+ WriteBE32(buffer2 + 16, s[4]);
+ WriteBE32(buffer2 + 20, s[5]);
+ WriteBE32(buffer2 + 24, s[6]);
+ WriteBE32(buffer2 + 28, s[7]);
+ sha256::Initialize(s);
+ tr(s, buffer2, 1);
+ WriteBE32(out + 0, s[0]);
+ WriteBE32(out + 4, s[1]);
+ WriteBE32(out + 8, s[2]);
+ WriteBE32(out + 12, s[3]);
+ WriteBE32(out + 16, s[4]);
+ WriteBE32(out + 20, s[5]);
+ WriteBE32(out + 24, s[6]);
+ WriteBE32(out + 28, s[7]);
+}
bool SelfTest(TransformType tr) {
static const unsigned char in1[65] = {0, 0x80};
@@ -173,22 +474,47 @@ bool SelfTest(TransformType tr) {
}
TransformType Transform = sha256::Transform;
+TransformD64Type TransformD64 = sha256::TransformD64;
+TransformD64Type TransformD64_4way = nullptr;
+TransformD64Type TransformD64_8way = nullptr;
+#if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__))
+// We can't use cpuid.h's __get_cpuid as it does not support subleafs.
+void inline cpuid(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d)
+{
+ __asm__ ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(leaf), "2"(subleaf));
+}
+#endif
} // namespace
+
std::string SHA256AutoDetect()
{
+ std::string ret = "standard";
#if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__))
uint32_t eax, ebx, ecx, edx;
- if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx >> 19) & 1) {
+ cpuid(1, 0, eax, ebx, ecx, edx);
+ if ((ecx >> 19) & 1) {
Transform = sha256_sse4::Transform;
- assert(SelfTest(Transform));
- return "sse4";
+ TransformD64 = TransformD64Wrapper<sha256_sse4::Transform>;
+#if defined(ENABLE_SSE41) && !defined(BUILD_BITCOIN_INTERNAL)
+ TransformD64_4way = sha256d64_sse41::Transform_4way;
+ ret = "sse4(1way+4way)";
+#if defined(ENABLE_AVX2) && !defined(BUILD_BITCOIN_INTERNAL)
+ cpuid(7, 0, eax, ebx, ecx, edx);
+ if ((ebx >> 5) & 1) {
+ TransformD64_8way = sha256d64_avx2::Transform_8way;
+ ret += ",avx2(8way)";
+ }
+#endif
+#else
+ ret = "sse4";
+#endif
}
#endif
assert(SelfTest(Transform));
- return "standard";
+ return ret;
}
////// SHA-256
@@ -247,3 +573,29 @@ CSHA256& CSHA256::Reset()
sha256::Initialize(s);
return *this;
}
+
+void SHA256D64(unsigned char* out, const unsigned char* in, size_t blocks)
+{
+ if (TransformD64_8way) {
+ while (blocks >= 8) {
+ TransformD64_8way(out, in);
+ out += 256;
+ in += 512;
+ blocks -= 8;
+ }
+ }
+ if (TransformD64_4way) {
+ while (blocks >= 4) {
+ TransformD64_4way(out, in);
+ out += 128;
+ in += 256;
+ blocks -= 4;
+ }
+ }
+ while (blocks) {
+ TransformD64(out, in);
+ out += 32;
+ in += 64;
+ --blocks;
+ }
+}
diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h
index dd30fe396f..31b2b3b3df 100644
--- a/src/crypto/sha256.h
+++ b/src/crypto/sha256.h
@@ -31,4 +31,11 @@ public:
*/
std::string SHA256AutoDetect();
+/** Compute multiple double-SHA256's of 64-byte blobs.
+ * output: pointer to a blocks*32 byte output buffer
+ * input: pointer to a blocks*64 byte input buffer
+ * blocks: the number of hashes to compute.
+ */
+void SHA256D64(unsigned char* output, const unsigned char* input, size_t blocks);
+
#endif // BITCOIN_CRYPTO_SHA256_H
diff --git a/src/crypto/sha256_avx2.cpp b/src/crypto/sha256_avx2.cpp
new file mode 100644
index 0000000000..f45c1d4ab6
--- /dev/null
+++ b/src/crypto/sha256_avx2.cpp
@@ -0,0 +1,329 @@
+#ifdef ENABLE_AVX2
+
+#include <stdint.h>
+#if defined(_MSC_VER)
+#include <immintrin.h>
+#elif defined(__GNUC__)
+#include <x86intrin.h>
+#endif
+
+#include "crypto/sha256.h"
+#include "crypto/common.h"
+
+namespace sha256d64_avx2 {
+namespace {
+
+__m256i inline K(uint32_t x) { return _mm256_set1_epi32(x); }
+
+__m256i inline Add(__m256i x, __m256i y) { return _mm256_add_epi32(x, y); }
+__m256i inline Add(__m256i x, __m256i y, __m256i z) { return Add(Add(x, y), z); }
+__m256i inline Add(__m256i x, __m256i y, __m256i z, __m256i w) { return Add(Add(x, y), Add(z, w)); }
+__m256i inline Add(__m256i x, __m256i y, __m256i z, __m256i w, __m256i v) { return Add(Add(x, y, z), Add(w, v)); }
+__m256i inline Inc(__m256i& x, __m256i y) { x = Add(x, y); return x; }
+__m256i inline Inc(__m256i& x, __m256i y, __m256i z) { x = Add(x, y, z); return x; }
+__m256i inline Inc(__m256i& x, __m256i y, __m256i z, __m256i w) { x = Add(x, y, z, w); return x; }
+__m256i inline Xor(__m256i x, __m256i y) { return _mm256_xor_si256(x, y); }
+__m256i inline Xor(__m256i x, __m256i y, __m256i z) { return Xor(Xor(x, y), z); }
+__m256i inline Or(__m256i x, __m256i y) { return _mm256_or_si256(x, y); }
+__m256i inline And(__m256i x, __m256i y) { return _mm256_and_si256(x, y); }
+__m256i inline ShR(__m256i x, int n) { return _mm256_srli_epi32(x, n); }
+__m256i inline ShL(__m256i x, int n) { return _mm256_slli_epi32(x, n); }
+
+__m256i inline Ch(__m256i x, __m256i y, __m256i z) { return Xor(z, And(x, Xor(y, z))); }
+__m256i inline Maj(__m256i x, __m256i y, __m256i z) { return Or(And(x, y), And(z, Or(x, y))); }
+__m256i inline Sigma0(__m256i x) { return Xor(Or(ShR(x, 2), ShL(x, 30)), Or(ShR(x, 13), ShL(x, 19)), Or(ShR(x, 22), ShL(x, 10))); }
+__m256i inline Sigma1(__m256i x) { return Xor(Or(ShR(x, 6), ShL(x, 26)), Or(ShR(x, 11), ShL(x, 21)), Or(ShR(x, 25), ShL(x, 7))); }
+__m256i inline sigma0(__m256i x) { return Xor(Or(ShR(x, 7), ShL(x, 25)), Or(ShR(x, 18), ShL(x, 14)), ShR(x, 3)); }
+__m256i inline sigma1(__m256i x) { return Xor(Or(ShR(x, 17), ShL(x, 15)), Or(ShR(x, 19), ShL(x, 13)), ShR(x, 10)); }
+
+/** One round of SHA-256. */
+void inline __attribute__((always_inline)) Round(__m256i a, __m256i b, __m256i c, __m256i& d, __m256i e, __m256i f, __m256i g, __m256i& h, __m256i k)
+{
+ __m256i t1 = Add(h, Sigma1(e), Ch(e, f, g), k);
+ __m256i t2 = Add(Sigma0(a), Maj(a, b, c));
+ d = Add(d, t1);
+ h = Add(t1, t2);
+}
+
+__m256i inline Read8(const unsigned char* chunk, int offset) {
+ __m256i ret = _mm256_set_epi32(
+ ReadLE32(chunk + 0 + offset),
+ ReadLE32(chunk + 64 + offset),
+ ReadLE32(chunk + 128 + offset),
+ ReadLE32(chunk + 192 + offset),
+ ReadLE32(chunk + 256 + offset),
+ ReadLE32(chunk + 320 + offset),
+ ReadLE32(chunk + 384 + offset),
+ ReadLE32(chunk + 448 + offset)
+ );
+ return _mm256_shuffle_epi8(ret, _mm256_set_epi32(0x0C0D0E0FUL, 0x08090A0BUL, 0x04050607UL, 0x00010203UL, 0x0C0D0E0FUL, 0x08090A0BUL, 0x04050607UL, 0x00010203UL));
+}
+
+void inline Write8(unsigned char* out, int offset, __m256i v) {
+ v = _mm256_shuffle_epi8(v, _mm256_set_epi32(0x0C0D0E0FUL, 0x08090A0BUL, 0x04050607UL, 0x00010203UL, 0x0C0D0E0FUL, 0x08090A0BUL, 0x04050607UL, 0x00010203UL));
+ WriteLE32(out + 0 + offset, _mm256_extract_epi32(v, 7));
+ WriteLE32(out + 32 + offset, _mm256_extract_epi32(v, 6));
+ WriteLE32(out + 64 + offset, _mm256_extract_epi32(v, 5));
+ WriteLE32(out + 96 + offset, _mm256_extract_epi32(v, 4));
+ WriteLE32(out + 128 + offset, _mm256_extract_epi32(v, 3));
+ WriteLE32(out + 160 + offset, _mm256_extract_epi32(v, 2));
+ WriteLE32(out + 192 + offset, _mm256_extract_epi32(v, 1));
+ WriteLE32(out + 224 + offset, _mm256_extract_epi32(v, 0));
+}
+
+}
+
+void Transform_8way(unsigned char* out, const unsigned char* in)
+{
+ // Transform 1
+ __m256i a = K(0x6a09e667ul);
+ __m256i b = K(0xbb67ae85ul);
+ __m256i c = K(0x3c6ef372ul);
+ __m256i d = K(0xa54ff53aul);
+ __m256i e = K(0x510e527ful);
+ __m256i f = K(0x9b05688cul);
+ __m256i g = K(0x1f83d9abul);
+ __m256i h = K(0x5be0cd19ul);
+
+ __m256i w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
+
+ Round(a, b, c, d, e, f, g, h, Add(K(0x428a2f98ul), w0 = Read8(in, 0)));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x71374491ul), w1 = Read8(in, 4)));
+ Round(g, h, a, b, c, d, e, f, Add(K(0xb5c0fbcful), w2 = Read8(in, 8)));
+ Round(f, g, h, a, b, c, d, e, Add(K(0xe9b5dba5ul), w3 = Read8(in, 12)));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x3956c25bul), w4 = Read8(in, 16)));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x59f111f1ul), w5 = Read8(in, 20)));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x923f82a4ul), w6 = Read8(in, 24)));
+ Round(b, c, d, e, f, g, h, a, Add(K(0xab1c5ed5ul), w7 = Read8(in, 28)));
+ Round(a, b, c, d, e, f, g, h, Add(K(0xd807aa98ul), w8 = Read8(in, 32)));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x12835b01ul), w9 = Read8(in, 36)));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x243185beul), w10 = Read8(in, 40)));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x550c7dc3ul), w11 = Read8(in, 44)));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x72be5d74ul), w12 = Read8(in, 48)));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x80deb1feul), w13 = Read8(in, 52)));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x9bdc06a7ul), w14 = Read8(in, 56)));
+ Round(b, c, d, e, f, g, h, a, Add(K(0xc19bf174ul), w15 = Read8(in, 60)));
+ Round(a, b, c, d, e, f, g, h, Add(K(0xe49b69c1ul), Inc(w0, sigma1(w14), w9, sigma0(w1))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0xefbe4786ul), Inc(w1, sigma1(w15), w10, sigma0(w2))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x0fc19dc6ul), Inc(w2, sigma1(w0), w11, sigma0(w3))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x240ca1ccul), Inc(w3, sigma1(w1), w12, sigma0(w4))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x2de92c6ful), Inc(w4, sigma1(w2), w13, sigma0(w5))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x4a7484aaul), Inc(w5, sigma1(w3), w14, sigma0(w6))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x5cb0a9dcul), Inc(w6, sigma1(w4), w15, sigma0(w7))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x76f988daul), Inc(w7, sigma1(w5), w0, sigma0(w8))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x983e5152ul), Inc(w8, sigma1(w6), w1, sigma0(w9))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0xa831c66dul), Inc(w9, sigma1(w7), w2, sigma0(w10))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0xb00327c8ul), Inc(w10, sigma1(w8), w3, sigma0(w11))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0xbf597fc7ul), Inc(w11, sigma1(w9), w4, sigma0(w12))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0xc6e00bf3ul), Inc(w12, sigma1(w10), w5, sigma0(w13))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0xd5a79147ul), Inc(w13, sigma1(w11), w6, sigma0(w14))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x06ca6351ul), Inc(w14, sigma1(w12), w7, sigma0(w15))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x14292967ul), Inc(w15, sigma1(w13), w8, sigma0(w0))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x27b70a85ul), Inc(w0, sigma1(w14), w9, sigma0(w1))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x2e1b2138ul), Inc(w1, sigma1(w15), w10, sigma0(w2))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x4d2c6dfcul), Inc(w2, sigma1(w0), w11, sigma0(w3))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x53380d13ul), Inc(w3, sigma1(w1), w12, sigma0(w4))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x650a7354ul), Inc(w4, sigma1(w2), w13, sigma0(w5))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x766a0abbul), Inc(w5, sigma1(w3), w14, sigma0(w6))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x81c2c92eul), Inc(w6, sigma1(w4), w15, sigma0(w7))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x92722c85ul), Inc(w7, sigma1(w5), w0, sigma0(w8))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0xa2bfe8a1ul), Inc(w8, sigma1(w6), w1, sigma0(w9))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0xa81a664bul), Inc(w9, sigma1(w7), w2, sigma0(w10))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0xc24b8b70ul), Inc(w10, sigma1(w8), w3, sigma0(w11))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0xc76c51a3ul), Inc(w11, sigma1(w9), w4, sigma0(w12))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0xd192e819ul), Inc(w12, sigma1(w10), w5, sigma0(w13))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0xd6990624ul), Inc(w13, sigma1(w11), w6, sigma0(w14))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0xf40e3585ul), Inc(w14, sigma1(w12), w7, sigma0(w15))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x106aa070ul), Inc(w15, sigma1(w13), w8, sigma0(w0))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x19a4c116ul), Inc(w0, sigma1(w14), w9, sigma0(w1))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x1e376c08ul), Inc(w1, sigma1(w15), w10, sigma0(w2))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x2748774cul), Inc(w2, sigma1(w0), w11, sigma0(w3))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x34b0bcb5ul), Inc(w3, sigma1(w1), w12, sigma0(w4))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x391c0cb3ul), Inc(w4, sigma1(w2), w13, sigma0(w5))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x4ed8aa4aul), Inc(w5, sigma1(w3), w14, sigma0(w6))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x5b9cca4ful), Inc(w6, sigma1(w4), w15, sigma0(w7))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x682e6ff3ul), Inc(w7, sigma1(w5), w0, sigma0(w8))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x748f82eeul), Inc(w8, sigma1(w6), w1, sigma0(w9))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x78a5636ful), Inc(w9, sigma1(w7), w2, sigma0(w10))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x84c87814ul), Inc(w10, sigma1(w8), w3, sigma0(w11))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x8cc70208ul), Inc(w11, sigma1(w9), w4, sigma0(w12))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x90befffaul), Inc(w12, sigma1(w10), w5, sigma0(w13))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0xa4506cebul), Inc(w13, sigma1(w11), w6, sigma0(w14))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0xbef9a3f7ul), Inc(w14, sigma1(w12), w7, sigma0(w15))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0xc67178f2ul), Inc(w15, sigma1(w13), w8, sigma0(w0))));
+
+ a = Add(a, K(0x6a09e667ul));
+ b = Add(b, K(0xbb67ae85ul));
+ c = Add(c, K(0x3c6ef372ul));
+ d = Add(d, K(0xa54ff53aul));
+ e = Add(e, K(0x510e527ful));
+ f = Add(f, K(0x9b05688cul));
+ g = Add(g, K(0x1f83d9abul));
+ h = Add(h, K(0x5be0cd19ul));
+
+ __m256i t0 = a, t1 = b, t2 = c, t3 = d, t4 = e, t5 = f, t6 = g, t7 = h;
+
+ // Transform 2
+ Round(a, b, c, d, e, f, g, h, K(0xc28a2f98ul));
+ Round(h, a, b, c, d, e, f, g, K(0x71374491ul));
+ Round(g, h, a, b, c, d, e, f, K(0xb5c0fbcful));
+ Round(f, g, h, a, b, c, d, e, K(0xe9b5dba5ul));
+ Round(e, f, g, h, a, b, c, d, K(0x3956c25bul));
+ Round(d, e, f, g, h, a, b, c, K(0x59f111f1ul));
+ Round(c, d, e, f, g, h, a, b, K(0x923f82a4ul));
+ Round(b, c, d, e, f, g, h, a, K(0xab1c5ed5ul));
+ Round(a, b, c, d, e, f, g, h, K(0xd807aa98ul));
+ Round(h, a, b, c, d, e, f, g, K(0x12835b01ul));
+ Round(g, h, a, b, c, d, e, f, K(0x243185beul));
+ Round(f, g, h, a, b, c, d, e, K(0x550c7dc3ul));
+ Round(e, f, g, h, a, b, c, d, K(0x72be5d74ul));
+ Round(d, e, f, g, h, a, b, c, K(0x80deb1feul));
+ Round(c, d, e, f, g, h, a, b, K(0x9bdc06a7ul));
+ Round(b, c, d, e, f, g, h, a, K(0xc19bf374ul));
+ Round(a, b, c, d, e, f, g, h, K(0x649b69c1ul));
+ Round(h, a, b, c, d, e, f, g, K(0xf0fe4786ul));
+ Round(g, h, a, b, c, d, e, f, K(0x0fe1edc6ul));
+ Round(f, g, h, a, b, c, d, e, K(0x240cf254ul));
+ Round(e, f, g, h, a, b, c, d, K(0x4fe9346ful));
+ Round(d, e, f, g, h, a, b, c, K(0x6cc984beul));
+ Round(c, d, e, f, g, h, a, b, K(0x61b9411eul));
+ Round(b, c, d, e, f, g, h, a, K(0x16f988faul));
+ Round(a, b, c, d, e, f, g, h, K(0xf2c65152ul));
+ Round(h, a, b, c, d, e, f, g, K(0xa88e5a6dul));
+ Round(g, h, a, b, c, d, e, f, K(0xb019fc65ul));
+ Round(f, g, h, a, b, c, d, e, K(0xb9d99ec7ul));
+ Round(e, f, g, h, a, b, c, d, K(0x9a1231c3ul));
+ Round(d, e, f, g, h, a, b, c, K(0xe70eeaa0ul));
+ Round(c, d, e, f, g, h, a, b, K(0xfdb1232bul));
+ Round(b, c, d, e, f, g, h, a, K(0xc7353eb0ul));
+ Round(a, b, c, d, e, f, g, h, K(0x3069bad5ul));
+ Round(h, a, b, c, d, e, f, g, K(0xcb976d5ful));
+ Round(g, h, a, b, c, d, e, f, K(0x5a0f118ful));
+ Round(f, g, h, a, b, c, d, e, K(0xdc1eeefdul));
+ Round(e, f, g, h, a, b, c, d, K(0x0a35b689ul));
+ Round(d, e, f, g, h, a, b, c, K(0xde0b7a04ul));
+ Round(c, d, e, f, g, h, a, b, K(0x58f4ca9dul));
+ Round(b, c, d, e, f, g, h, a, K(0xe15d5b16ul));
+ Round(a, b, c, d, e, f, g, h, K(0x007f3e86ul));
+ Round(h, a, b, c, d, e, f, g, K(0x37088980ul));
+ Round(g, h, a, b, c, d, e, f, K(0xa507ea32ul));
+ Round(f, g, h, a, b, c, d, e, K(0x6fab9537ul));
+ Round(e, f, g, h, a, b, c, d, K(0x17406110ul));
+ Round(d, e, f, g, h, a, b, c, K(0x0d8cd6f1ul));
+ Round(c, d, e, f, g, h, a, b, K(0xcdaa3b6dul));
+ Round(b, c, d, e, f, g, h, a, K(0xc0bbbe37ul));
+ Round(a, b, c, d, e, f, g, h, K(0x83613bdaul));
+ Round(h, a, b, c, d, e, f, g, K(0xdb48a363ul));
+ Round(g, h, a, b, c, d, e, f, K(0x0b02e931ul));
+ Round(f, g, h, a, b, c, d, e, K(0x6fd15ca7ul));
+ Round(e, f, g, h, a, b, c, d, K(0x521afacaul));
+ Round(d, e, f, g, h, a, b, c, K(0x31338431ul));
+ Round(c, d, e, f, g, h, a, b, K(0x6ed41a95ul));
+ Round(b, c, d, e, f, g, h, a, K(0x6d437890ul));
+ Round(a, b, c, d, e, f, g, h, K(0xc39c91f2ul));
+ Round(h, a, b, c, d, e, f, g, K(0x9eccabbdul));
+ Round(g, h, a, b, c, d, e, f, K(0xb5c9a0e6ul));
+ Round(f, g, h, a, b, c, d, e, K(0x532fb63cul));
+ Round(e, f, g, h, a, b, c, d, K(0xd2c741c6ul));
+ Round(d, e, f, g, h, a, b, c, K(0x07237ea3ul));
+ Round(c, d, e, f, g, h, a, b, K(0xa4954b68ul));
+ Round(b, c, d, e, f, g, h, a, K(0x4c191d76ul));
+
+ w0 = Add(t0, a);
+ w1 = Add(t1, b);
+ w2 = Add(t2, c);
+ w3 = Add(t3, d);
+ w4 = Add(t4, e);
+ w5 = Add(t5, f);
+ w6 = Add(t6, g);
+ w7 = Add(t7, h);
+
+ // Transform 3
+ a = K(0x6a09e667ul);
+ b = K(0xbb67ae85ul);
+ c = K(0x3c6ef372ul);
+ d = K(0xa54ff53aul);
+ e = K(0x510e527ful);
+ f = K(0x9b05688cul);
+ g = K(0x1f83d9abul);
+ h = K(0x5be0cd19ul);
+
+ Round(a, b, c, d, e, f, g, h, Add(K(0x428a2f98ul), w0));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x71374491ul), w1));
+ Round(g, h, a, b, c, d, e, f, Add(K(0xb5c0fbcful), w2));
+ Round(f, g, h, a, b, c, d, e, Add(K(0xe9b5dba5ul), w3));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x3956c25bul), w4));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x59f111f1ul), w5));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x923f82a4ul), w6));
+ Round(b, c, d, e, f, g, h, a, Add(K(0xab1c5ed5ul), w7));
+ Round(a, b, c, d, e, f, g, h, K(0x5807aa98ul));
+ Round(h, a, b, c, d, e, f, g, K(0x12835b01ul));
+ Round(g, h, a, b, c, d, e, f, K(0x243185beul));
+ Round(f, g, h, a, b, c, d, e, K(0x550c7dc3ul));
+ Round(e, f, g, h, a, b, c, d, K(0x72be5d74ul));
+ Round(d, e, f, g, h, a, b, c, K(0x80deb1feul));
+ Round(c, d, e, f, g, h, a, b, K(0x9bdc06a7ul));
+ Round(b, c, d, e, f, g, h, a, K(0xc19bf274ul));
+ Round(a, b, c, d, e, f, g, h, Add(K(0xe49b69c1ul), Inc(w0, sigma0(w1))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0xefbe4786ul), Inc(w1, K(0xa00000ul), sigma0(w2))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x0fc19dc6ul), Inc(w2, sigma1(w0), sigma0(w3))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x240ca1ccul), Inc(w3, sigma1(w1), sigma0(w4))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x2de92c6ful), Inc(w4, sigma1(w2), sigma0(w5))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x4a7484aaul), Inc(w5, sigma1(w3), sigma0(w6))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x5cb0a9dcul), Inc(w6, sigma1(w4), K(0x100ul), sigma0(w7))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x76f988daul), Inc(w7, sigma1(w5), w0, K(0x11002000ul))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x983e5152ul), w8 = Add(K(0x80000000ul), sigma1(w6), w1)));
+ Round(h, a, b, c, d, e, f, g, Add(K(0xa831c66dul), w9 = Add(sigma1(w7), w2)));
+ Round(g, h, a, b, c, d, e, f, Add(K(0xb00327c8ul), w10 = Add(sigma1(w8), w3)));
+ Round(f, g, h, a, b, c, d, e, Add(K(0xbf597fc7ul), w11 = Add(sigma1(w9), w4)));
+ Round(e, f, g, h, a, b, c, d, Add(K(0xc6e00bf3ul), w12 = Add(sigma1(w10), w5)));
+ Round(d, e, f, g, h, a, b, c, Add(K(0xd5a79147ul), w13 = Add(sigma1(w11), w6)));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x06ca6351ul), w14 = Add(sigma1(w12), w7, K(0x400022ul))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x14292967ul), w15 = Add(K(0x100ul), sigma1(w13), w8, sigma0(w0))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x27b70a85ul), Inc(w0, sigma1(w14), w9, sigma0(w1))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x2e1b2138ul), Inc(w1, sigma1(w15), w10, sigma0(w2))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x4d2c6dfcul), Inc(w2, sigma1(w0), w11, sigma0(w3))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x53380d13ul), Inc(w3, sigma1(w1), w12, sigma0(w4))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x650a7354ul), Inc(w4, sigma1(w2), w13, sigma0(w5))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x766a0abbul), Inc(w5, sigma1(w3), w14, sigma0(w6))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x81c2c92eul), Inc(w6, sigma1(w4), w15, sigma0(w7))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x92722c85ul), Inc(w7, sigma1(w5), w0, sigma0(w8))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0xa2bfe8a1ul), Inc(w8, sigma1(w6), w1, sigma0(w9))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0xa81a664bul), Inc(w9, sigma1(w7), w2, sigma0(w10))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0xc24b8b70ul), Inc(w10, sigma1(w8), w3, sigma0(w11))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0xc76c51a3ul), Inc(w11, sigma1(w9), w4, sigma0(w12))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0xd192e819ul), Inc(w12, sigma1(w10), w5, sigma0(w13))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0xd6990624ul), Inc(w13, sigma1(w11), w6, sigma0(w14))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0xf40e3585ul), Inc(w14, sigma1(w12), w7, sigma0(w15))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x106aa070ul), Inc(w15, sigma1(w13), w8, sigma0(w0))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x19a4c116ul), Inc(w0, sigma1(w14), w9, sigma0(w1))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x1e376c08ul), Inc(w1, sigma1(w15), w10, sigma0(w2))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x2748774cul), Inc(w2, sigma1(w0), w11, sigma0(w3))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x34b0bcb5ul), Inc(w3, sigma1(w1), w12, sigma0(w4))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x391c0cb3ul), Inc(w4, sigma1(w2), w13, sigma0(w5))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x4ed8aa4aul), Inc(w5, sigma1(w3), w14, sigma0(w6))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x5b9cca4ful), Inc(w6, sigma1(w4), w15, sigma0(w7))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x682e6ff3ul), Inc(w7, sigma1(w5), w0, sigma0(w8))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x748f82eeul), Inc(w8, sigma1(w6), w1, sigma0(w9))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x78a5636ful), Inc(w9, sigma1(w7), w2, sigma0(w10))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x84c87814ul), Inc(w10, sigma1(w8), w3, sigma0(w11))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x8cc70208ul), Inc(w11, sigma1(w9), w4, sigma0(w12))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x90befffaul), Inc(w12, sigma1(w10), w5, sigma0(w13))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0xa4506cebul), Inc(w13, sigma1(w11), w6, sigma0(w14))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0xbef9a3f7ul), w14, sigma1(w12), w7, sigma0(w15)));
+ Round(b, c, d, e, f, g, h, a, Add(K(0xc67178f2ul), w15, sigma1(w13), w8, sigma0(w0)));
+
+ // Output
+ Write8(out, 0, Add(a, K(0x6a09e667ul)));
+ Write8(out, 4, Add(b, K(0xbb67ae85ul)));
+ Write8(out, 8, Add(c, K(0x3c6ef372ul)));
+ Write8(out, 12, Add(d, K(0xa54ff53aul)));
+ Write8(out, 16, Add(e, K(0x510e527ful)));
+ Write8(out, 20, Add(f, K(0x9b05688cul)));
+ Write8(out, 24, Add(g, K(0x1f83d9abul)));
+ Write8(out, 28, Add(h, K(0x5be0cd19ul)));
+}
+
+}
+
+#endif
diff --git a/src/crypto/sha256_sse41.cpp b/src/crypto/sha256_sse41.cpp
new file mode 100644
index 0000000000..a11d658c70
--- /dev/null
+++ b/src/crypto/sha256_sse41.cpp
@@ -0,0 +1,321 @@
+#ifdef ENABLE_SSE41
+
+#include <stdint.h>
+#if defined(_MSC_VER)
+#include <immintrin.h>
+#elif defined(__GNUC__)
+#include <x86intrin.h>
+#endif
+
+#include "crypto/sha256.h"
+#include "crypto/common.h"
+
+namespace sha256d64_sse41 {
+namespace {
+
+__m128i inline K(uint32_t x) { return _mm_set1_epi32(x); }
+
+__m128i inline Add(__m128i x, __m128i y) { return _mm_add_epi32(x, y); }
+__m128i inline Add(__m128i x, __m128i y, __m128i z) { return Add(Add(x, y), z); }
+__m128i inline Add(__m128i x, __m128i y, __m128i z, __m128i w) { return Add(Add(x, y), Add(z, w)); }
+__m128i inline Add(__m128i x, __m128i y, __m128i z, __m128i w, __m128i v) { return Add(Add(x, y, z), Add(w, v)); }
+__m128i inline Inc(__m128i& x, __m128i y) { x = Add(x, y); return x; }
+__m128i inline Inc(__m128i& x, __m128i y, __m128i z) { x = Add(x, y, z); return x; }
+__m128i inline Inc(__m128i& x, __m128i y, __m128i z, __m128i w) { x = Add(x, y, z, w); return x; }
+__m128i inline Xor(__m128i x, __m128i y) { return _mm_xor_si128(x, y); }
+__m128i inline Xor(__m128i x, __m128i y, __m128i z) { return Xor(Xor(x, y), z); }
+__m128i inline Or(__m128i x, __m128i y) { return _mm_or_si128(x, y); }
+__m128i inline And(__m128i x, __m128i y) { return _mm_and_si128(x, y); }
+__m128i inline ShR(__m128i x, int n) { return _mm_srli_epi32(x, n); }
+__m128i inline ShL(__m128i x, int n) { return _mm_slli_epi32(x, n); }
+
+__m128i inline Ch(__m128i x, __m128i y, __m128i z) { return Xor(z, And(x, Xor(y, z))); }
+__m128i inline Maj(__m128i x, __m128i y, __m128i z) { return Or(And(x, y), And(z, Or(x, y))); }
+__m128i inline Sigma0(__m128i x) { return Xor(Or(ShR(x, 2), ShL(x, 30)), Or(ShR(x, 13), ShL(x, 19)), Or(ShR(x, 22), ShL(x, 10))); }
+__m128i inline Sigma1(__m128i x) { return Xor(Or(ShR(x, 6), ShL(x, 26)), Or(ShR(x, 11), ShL(x, 21)), Or(ShR(x, 25), ShL(x, 7))); }
+__m128i inline sigma0(__m128i x) { return Xor(Or(ShR(x, 7), ShL(x, 25)), Or(ShR(x, 18), ShL(x, 14)), ShR(x, 3)); }
+__m128i inline sigma1(__m128i x) { return Xor(Or(ShR(x, 17), ShL(x, 15)), Or(ShR(x, 19), ShL(x, 13)), ShR(x, 10)); }
+
+/** One round of SHA-256. */
+void inline __attribute__((always_inline)) Round(__m128i a, __m128i b, __m128i c, __m128i& d, __m128i e, __m128i f, __m128i g, __m128i& h, __m128i k)
+{
+ __m128i t1 = Add(h, Sigma1(e), Ch(e, f, g), k);
+ __m128i t2 = Add(Sigma0(a), Maj(a, b, c));
+ d = Add(d, t1);
+ h = Add(t1, t2);
+}
+
+__m128i inline Read4(const unsigned char* chunk, int offset) {
+ __m128i ret = _mm_set_epi32(
+ ReadLE32(chunk + 0 + offset),
+ ReadLE32(chunk + 64 + offset),
+ ReadLE32(chunk + 128 + offset),
+ ReadLE32(chunk + 192 + offset)
+ );
+ return _mm_shuffle_epi8(ret, _mm_set_epi32(0x0C0D0E0FUL, 0x08090A0BUL, 0x04050607UL, 0x00010203UL));
+}
+
+void inline Write4(unsigned char* out, int offset, __m128i v) {
+ v = _mm_shuffle_epi8(v, _mm_set_epi32(0x0C0D0E0FUL, 0x08090A0BUL, 0x04050607UL, 0x00010203UL));
+ WriteLE32(out + 0 + offset, _mm_extract_epi32(v, 3));
+ WriteLE32(out + 32 + offset, _mm_extract_epi32(v, 2));
+ WriteLE32(out + 64 + offset, _mm_extract_epi32(v, 1));
+ WriteLE32(out + 96 + offset, _mm_extract_epi32(v, 0));
+}
+
+}
+
+void Transform_4way(unsigned char* out, const unsigned char* in)
+{
+ // Transform 1
+ __m128i a = K(0x6a09e667ul);
+ __m128i b = K(0xbb67ae85ul);
+ __m128i c = K(0x3c6ef372ul);
+ __m128i d = K(0xa54ff53aul);
+ __m128i e = K(0x510e527ful);
+ __m128i f = K(0x9b05688cul);
+ __m128i g = K(0x1f83d9abul);
+ __m128i h = K(0x5be0cd19ul);
+
+ __m128i w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
+
+ Round(a, b, c, d, e, f, g, h, Add(K(0x428a2f98ul), w0 = Read4(in, 0)));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x71374491ul), w1 = Read4(in, 4)));
+ Round(g, h, a, b, c, d, e, f, Add(K(0xb5c0fbcful), w2 = Read4(in, 8)));
+ Round(f, g, h, a, b, c, d, e, Add(K(0xe9b5dba5ul), w3 = Read4(in, 12)));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x3956c25bul), w4 = Read4(in, 16)));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x59f111f1ul), w5 = Read4(in, 20)));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x923f82a4ul), w6 = Read4(in, 24)));
+ Round(b, c, d, e, f, g, h, a, Add(K(0xab1c5ed5ul), w7 = Read4(in, 28)));
+ Round(a, b, c, d, e, f, g, h, Add(K(0xd807aa98ul), w8 = Read4(in, 32)));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x12835b01ul), w9 = Read4(in, 36)));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x243185beul), w10 = Read4(in, 40)));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x550c7dc3ul), w11 = Read4(in, 44)));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x72be5d74ul), w12 = Read4(in, 48)));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x80deb1feul), w13 = Read4(in, 52)));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x9bdc06a7ul), w14 = Read4(in, 56)));
+ Round(b, c, d, e, f, g, h, a, Add(K(0xc19bf174ul), w15 = Read4(in, 60)));
+ Round(a, b, c, d, e, f, g, h, Add(K(0xe49b69c1ul), Inc(w0, sigma1(w14), w9, sigma0(w1))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0xefbe4786ul), Inc(w1, sigma1(w15), w10, sigma0(w2))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x0fc19dc6ul), Inc(w2, sigma1(w0), w11, sigma0(w3))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x240ca1ccul), Inc(w3, sigma1(w1), w12, sigma0(w4))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x2de92c6ful), Inc(w4, sigma1(w2), w13, sigma0(w5))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x4a7484aaul), Inc(w5, sigma1(w3), w14, sigma0(w6))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x5cb0a9dcul), Inc(w6, sigma1(w4), w15, sigma0(w7))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x76f988daul), Inc(w7, sigma1(w5), w0, sigma0(w8))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x983e5152ul), Inc(w8, sigma1(w6), w1, sigma0(w9))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0xa831c66dul), Inc(w9, sigma1(w7), w2, sigma0(w10))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0xb00327c8ul), Inc(w10, sigma1(w8), w3, sigma0(w11))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0xbf597fc7ul), Inc(w11, sigma1(w9), w4, sigma0(w12))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0xc6e00bf3ul), Inc(w12, sigma1(w10), w5, sigma0(w13))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0xd5a79147ul), Inc(w13, sigma1(w11), w6, sigma0(w14))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x06ca6351ul), Inc(w14, sigma1(w12), w7, sigma0(w15))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x14292967ul), Inc(w15, sigma1(w13), w8, sigma0(w0))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x27b70a85ul), Inc(w0, sigma1(w14), w9, sigma0(w1))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x2e1b2138ul), Inc(w1, sigma1(w15), w10, sigma0(w2))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x4d2c6dfcul), Inc(w2, sigma1(w0), w11, sigma0(w3))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x53380d13ul), Inc(w3, sigma1(w1), w12, sigma0(w4))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x650a7354ul), Inc(w4, sigma1(w2), w13, sigma0(w5))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x766a0abbul), Inc(w5, sigma1(w3), w14, sigma0(w6))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x81c2c92eul), Inc(w6, sigma1(w4), w15, sigma0(w7))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x92722c85ul), Inc(w7, sigma1(w5), w0, sigma0(w8))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0xa2bfe8a1ul), Inc(w8, sigma1(w6), w1, sigma0(w9))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0xa81a664bul), Inc(w9, sigma1(w7), w2, sigma0(w10))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0xc24b8b70ul), Inc(w10, sigma1(w8), w3, sigma0(w11))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0xc76c51a3ul), Inc(w11, sigma1(w9), w4, sigma0(w12))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0xd192e819ul), Inc(w12, sigma1(w10), w5, sigma0(w13))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0xd6990624ul), Inc(w13, sigma1(w11), w6, sigma0(w14))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0xf40e3585ul), Inc(w14, sigma1(w12), w7, sigma0(w15))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x106aa070ul), Inc(w15, sigma1(w13), w8, sigma0(w0))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x19a4c116ul), Inc(w0, sigma1(w14), w9, sigma0(w1))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x1e376c08ul), Inc(w1, sigma1(w15), w10, sigma0(w2))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x2748774cul), Inc(w2, sigma1(w0), w11, sigma0(w3))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x34b0bcb5ul), Inc(w3, sigma1(w1), w12, sigma0(w4))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x391c0cb3ul), Inc(w4, sigma1(w2), w13, sigma0(w5))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x4ed8aa4aul), Inc(w5, sigma1(w3), w14, sigma0(w6))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x5b9cca4ful), Inc(w6, sigma1(w4), w15, sigma0(w7))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x682e6ff3ul), Inc(w7, sigma1(w5), w0, sigma0(w8))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x748f82eeul), Inc(w8, sigma1(w6), w1, sigma0(w9))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x78a5636ful), Inc(w9, sigma1(w7), w2, sigma0(w10))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x84c87814ul), Inc(w10, sigma1(w8), w3, sigma0(w11))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x8cc70208ul), Inc(w11, sigma1(w9), w4, sigma0(w12))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x90befffaul), Inc(w12, sigma1(w10), w5, sigma0(w13))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0xa4506cebul), Inc(w13, sigma1(w11), w6, sigma0(w14))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0xbef9a3f7ul), Inc(w14, sigma1(w12), w7, sigma0(w15))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0xc67178f2ul), Inc(w15, sigma1(w13), w8, sigma0(w0))));
+
+ a = Add(a, K(0x6a09e667ul));
+ b = Add(b, K(0xbb67ae85ul));
+ c = Add(c, K(0x3c6ef372ul));
+ d = Add(d, K(0xa54ff53aul));
+ e = Add(e, K(0x510e527ful));
+ f = Add(f, K(0x9b05688cul));
+ g = Add(g, K(0x1f83d9abul));
+ h = Add(h, K(0x5be0cd19ul));
+
+ __m128i t0 = a, t1 = b, t2 = c, t3 = d, t4 = e, t5 = f, t6 = g, t7 = h;
+
+ // Transform 2
+ Round(a, b, c, d, e, f, g, h, K(0xc28a2f98ul));
+ Round(h, a, b, c, d, e, f, g, K(0x71374491ul));
+ Round(g, h, a, b, c, d, e, f, K(0xb5c0fbcful));
+ Round(f, g, h, a, b, c, d, e, K(0xe9b5dba5ul));
+ Round(e, f, g, h, a, b, c, d, K(0x3956c25bul));
+ Round(d, e, f, g, h, a, b, c, K(0x59f111f1ul));
+ Round(c, d, e, f, g, h, a, b, K(0x923f82a4ul));
+ Round(b, c, d, e, f, g, h, a, K(0xab1c5ed5ul));
+ Round(a, b, c, d, e, f, g, h, K(0xd807aa98ul));
+ Round(h, a, b, c, d, e, f, g, K(0x12835b01ul));
+ Round(g, h, a, b, c, d, e, f, K(0x243185beul));
+ Round(f, g, h, a, b, c, d, e, K(0x550c7dc3ul));
+ Round(e, f, g, h, a, b, c, d, K(0x72be5d74ul));
+ Round(d, e, f, g, h, a, b, c, K(0x80deb1feul));
+ Round(c, d, e, f, g, h, a, b, K(0x9bdc06a7ul));
+ Round(b, c, d, e, f, g, h, a, K(0xc19bf374ul));
+ Round(a, b, c, d, e, f, g, h, K(0x649b69c1ul));
+ Round(h, a, b, c, d, e, f, g, K(0xf0fe4786ul));
+ Round(g, h, a, b, c, d, e, f, K(0x0fe1edc6ul));
+ Round(f, g, h, a, b, c, d, e, K(0x240cf254ul));
+ Round(e, f, g, h, a, b, c, d, K(0x4fe9346ful));
+ Round(d, e, f, g, h, a, b, c, K(0x6cc984beul));
+ Round(c, d, e, f, g, h, a, b, K(0x61b9411eul));
+ Round(b, c, d, e, f, g, h, a, K(0x16f988faul));
+ Round(a, b, c, d, e, f, g, h, K(0xf2c65152ul));
+ Round(h, a, b, c, d, e, f, g, K(0xa88e5a6dul));
+ Round(g, h, a, b, c, d, e, f, K(0xb019fc65ul));
+ Round(f, g, h, a, b, c, d, e, K(0xb9d99ec7ul));
+ Round(e, f, g, h, a, b, c, d, K(0x9a1231c3ul));
+ Round(d, e, f, g, h, a, b, c, K(0xe70eeaa0ul));
+ Round(c, d, e, f, g, h, a, b, K(0xfdb1232bul));
+ Round(b, c, d, e, f, g, h, a, K(0xc7353eb0ul));
+ Round(a, b, c, d, e, f, g, h, K(0x3069bad5ul));
+ Round(h, a, b, c, d, e, f, g, K(0xcb976d5ful));
+ Round(g, h, a, b, c, d, e, f, K(0x5a0f118ful));
+ Round(f, g, h, a, b, c, d, e, K(0xdc1eeefdul));
+ Round(e, f, g, h, a, b, c, d, K(0x0a35b689ul));
+ Round(d, e, f, g, h, a, b, c, K(0xde0b7a04ul));
+ Round(c, d, e, f, g, h, a, b, K(0x58f4ca9dul));
+ Round(b, c, d, e, f, g, h, a, K(0xe15d5b16ul));
+ Round(a, b, c, d, e, f, g, h, K(0x007f3e86ul));
+ Round(h, a, b, c, d, e, f, g, K(0x37088980ul));
+ Round(g, h, a, b, c, d, e, f, K(0xa507ea32ul));
+ Round(f, g, h, a, b, c, d, e, K(0x6fab9537ul));
+ Round(e, f, g, h, a, b, c, d, K(0x17406110ul));
+ Round(d, e, f, g, h, a, b, c, K(0x0d8cd6f1ul));
+ Round(c, d, e, f, g, h, a, b, K(0xcdaa3b6dul));
+ Round(b, c, d, e, f, g, h, a, K(0xc0bbbe37ul));
+ Round(a, b, c, d, e, f, g, h, K(0x83613bdaul));
+ Round(h, a, b, c, d, e, f, g, K(0xdb48a363ul));
+ Round(g, h, a, b, c, d, e, f, K(0x0b02e931ul));
+ Round(f, g, h, a, b, c, d, e, K(0x6fd15ca7ul));
+ Round(e, f, g, h, a, b, c, d, K(0x521afacaul));
+ Round(d, e, f, g, h, a, b, c, K(0x31338431ul));
+ Round(c, d, e, f, g, h, a, b, K(0x6ed41a95ul));
+ Round(b, c, d, e, f, g, h, a, K(0x6d437890ul));
+ Round(a, b, c, d, e, f, g, h, K(0xc39c91f2ul));
+ Round(h, a, b, c, d, e, f, g, K(0x9eccabbdul));
+ Round(g, h, a, b, c, d, e, f, K(0xb5c9a0e6ul));
+ Round(f, g, h, a, b, c, d, e, K(0x532fb63cul));
+ Round(e, f, g, h, a, b, c, d, K(0xd2c741c6ul));
+ Round(d, e, f, g, h, a, b, c, K(0x07237ea3ul));
+ Round(c, d, e, f, g, h, a, b, K(0xa4954b68ul));
+ Round(b, c, d, e, f, g, h, a, K(0x4c191d76ul));
+
+ w0 = Add(t0, a);
+ w1 = Add(t1, b);
+ w2 = Add(t2, c);
+ w3 = Add(t3, d);
+ w4 = Add(t4, e);
+ w5 = Add(t5, f);
+ w6 = Add(t6, g);
+ w7 = Add(t7, h);
+
+ // Transform 3
+ a = K(0x6a09e667ul);
+ b = K(0xbb67ae85ul);
+ c = K(0x3c6ef372ul);
+ d = K(0xa54ff53aul);
+ e = K(0x510e527ful);
+ f = K(0x9b05688cul);
+ g = K(0x1f83d9abul);
+ h = K(0x5be0cd19ul);
+
+ Round(a, b, c, d, e, f, g, h, Add(K(0x428a2f98ul), w0));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x71374491ul), w1));
+ Round(g, h, a, b, c, d, e, f, Add(K(0xb5c0fbcful), w2));
+ Round(f, g, h, a, b, c, d, e, Add(K(0xe9b5dba5ul), w3));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x3956c25bul), w4));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x59f111f1ul), w5));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x923f82a4ul), w6));
+ Round(b, c, d, e, f, g, h, a, Add(K(0xab1c5ed5ul), w7));
+ Round(a, b, c, d, e, f, g, h, K(0x5807aa98ul));
+ Round(h, a, b, c, d, e, f, g, K(0x12835b01ul));
+ Round(g, h, a, b, c, d, e, f, K(0x243185beul));
+ Round(f, g, h, a, b, c, d, e, K(0x550c7dc3ul));
+ Round(e, f, g, h, a, b, c, d, K(0x72be5d74ul));
+ Round(d, e, f, g, h, a, b, c, K(0x80deb1feul));
+ Round(c, d, e, f, g, h, a, b, K(0x9bdc06a7ul));
+ Round(b, c, d, e, f, g, h, a, K(0xc19bf274ul));
+ Round(a, b, c, d, e, f, g, h, Add(K(0xe49b69c1ul), Inc(w0, sigma0(w1))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0xefbe4786ul), Inc(w1, K(0xa00000ul), sigma0(w2))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x0fc19dc6ul), Inc(w2, sigma1(w0), sigma0(w3))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x240ca1ccul), Inc(w3, sigma1(w1), sigma0(w4))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x2de92c6ful), Inc(w4, sigma1(w2), sigma0(w5))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x4a7484aaul), Inc(w5, sigma1(w3), sigma0(w6))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x5cb0a9dcul), Inc(w6, sigma1(w4), K(0x100ul), sigma0(w7))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x76f988daul), Inc(w7, sigma1(w5), w0, K(0x11002000ul))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x983e5152ul), w8 = Add(K(0x80000000ul), sigma1(w6), w1)));
+ Round(h, a, b, c, d, e, f, g, Add(K(0xa831c66dul), w9 = Add(sigma1(w7), w2)));
+ Round(g, h, a, b, c, d, e, f, Add(K(0xb00327c8ul), w10 = Add(sigma1(w8), w3)));
+ Round(f, g, h, a, b, c, d, e, Add(K(0xbf597fc7ul), w11 = Add(sigma1(w9), w4)));
+ Round(e, f, g, h, a, b, c, d, Add(K(0xc6e00bf3ul), w12 = Add(sigma1(w10), w5)));
+ Round(d, e, f, g, h, a, b, c, Add(K(0xd5a79147ul), w13 = Add(sigma1(w11), w6)));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x06ca6351ul), w14 = Add(sigma1(w12), w7, K(0x400022ul))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x14292967ul), w15 = Add(K(0x100ul), sigma1(w13), w8, sigma0(w0))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x27b70a85ul), Inc(w0, sigma1(w14), w9, sigma0(w1))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x2e1b2138ul), Inc(w1, sigma1(w15), w10, sigma0(w2))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x4d2c6dfcul), Inc(w2, sigma1(w0), w11, sigma0(w3))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x53380d13ul), Inc(w3, sigma1(w1), w12, sigma0(w4))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x650a7354ul), Inc(w4, sigma1(w2), w13, sigma0(w5))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x766a0abbul), Inc(w5, sigma1(w3), w14, sigma0(w6))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x81c2c92eul), Inc(w6, sigma1(w4), w15, sigma0(w7))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x92722c85ul), Inc(w7, sigma1(w5), w0, sigma0(w8))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0xa2bfe8a1ul), Inc(w8, sigma1(w6), w1, sigma0(w9))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0xa81a664bul), Inc(w9, sigma1(w7), w2, sigma0(w10))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0xc24b8b70ul), Inc(w10, sigma1(w8), w3, sigma0(w11))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0xc76c51a3ul), Inc(w11, sigma1(w9), w4, sigma0(w12))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0xd192e819ul), Inc(w12, sigma1(w10), w5, sigma0(w13))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0xd6990624ul), Inc(w13, sigma1(w11), w6, sigma0(w14))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0xf40e3585ul), Inc(w14, sigma1(w12), w7, sigma0(w15))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x106aa070ul), Inc(w15, sigma1(w13), w8, sigma0(w0))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x19a4c116ul), Inc(w0, sigma1(w14), w9, sigma0(w1))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x1e376c08ul), Inc(w1, sigma1(w15), w10, sigma0(w2))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x2748774cul), Inc(w2, sigma1(w0), w11, sigma0(w3))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x34b0bcb5ul), Inc(w3, sigma1(w1), w12, sigma0(w4))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x391c0cb3ul), Inc(w4, sigma1(w2), w13, sigma0(w5))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0x4ed8aa4aul), Inc(w5, sigma1(w3), w14, sigma0(w6))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0x5b9cca4ful), Inc(w6, sigma1(w4), w15, sigma0(w7))));
+ Round(b, c, d, e, f, g, h, a, Add(K(0x682e6ff3ul), Inc(w7, sigma1(w5), w0, sigma0(w8))));
+ Round(a, b, c, d, e, f, g, h, Add(K(0x748f82eeul), Inc(w8, sigma1(w6), w1, sigma0(w9))));
+ Round(h, a, b, c, d, e, f, g, Add(K(0x78a5636ful), Inc(w9, sigma1(w7), w2, sigma0(w10))));
+ Round(g, h, a, b, c, d, e, f, Add(K(0x84c87814ul), Inc(w10, sigma1(w8), w3, sigma0(w11))));
+ Round(f, g, h, a, b, c, d, e, Add(K(0x8cc70208ul), Inc(w11, sigma1(w9), w4, sigma0(w12))));
+ Round(e, f, g, h, a, b, c, d, Add(K(0x90befffaul), Inc(w12, sigma1(w10), w5, sigma0(w13))));
+ Round(d, e, f, g, h, a, b, c, Add(K(0xa4506cebul), Inc(w13, sigma1(w11), w6, sigma0(w14))));
+ Round(c, d, e, f, g, h, a, b, Add(K(0xbef9a3f7ul), w14, sigma1(w12), w7, sigma0(w15)));
+ Round(b, c, d, e, f, g, h, a, Add(K(0xc67178f2ul), w15, sigma1(w13), w8, sigma0(w0)));
+
+ // Output
+ Write4(out, 0, Add(a, K(0x6a09e667ul)));
+ Write4(out, 4, Add(b, K(0xbb67ae85ul)));
+ Write4(out, 8, Add(c, K(0x3c6ef372ul)));
+ Write4(out, 12, Add(d, K(0xa54ff53aul)));
+ Write4(out, 16, Add(e, K(0x510e527ful)));
+ Write4(out, 20, Add(f, K(0x9b05688cul)));
+ Write4(out, 24, Add(g, K(0x1f83d9abul)));
+ Write4(out, 28, Add(h, K(0x5be0cd19ul)));
+}
+
+}
+
+#endif
diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp
index 5b6e0f9980..3ff16b7664 100644
--- a/src/index/txindex.cpp
+++ b/src/index/txindex.cpp
@@ -170,7 +170,7 @@ void TxIndex::BlockConnected(const std::shared_ptr<const CBlock>& block, const C
}
} else {
// Ensure block connects to an ancestor of the current best block. This should be the case
- // most of the time, but may not be immediately after the the sync thread catches up and sets
+ // most of the time, but may not be immediately after the sync thread catches up and sets
// m_synced. Consider the case where there is a reorg and the blocks on the stale branch are
// in the ValidationInterface queue backlog even after the sync thread has caught up to the
// new chain tip. In this unlikely event, log a warning and let the queue clear.
@@ -212,7 +212,7 @@ void TxIndex::ChainStateFlushed(const CBlockLocator& locator)
}
// This checks that ChainStateFlushed callbacks are received after BlockConnected. The check may fail
- // immediately after the the sync thread catches up and sets m_synced. Consider the case where
+ // immediately after the sync thread catches up and sets m_synced. Consider the case where
// there is a reorg and the blocks on the stale branch are in the ValidationInterface queue
// backlog even after the sync thread has caught up to the new chain tip. In this unlikely
// event, log a warning and let the queue clear.
diff --git a/src/init.cpp b/src/init.cpp
index 4ad68b73f2..b4e2eec0d2 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -350,93 +350,93 @@ void SetupServerArgs()
// Set all of the args and their help
// When adding new options to the categories, please keep and ensure alphabetical ordering.
- // Do not translate _(...) -help-debug options, Many technical terms, and only a very small audience, so is unnecessary stress to translators.
- gArgs.AddArg("-?", _("Print this help message and exit"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-version", _("Print version and exit"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-alertnotify=<cmd>", _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-assumevalid=<hex>", strprintf(_("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)"), defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex()), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-blocksdir=<dir>", _("Specify blocks directory (default: <datadir>/blocks)"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-blockreconstructionextratxn=<n>", strprintf(_("Extra transactions to keep in memory for compact block reconstructions (default: %u)"), DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-blocksonly", strprintf(_("Whether to operate in a blocks only mode (default: %u)"), DEFAULT_BLOCKSONLY), true, OptionsCategory::OPTIONS);
- gArgs.AddArg("-conf=<file>", strprintf(_("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)"), BITCOIN_CONF_FILENAME), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-datadir=<dir>", _("Specify data directory"), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-?", "Print this help message and exit", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-version", "Print version and exit", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-alertnotify=<cmd>", "Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-assumevalid=<hex>", strprintf("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)", defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex()), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-blocksdir=<dir>", "Specify blocks directory (default: <datadir>/blocks)", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-blocknotify=<cmd>", "Execute command when the best block changes (%s in cmd is replaced by block hash)", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-blockreconstructionextratxn=<n>", strprintf("Extra transactions to keep in memory for compact block reconstructions (default: %u)", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-blocksonly", strprintf("Whether to operate in a blocks only mode (default: %u)", DEFAULT_BLOCKSONLY), true, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-conf=<file>", strprintf("Specify configuration file. Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-datadir=<dir>", "Specify data directory", false, OptionsCategory::OPTIONS);
gArgs.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", nDefaultDbBatchSize), true, OptionsCategory::OPTIONS);
- gArgs.AddArg("-dbcache=<n>", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-debuglogfile=<file>", strprintf(_("Specify location of debug log file. Relative paths will be prefixed by a net-specific datadir location. (default: %s)"), DEFAULT_DEBUGLOGFILE), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-dbcache=<n>", strprintf("Set database cache size in megabytes (%d to %d, default: %d)", nMinDbCache, nMaxDbCache, nDefaultDbCache), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-debuglogfile=<file>", strprintf("Specify location of debug log file. Relative paths will be prefixed by a net-specific datadir location. (default: %s)", DEFAULT_DEBUGLOGFILE), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-feefilter", strprintf("Tell other nodes to filter invs to us by our mempool min fee (default: %u)", DEFAULT_FEEFILTER), true, OptionsCategory::OPTIONS);
- gArgs.AddArg("-includeconf=<file>", _("Specify additional configuration file, relative to the -datadir path (only useable from configuration file, not command line)"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-loadblock=<file>", _("Imports blocks from external blk000??.dat file on startup"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-maxmempool=<n>", strprintf(_("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-mempoolexpiry=<n>", strprintf(_("Do not keep transactions in the mempool longer than <n> hours (default: %u)"), DEFAULT_MEMPOOL_EXPIRY), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-includeconf=<file>", "Specify additional configuration file, relative to the -datadir path (only useable from configuration file, not command line)", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-loadblock=<file>", "Imports blocks from external blk000??.dat file on startup", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-maxmempool=<n>", strprintf("Keep the transaction memory pool below <n> megabytes (default: %u)", DEFAULT_MAX_MEMPOOL_SIZE), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-maxorphantx=<n>", strprintf("Keep at most <n> unconnectable transactions in memory (default: %u)", DEFAULT_MAX_ORPHAN_TRANSACTIONS), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-mempoolexpiry=<n>", strprintf("Do not keep transactions in the mempool longer than <n> hours (default: %u)", DEFAULT_MEMPOOL_EXPIRY), false, OptionsCategory::OPTIONS);
gArgs.AddArg("-minimumchainwork=<hex>", strprintf("Minimum work assumed to exist on a valid chain in hex (default: %s, testnet: %s)", defaultChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnetChainParams->GetConsensus().nMinimumChainWork.GetHex()), true, OptionsCategory::OPTIONS);
- gArgs.AddArg("-par=<n>", strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"),
+ gArgs.AddArg("-par=<n>", 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), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-persistmempool", strprintf(_("Whether to save the mempool on shutdown and load on restart (default: %u)"), DEFAULT_PERSIST_MEMPOOL), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-persistmempool", strprintf("Whether to save the mempool on shutdown and load on restart (default: %u)", DEFAULT_PERSIST_MEMPOOL), false, OptionsCategory::OPTIONS);
#ifndef WIN32
- gArgs.AddArg("-pid=<file>", strprintf(_("Specify pid file. Relative paths will be prefixed by a net-specific datadir location. (default: %s)"), BITCOIN_PID_FILENAME), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-pid=<file>", strprintf("Specify pid file. Relative paths will be prefixed by a net-specific datadir location. (default: %s)", BITCOIN_PID_FILENAME), false, OptionsCategory::OPTIONS);
#endif
- gArgs.AddArg("-prune=<n>", strprintf(_("Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. "
+ gArgs.AddArg("-prune=<n>", strprintf("Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. "
"Warning: Reverting this setting requires re-downloading the entire blockchain. "
- "(default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >%u = automatically prune block files to stay under the specified target size in MiB)"), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-reindex", _("Rebuild chain state and block index from the blk*.dat files on disk"), false, OptionsCategory::OPTIONS);
- gArgs.AddArg("-reindex-chainstate", _("Rebuild chain state from the currently indexed blocks"), false, OptionsCategory::OPTIONS);
+ "(default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >%u = automatically prune block files to stay under the specified target size in MiB)", MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-reindex", "Rebuild chain state and block index from the blk*.dat files on disk", false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-reindex-chainstate", "Rebuild chain state from the currently indexed blocks", false, OptionsCategory::OPTIONS);
#ifndef WIN32
- gArgs.AddArg("-sysperms", _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)"), false, OptionsCategory::OPTIONS);
+ gArgs.AddArg("-sysperms", "Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)", false, OptionsCategory::OPTIONS);
#endif
- gArgs.AddArg("-txindex", strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"), DEFAULT_TXINDEX), false, OptionsCategory::OPTIONS);
-
- gArgs.AddArg("-addnode=<ip>", _("Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info)"), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-banscore=<n>", strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), DEFAULT_BANSCORE_THRESHOLD), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-bantime=<n>", strprintf(_("Number of seconds to keep misbehaving peers from reconnecting (default: %u)"), DEFAULT_MISBEHAVING_BANTIME), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-bind=<addr>", _("Bind to given address and always listen on it. Use [host]:port notation for IPv6"), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-connect=<ip>", _("Connect only to the specified node(s); -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode)"), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-discover", _("Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)"), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-dns", _("Allow DNS lookups for -addnode, -seednode and -connect") + " " + strprintf(_("(default: %u)"), DEFAULT_NAME_LOOKUP), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-dnsseed", _("Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)"), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-externalip=<ip>", _("Specify your own public address"), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-forcednsseed", strprintf(_("Always query for peer addresses via DNS lookup (default: %u)"), DEFAULT_FORCEDNSSEED), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-listen", _("Accept connections from outside (default: 1 if no -proxy or -connect)"), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-listenonion", strprintf(_("Automatically create Tor hidden service (default: %d)"), DEFAULT_LISTEN_ONION), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-maxconnections=<n>", strprintf(_("Maintain at most <n> connections to peers (default: %u)"), DEFAULT_MAX_PEER_CONNECTIONS), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-maxreceivebuffer=<n>", strprintf(_("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)"), DEFAULT_MAXRECEIVEBUFFER), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-maxsendbuffer=<n>", strprintf(_("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)"), DEFAULT_MAXSENDBUFFER), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-maxtimeadjustment", strprintf(_("Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)"), DEFAULT_MAX_TIME_ADJUSTMENT), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-maxuploadtarget=<n>", strprintf(_("Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)"), DEFAULT_MAX_UPLOAD_TARGET), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-onion=<ip:port>", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy"), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-onlynet=<net>", _("Only connect to nodes in network <net> (ipv4, ipv6 or onion)"), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-peerbloomfilters", strprintf(_("Support filtering of blocks and transaction with bloom filters (default: %u)"), DEFAULT_PEERBLOOMFILTERS), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), DEFAULT_PERMIT_BAREMULTISIG), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-port=<port>", strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort()), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-proxy=<ip:port>", _("Connect through SOCKS5 proxy"), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-proxyrandomize", strprintf(_("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)"), DEFAULT_PROXYRANDOMIZE), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-seednode=<ip>", _("Connect to a node to retrieve peer addresses, and disconnect"), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-timeout=<n>", strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-torcontrol=<ip>:<port>", strprintf(_("Tor control port to use if onion listening enabled (default: %s)"), DEFAULT_TOR_CONTROL), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-torpassword=<pass>", _("Tor control port password (default: empty)"), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), false, OptionsCategory::OPTIONS);
+
+ gArgs.AddArg("-addnode=<ip>", "Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info)", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-banscore=<n>", strprintf("Threshold for disconnecting misbehaving peers (default: %u)", DEFAULT_BANSCORE_THRESHOLD), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-bantime=<n>", strprintf("Number of seconds to keep misbehaving peers from reconnecting (default: %u)", DEFAULT_MISBEHAVING_BANTIME), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-bind=<addr>", "Bind to given address and always listen on it. Use [host]:port notation for IPv6", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-connect=<ip>", "Connect only to the specified node(s); -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode)", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-dnsseed", "Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-enablebip61", strprintf("Send reject messages per BIP61 (default: %u)", DEFAULT_ENABLE_BIP61), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-externalip=<ip>", "Specify your own public address", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-forcednsseed", strprintf("Always query for peer addresses via DNS lookup (default: %u)", DEFAULT_FORCEDNSSEED), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-listen", "Accept connections from outside (default: 1 if no -proxy or -connect)", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-listenonion", strprintf("Automatically create Tor hidden service (default: %d)", DEFAULT_LISTEN_ONION), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-maxconnections=<n>", strprintf("Maintain at most <n> connections to peers (default: %u)", DEFAULT_MAX_PEER_CONNECTIONS), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-maxreceivebuffer=<n>", strprintf("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)", DEFAULT_MAXRECEIVEBUFFER), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-maxsendbuffer=<n>", strprintf("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)", DEFAULT_MAXSENDBUFFER), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-maxtimeadjustment", strprintf("Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)", DEFAULT_MAX_TIME_ADJUSTMENT), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-maxuploadtarget=<n>", strprintf("Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)", DEFAULT_MAX_UPLOAD_TARGET), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-onion=<ip:port>", "Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy)", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-onlynet=<net>", "Only connect to nodes in network <net> (ipv4, ipv6 or onion)", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-permitbaremultisig", strprintf("Relay non-P2SH multisig (default: %u)", DEFAULT_PERMIT_BAREMULTISIG), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-port=<port>", strprintf("Listen for connections on <port> (default: %u or testnet: %u)", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort()), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-proxy=<ip:port>", "Connect through SOCKS5 proxy", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-proxyrandomize", strprintf("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)", DEFAULT_PROXYRANDOMIZE), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-seednode=<ip>", "Connect to a node to retrieve peer addresses, and disconnect", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-timeout=<n>", strprintf("Specify connection timeout in milliseconds (minimum: 1, default: %d)", DEFAULT_CONNECT_TIMEOUT), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-torcontrol=<ip>:<port>", strprintf("Tor control port to use if onion listening enabled (default: %s)", DEFAULT_TOR_CONTROL), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-torpassword=<pass>", "Tor control port password (default: empty)", false, OptionsCategory::CONNECTION);
#ifdef USE_UPNP
#if USE_UPNP
- gArgs.AddArg("-upnp", _("Use UPnP to map the listening port (default: 1 when listening and no -proxy)"), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-upnp", "Use UPnP to map the listening port (default: 1 when listening and no -proxy)", false, OptionsCategory::CONNECTION);
#else
- gArgs.AddArg("-upnp", strprintf(_("Use UPnP to map the listening port (default: %u)"), 0), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-upnp", strprintf("Use UPnP to map the listening port (default: %u)", 0), false, OptionsCategory::CONNECTION);
#endif
#endif
- gArgs.AddArg("-whitebind=<addr>", _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6"), false, OptionsCategory::CONNECTION);
- gArgs.AddArg("-whitelist=<IP address or network>", _("Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.") +
- " " + _("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"), false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-whitebind=<addr>", "Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6", false, OptionsCategory::CONNECTION);
+ gArgs.AddArg("-whitelist=<IP address or network>", "Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times."
+ " 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", false, OptionsCategory::CONNECTION);
g_wallet_init_interface.AddWalletOptions();
#if ENABLE_ZMQ
- gArgs.AddArg("-zmqpubhashblock=<address>", _("Enable publish hash block in <address>"), false, OptionsCategory::ZMQ);
- gArgs.AddArg("-zmqpubhashtx=<address>", _("Enable publish hash transaction in <address>"), false, OptionsCategory::ZMQ);
- gArgs.AddArg("-zmqpubrawblock=<address>", _("Enable publish raw block in <address>"), false, OptionsCategory::ZMQ);
- gArgs.AddArg("-zmqpubrawtx=<address>", _("Enable publish raw transaction in <address>"), false, OptionsCategory::ZMQ);
+ gArgs.AddArg("-zmqpubhashblock=<address>", "Enable publish hash block in <address>", false, OptionsCategory::ZMQ);
+ gArgs.AddArg("-zmqpubhashtx=<address>", "Enable publish hash transaction in <address>", false, OptionsCategory::ZMQ);
+ gArgs.AddArg("-zmqpubrawblock=<address>", "Enable publish raw block in <address>", false, OptionsCategory::ZMQ);
+ gArgs.AddArg("-zmqpubrawtx=<address>", "Enable publish raw transaction in <address>", false, OptionsCategory::ZMQ);
#endif
- gArgs.AddArg("-checkblocks=<n>", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), DEFAULT_CHECKBLOCKS), true, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-checklevel=<n>", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), DEFAULT_CHECKLEVEL), true, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-checkblocks=<n>", strprintf("How many blocks to check at startup (default: %u, 0 = all)", DEFAULT_CHECKBLOCKS), true, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-checklevel=<n>", strprintf("How thorough the block verification of -checkblocks is (0-4, default: %u)", DEFAULT_CHECKLEVEL), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. (default: %u)", defaultChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u)", defaultChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED), true, OptionsCategory::DEBUG_TEST);
@@ -450,55 +450,72 @@ void SetupServerArgs()
gArgs.AddArg("-limitdescendantsize=<n>", strprintf("Do not accept transactions if any ancestor would have more than <n> kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-vbparams=deployment:start:end", "Use given start/end times for specified version bits deployment (regtest-only)", true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-addrmantest", "Allows to test address relay on localhost", true, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " +
- _("If <category> is not supplied or if <category> = 1, output all debugging information.") + " " + _("<category> can be:") + " " + ListLogCategories() + ".", false, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-debugexclude=<category>", strprintf(_("Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.")), false, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-help-debug", _("Show all debugging options (usage: --help -help-debug)"), false, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-logips", strprintf(_("Include IP addresses in debug output (default: %u)"), DEFAULT_LOGIPS), false, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-logtimestamps", strprintf(_("Prepend debug output with timestamp (default: %u)"), DEFAULT_LOGTIMESTAMPS), false, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-debug=<category>", strprintf("Output debugging information (default: %u, supplying <category> is optional)", 0) + ". " +
+ "If <category> is not supplied or if <category> = 1, output all debugging information. <category> can be: " + ListLogCategories() + ".", false, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-debugexclude=<category>", strprintf("Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories."), false, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-help-debug", "Show all debugging options (usage: --help -help-debug)", false, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-logips", strprintf("Include IP addresses in debug output (default: %u)", DEFAULT_LOGIPS), false, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-logtimestamps", strprintf("Prepend debug output with timestamp (default: %u)", DEFAULT_LOGTIMESTAMPS), false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-logtimemicros", strprintf("Add microsecond precision to debug timestamps (default: %u)", DEFAULT_LOGTIMEMICROS), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-mocktime=<n>", "Replace actual time with <n> seconds since epoch (default: 0)", true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-maxsigcachesize=<n>", strprintf("Limit sum of signature cache and script execution cache sizes to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE), true, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-maxtipage=<n>", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE), true, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-maxtxfee=<amt>", 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)"),
+ gArgs.AddArg("-maxtxfee=<amt>", 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)), false, OptionsCategory::DEBUG_TEST);
gArgs.AddArg("-printpriority", strprintf("Log transaction fee per kB when mining blocks (default: %u)", DEFAULT_PRINTPRIORITY), true, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-printtoconsole", _("Send trace/debug info to console instead of debug.log file"), false, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)"), false, OptionsCategory::DEBUG_TEST);
- gArgs.AddArg("-uacomment=<cmt>", _("Append comment to the user agent string"), false, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-printtoconsole", "Send trace/debug info to console instead of debug.log file", false, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-shrinkdebugfile", "Shrink debug.log file on client startup (default: 1 when no -debug)", false, OptionsCategory::DEBUG_TEST);
+ gArgs.AddArg("-uacomment=<cmt>", "Append comment to the user agent string", false, OptionsCategory::DEBUG_TEST);
SetupChainParamsBaseOptions();
gArgs.AddArg("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !testnetChainParams->RequireStandard()), true, OptionsCategory::NODE_RELAY);
gArgs.AddArg("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to define cost of relay, used for mempool limiting and BIP 125 replacement. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)), true, OptionsCategory::NODE_RELAY);
gArgs.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to defined dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), true, OptionsCategory::NODE_RELAY);
- gArgs.AddArg("-bytespersigop", strprintf(_("Equivalent bytes per sigop in transactions for relay and mining (default: %u)"), DEFAULT_BYTES_PER_SIGOP), false, OptionsCategory::NODE_RELAY);
- gArgs.AddArg("-datacarrier", strprintf(_("Relay and mine data carrier transactions (default: %u)"), DEFAULT_ACCEPT_DATACARRIER), false, OptionsCategory::NODE_RELAY);
- gArgs.AddArg("-datacarriersize", strprintf(_("Maximum size of data in data carrier transactions we relay and mine (default: %u)"), MAX_OP_RETURN_RELAY), false, OptionsCategory::NODE_RELAY);
- gArgs.AddArg("-mempoolreplacement", strprintf(_("Enable transaction replacement in the memory pool (default: %u)"), DEFAULT_ENABLE_REPLACEMENT), false, OptionsCategory::NODE_RELAY);
- gArgs.AddArg("-minrelaytxfee=<amt>", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)"),
+ gArgs.AddArg("-bytespersigop", strprintf("Equivalent bytes per sigop in transactions for relay and mining (default: %u)", DEFAULT_BYTES_PER_SIGOP), false, OptionsCategory::NODE_RELAY);
+ gArgs.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), false, OptionsCategory::NODE_RELAY);
+ gArgs.AddArg("-datacarriersize", strprintf("Maximum size of data in data carrier transactions we relay and mine (default: %u)", MAX_OP_RETURN_RELAY), false, OptionsCategory::NODE_RELAY);
+ gArgs.AddArg("-mempoolreplacement", strprintf("Enable transaction replacement in the memory pool (default: %u)", DEFAULT_ENABLE_REPLACEMENT), false, OptionsCategory::NODE_RELAY);
+ gArgs.AddArg("-minrelaytxfee=<amt>", 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)), false, OptionsCategory::NODE_RELAY);
- gArgs.AddArg("-whitelistforcerelay", strprintf(_("Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)"), DEFAULT_WHITELISTFORCERELAY), false, OptionsCategory::NODE_RELAY);
- gArgs.AddArg("-whitelistrelay", strprintf(_("Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)"), DEFAULT_WHITELISTRELAY), false, OptionsCategory::NODE_RELAY);
+ gArgs.AddArg("-whitelistforcerelay", strprintf("Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)", DEFAULT_WHITELISTFORCERELAY), false, OptionsCategory::NODE_RELAY);
+ gArgs.AddArg("-whitelistrelay", strprintf("Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)", DEFAULT_WHITELISTRELAY), false, OptionsCategory::NODE_RELAY);
- gArgs.AddArg("-blockmaxweight=<n>", strprintf(_("Set maximum BIP141 block weight (default: %d)"), DEFAULT_BLOCK_MAX_WEIGHT), false, OptionsCategory::BLOCK_CREATION);
- gArgs.AddArg("-blockmintxfee=<amt>", strprintf(_("Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)"), CURRENCY_UNIT, FormatMoney(DEFAULT_BLOCK_MIN_TX_FEE)), false, OptionsCategory::BLOCK_CREATION);
+ gArgs.AddArg("-blockmaxweight=<n>", strprintf("Set maximum BIP141 block weight (default: %d)", DEFAULT_BLOCK_MAX_WEIGHT), false, OptionsCategory::BLOCK_CREATION);
+ gArgs.AddArg("-blockmintxfee=<amt>", strprintf("Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_BLOCK_MIN_TX_FEE)), false, OptionsCategory::BLOCK_CREATION);
gArgs.AddArg("-blockversion=<n>", "Override block version to test forking scenarios", true, OptionsCategory::BLOCK_CREATION);
- gArgs.AddArg("-rest", strprintf(_("Accept public REST requests (default: %u)"), DEFAULT_REST_ENABLE), false, OptionsCategory::RPC);
- gArgs.AddArg("-rpcallowip=<ip>", _("Allow JSON-RPC connections from specified source. Valid for <ip> 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"), false, OptionsCategory::RPC);
- gArgs.AddArg("-rpcauth=<userpw>", _("Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times"), false, OptionsCategory::RPC);
- gArgs.AddArg("-rpcbind=<addr>[:port]", _("Bind to given address to listen for JSON-RPC connections. This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)"), false, OptionsCategory::RPC);
- gArgs.AddArg("-rpccookiefile=<loc>", _("Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)"), false, OptionsCategory::RPC);
- gArgs.AddArg("-rpcpassword=<pw>", _("Password for JSON-RPC connections"), false, OptionsCategory::RPC);
- gArgs.AddArg("-rpcport=<port>", strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()), false, OptionsCategory::RPC);
- gArgs.AddArg("-rpcserialversion", strprintf(_("Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)"), DEFAULT_RPC_SERIALIZE_VERSION), false, OptionsCategory::RPC);
+ gArgs.AddArg("-rest", strprintf("Accept public REST requests (default: %u)", DEFAULT_REST_ENABLE), false, OptionsCategory::RPC);
+ gArgs.AddArg("-rpcallowip=<ip>", "Allow JSON-RPC connections from specified source. Valid for <ip> 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", false, OptionsCategory::RPC);
+ gArgs.AddArg("-rpcauth=<userpw>", "Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times", false, OptionsCategory::RPC);
+ gArgs.AddArg("-rpcbind=<addr>[:port]", "Bind to given address to listen for JSON-RPC connections. This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)", false, OptionsCategory::RPC);
+ gArgs.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", false, OptionsCategory::RPC);
+ gArgs.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", false, OptionsCategory::RPC);
+ gArgs.AddArg("-rpcport=<port>", strprintf("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()), false, OptionsCategory::RPC);
+ gArgs.AddArg("-rpcserialversion", strprintf("Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)", DEFAULT_RPC_SERIALIZE_VERSION), false, OptionsCategory::RPC);
gArgs.AddArg("-rpcservertimeout=<n>", strprintf("Timeout during HTTP requests (default: %d)", DEFAULT_HTTP_SERVER_TIMEOUT), true, OptionsCategory::RPC);
- gArgs.AddArg("-rpcthreads=<n>", strprintf(_("Set the number of threads to service RPC calls (default: %d)"), DEFAULT_HTTP_THREADS), false, OptionsCategory::RPC);
- gArgs.AddArg("-rpcuser=<user>", _("Username for JSON-RPC connections"), false, OptionsCategory::RPC);
+ gArgs.AddArg("-rpcthreads=<n>", strprintf("Set the number of threads to service RPC calls (default: %d)", DEFAULT_HTTP_THREADS), false, OptionsCategory::RPC);
+ gArgs.AddArg("-rpcuser=<user>", "Username for JSON-RPC connections", false, OptionsCategory::RPC);
gArgs.AddArg("-rpcworkqueue=<n>", strprintf("Set the depth of the work queue to service RPC calls (default: %d)", DEFAULT_HTTP_WORKQUEUE), true, OptionsCategory::RPC);
- gArgs.AddArg("-server", _("Accept command line and JSON-RPC commands"), false, OptionsCategory::RPC);
+ gArgs.AddArg("-server", "Accept command line and JSON-RPC commands", false, OptionsCategory::RPC);
+
+ // Hidden options
+ gArgs.AddArg("-rpcssl", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-benchmark", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-h", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-help", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-socks", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-tor", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-debugnet", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-whitelistalwaysrelay", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-prematurewitness", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-walletprematurewitness", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-promiscuousmempoolflags", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-blockminsize", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-dbcrashratio", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-forcecompactdb", "", false, OptionsCategory::HIDDEN);
+ gArgs.AddArg("-usehd", "", false, OptionsCategory::HIDDEN);
}
std::string LicenseInfo()
@@ -1099,6 +1116,8 @@ bool AppInitParameterInteraction()
if (gArgs.GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS))
nLocalServices = ServiceFlags(nLocalServices | NODE_BLOOM);
+ g_enable_bip61 = gArgs.GetBoolArg("-enablebip61", DEFAULT_ENABLE_BIP61);
+
if (gArgs.GetArg("-rpcserialversion", DEFAULT_RPC_SERIALIZE_VERSION) < 0)
return InitError("rpcserialversion must be non-negative.");
diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp
index 73657d4f5a..4189ff7497 100644
--- a/src/interfaces/node.cpp
+++ b/src/interfaces/node.cpp
@@ -48,11 +48,11 @@ namespace {
class NodeImpl : public Node
{
- void parseParameters(int argc, const char* const argv[]) override
+ bool parseParameters(int argc, const char* const argv[], std::string& error) override
{
- gArgs.ParseParameters(argc, argv);
+ return gArgs.ParseParameters(argc, argv, error);
}
- void readConfigFiles() override { gArgs.ReadConfigFiles(); }
+ bool readConfigFiles(std::string& error) override { return gArgs.ReadConfigFiles(error); }
bool softSetArg(const std::string& arg, const std::string& value) override { return gArgs.SoftSetArg(arg, value); }
bool softSetBoolArg(const std::string& arg, bool value) override { return gArgs.SoftSetBoolArg(arg, value); }
void selectParams(const std::string& network) override { SelectParams(network); }
@@ -222,8 +222,8 @@ class NodeImpl : public Node
{
#ifdef ENABLE_WALLET
std::vector<std::unique_ptr<Wallet>> wallets;
- for (CWallet* wallet : GetWallets()) {
- wallets.emplace_back(MakeWallet(*wallet));
+ for (const std::shared_ptr<CWallet>& wallet : GetWallets()) {
+ wallets.emplace_back(MakeWallet(wallet));
}
return wallets;
#else
@@ -249,7 +249,7 @@ class NodeImpl : public Node
std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) override
{
CHECK_WALLET(
- return MakeHandler(::uiInterface.LoadWallet.connect([fn](CWallet* wallet) { fn(MakeWallet(*wallet)); })));
+ return MakeHandler(::uiInterface.LoadWallet.connect([fn](std::shared_ptr<CWallet> wallet) { fn(MakeWallet(wallet)); })));
}
std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override
{
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
index 2a1a8152df..8185c015a9 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -38,7 +38,7 @@ public:
virtual ~Node() {}
//! Set command line arguments.
- virtual void parseParameters(int argc, const char* const argv[]) = 0;
+ virtual bool parseParameters(int argc, const char* const argv[], std::string& error) = 0;
//! Set a command line argument if it doesn't already have a value
virtual bool softSetArg(const std::string& arg, const std::string& value) = 0;
@@ -47,7 +47,7 @@ public:
virtual bool softSetBoolArg(const std::string& arg, bool value) = 0;
//! Load settings from configuration file.
- virtual void readConfigFiles() = 0;
+ virtual bool readConfigFiles(std::string& error) = 0;
//! Choose network parameters.
virtual void selectParams(const std::string& network) = 0;
diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp
index 63b9d80a92..3029dbe8e3 100644
--- a/src/interfaces/wallet.cpp
+++ b/src/interfaces/wallet.cpp
@@ -118,7 +118,7 @@ WalletTxOut MakeWalletTxOut(CWallet& wallet, const CWalletTx& wtx, int n, int de
class WalletImpl : public Wallet
{
public:
- WalletImpl(CWallet& wallet) : m_wallet(wallet) {}
+ WalletImpl(const std::shared_ptr<CWallet>& wallet) : m_shared_wallet(wallet), m_wallet(*wallet.get()) {}
bool encryptWallet(const SecureString& wallet_passphrase) override
{
@@ -453,11 +453,12 @@ public:
return MakeHandler(m_wallet.NotifyWatchonlyChanged.connect(fn));
}
+ std::shared_ptr<CWallet> m_shared_wallet;
CWallet& m_wallet;
};
} // namespace
-std::unique_ptr<Wallet> MakeWallet(CWallet& wallet) { return MakeUnique<WalletImpl>(wallet); }
+std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet) { return MakeUnique<WalletImpl>(wallet); }
} // namespace interfaces
diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h
index ff779cd0ad..82ae0b14b5 100644
--- a/src/interfaces/wallet.h
+++ b/src/interfaces/wallet.h
@@ -363,7 +363,7 @@ struct WalletTxOut
//! Return implementation of Wallet interface. This function will be undefined
//! in builds where ENABLE_WALLET is false.
-std::unique_ptr<Wallet> MakeWallet(CWallet& wallet);
+std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet);
} // namespace interfaces
diff --git a/src/key.cpp b/src/key.cpp
index 042e687772..94be179bfb 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -273,7 +273,7 @@ bool CExtKey::Derive(CExtKey &out, unsigned int _nChild) const {
return key.Derive(out.key, out.chaincode, _nChild, chaincode);
}
-void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) {
+void CExtKey::SetSeed(const unsigned char *seed, unsigned int nSeedLen) {
static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'};
std::vector<unsigned char, secure_allocator<unsigned char>> vout(64);
CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(vout.data());
diff --git a/src/key.h b/src/key.h
index 3c0a7574ff..f573a18a4e 100644
--- a/src/key.h
+++ b/src/key.h
@@ -158,7 +158,7 @@ struct CExtKey {
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
bool Derive(CExtKey& out, unsigned int nChild) const;
CExtPubKey Neuter() const;
- void SetMaster(const unsigned char* seed, unsigned int nSeedLen);
+ void SetSeed(const unsigned char* seed, unsigned int nSeedLen);
template <typename Stream>
void Serialize(Stream& s) const
{
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index ed2fb598d2..fc05dd2ad2 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -37,6 +37,7 @@
#endif
std::atomic<int64_t> nTimeBestReceived(0); // Used only to inform the wallet of when we last received a block
+bool g_enable_bip61 = DEFAULT_ENABLE_BIP61;
struct IteratorComparator
{
@@ -1070,12 +1071,13 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman* connma
connman->ForEachNodeThen(std::move(sortfunc), std::move(pushfunc));
}
-void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensusParams, const CInv& inv, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
+void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, const CInv& inv, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
{
bool send = false;
std::shared_ptr<const CBlock> a_recent_block;
std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
bool fWitnessesPresentInARecentCompactBlock;
+ const Consensus::Params& consensusParams = chainparams.GetConsensus();
{
LOCK(cs_most_recent_block);
a_recent_block = most_recent_block;
@@ -1142,6 +1144,15 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
std::shared_ptr<const CBlock> pblock;
if (a_recent_block && a_recent_block->GetHash() == pindex->GetBlockHash()) {
pblock = a_recent_block;
+ } else if (inv.type == MSG_WITNESS_BLOCK) {
+ // Fast-path: in this case it is possible to serve the block directly from disk,
+ // as the network format matches the format on disk
+ std::vector<uint8_t> block_data;
+ if (!ReadRawBlockFromDisk(block_data, pindex, chainparams.MessageStart())) {
+ assert(!"cannot load block from disk");
+ }
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, MakeSpan(block_data)));
+ // Don't set pblock as we've sent the block
} else {
// Send block from disk
std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
@@ -1149,53 +1160,55 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
assert(!"cannot load block from disk");
pblock = pblockRead;
}
- if (inv.type == MSG_BLOCK)
- connman->PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock));
- else if (inv.type == MSG_WITNESS_BLOCK)
- connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock));
- else if (inv.type == MSG_FILTERED_BLOCK)
- {
- bool sendMerkleBlock = false;
- CMerkleBlock merkleBlock;
+ if (pblock) {
+ if (inv.type == MSG_BLOCK)
+ connman->PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::BLOCK, *pblock));
+ else if (inv.type == MSG_WITNESS_BLOCK)
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::BLOCK, *pblock));
+ else if (inv.type == MSG_FILTERED_BLOCK)
{
- LOCK(pfrom->cs_filter);
- if (pfrom->pfilter) {
- sendMerkleBlock = true;
- merkleBlock = CMerkleBlock(*pblock, *pfrom->pfilter);
+ bool sendMerkleBlock = false;
+ CMerkleBlock merkleBlock;
+ {
+ LOCK(pfrom->cs_filter);
+ if (pfrom->pfilter) {
+ sendMerkleBlock = true;
+ merkleBlock = CMerkleBlock(*pblock, *pfrom->pfilter);
+ }
}
+ if (sendMerkleBlock) {
+ connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::MERKLEBLOCK, merkleBlock));
+ // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
+ // This avoids hurting performance by pointlessly requiring a round-trip
+ // Note that there is currently no way for a node to request any single transactions we didn't send here -
+ // they must either disconnect and retry or request the full block.
+ // Thus, the protocol spec specified allows for us to provide duplicate txn here,
+ // however we MUST always provide at least what the remote peer needs
+ typedef std::pair<unsigned int, uint256> PairType;
+ for (PairType& pair : merkleBlock.vMatchedTxn)
+ connman->PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx[pair.first]));
+ }
+ // else
+ // no response
}
- if (sendMerkleBlock) {
- connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::MERKLEBLOCK, merkleBlock));
- // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
- // This avoids hurting performance by pointlessly requiring a round-trip
- // Note that there is currently no way for a node to request any single transactions we didn't send here -
- // they must either disconnect and retry or request the full block.
- // Thus, the protocol spec specified allows for us to provide duplicate txn here,
- // however we MUST always provide at least what the remote peer needs
- typedef std::pair<unsigned int, uint256> PairType;
- for (PairType& pair : merkleBlock.vMatchedTxn)
- connman->PushMessage(pfrom, msgMaker.Make(SERIALIZE_TRANSACTION_NO_WITNESS, NetMsgType::TX, *pblock->vtx[pair.first]));
- }
- // else
- // no response
- }
- else if (inv.type == MSG_CMPCT_BLOCK)
- {
- // If a peer is asking for old blocks, we're almost guaranteed
- // they won't have a useful mempool to match against a compact block,
- // and we don't feel like constructing the object for them, so
- // instead we respond with the full, non-compact block.
- bool fPeerWantsWitness = State(pfrom->GetId())->fWantsCmpctWitness;
- int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
- if (CanDirectFetch(consensusParams) && pindex->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) {
- if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->GetBlockHash()) {
- connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
+ else if (inv.type == MSG_CMPCT_BLOCK)
+ {
+ // If a peer is asking for old blocks, we're almost guaranteed
+ // they won't have a useful mempool to match against a compact block,
+ // and we don't feel like constructing the object for them, so
+ // instead we respond with the full, non-compact block.
+ bool fPeerWantsWitness = State(pfrom->GetId())->fWantsCmpctWitness;
+ int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
+ if (CanDirectFetch(consensusParams) && pindex->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) {
+ if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->GetBlockHash()) {
+ connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
+ } else {
+ CBlockHeaderAndShortTxIDs cmpctblock(*pblock, fPeerWantsWitness);
+ connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
+ }
} else {
- CBlockHeaderAndShortTxIDs cmpctblock(*pblock, fPeerWantsWitness);
- connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, cmpctblock));
+ connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCK, *pblock));
}
- } else {
- connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::BLOCK, *pblock));
}
}
@@ -1213,7 +1226,7 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
}
}
-void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParams, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
+void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
{
AssertLockNotHeld(cs_main);
@@ -1262,7 +1275,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
const CInv &inv = *it;
if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK || inv.type == MSG_CMPCT_BLOCK || inv.type == MSG_WITNESS_BLOCK) {
it++;
- ProcessGetBlockData(pfrom, consensusParams, inv, connman, interruptMsgProc);
+ ProcessGetBlockData(pfrom, chainparams, inv, connman, interruptMsgProc);
}
}
@@ -1579,7 +1592,9 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
// Each connection can only send one version message
if (pfrom->nVersion != 0)
{
- connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, std::string("Duplicate version message")));
+ if (g_enable_bip61) {
+ connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, std::string("Duplicate version message")));
+ }
LOCK(cs_main);
Misbehaving(pfrom->GetId(), 1);
return false;
@@ -1608,8 +1623,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
if (!pfrom->fInbound && !pfrom->fFeeler && !pfrom->m_manual_connection && !HasAllDesirableServiceFlags(nServices))
{
LogPrint(BCLog::NET, "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->GetId(), nServices, GetDesirableServiceFlags(nServices));
- connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD,
- strprintf("Expected to offer services %08x", GetDesirableServiceFlags(nServices))));
+ if (g_enable_bip61) {
+ connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD,
+ strprintf("Expected to offer services %08x", GetDesirableServiceFlags(nServices))));
+ }
pfrom->fDisconnect = true;
return false;
}
@@ -1629,8 +1646,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
{
// disconnect from peers older than this proto version
LogPrint(BCLog::NET, "peer=%d using obsolete version %i; disconnecting\n", pfrom->GetId(), nVersion);
- connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE,
- strprintf("Version must be %d or greater", MIN_PEER_PROTO_VERSION)));
+ if (g_enable_bip61) {
+ connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE,
+ strprintf("Version must be %d or greater", MIN_PEER_PROTO_VERSION)));
+ }
pfrom->fDisconnect = true;
return false;
}
@@ -1972,7 +1991,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
}
pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end());
- ProcessGetData(pfrom, chainparams.GetConsensus(), connman, interruptMsgProc);
+ ProcessGetData(pfrom, chainparams, connman, interruptMsgProc);
}
@@ -2328,9 +2347,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
LogPrint(BCLog::MEMPOOLREJ, "%s from peer=%d was not accepted: %s\n", tx.GetHash().ToString(),
pfrom->GetId(),
FormatStateMessage(state));
- if (state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P
+ if (g_enable_bip61 && state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) { // Never send AcceptToMemoryPool's internal codes over P2P
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(),
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash));
+ }
if (nDoS > 0) {
Misbehaving(pfrom->GetId(), nDoS);
}
@@ -2903,8 +2923,10 @@ static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman* connman)
AssertLockHeld(cs_main);
CNodeState &state = *State(pnode->GetId());
- for (const CBlockReject& reject : state.rejects) {
- connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, std::string(NetMsgType::BLOCK), reject.chRejectCode, reject.strRejectReason, reject.hashBlock));
+ if (g_enable_bip61) {
+ for (const CBlockReject& reject : state.rejects) {
+ connman->PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, std::string(NetMsgType::BLOCK), reject.chRejectCode, reject.strRejectReason, reject.hashBlock));
+ }
}
state.rejects.clear();
@@ -2942,7 +2964,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
bool fMoreWork = false;
if (!pfrom->vRecvGetData.empty())
- ProcessGetData(pfrom, chainparams.GetConsensus(), connman, interruptMsgProc);
+ ProcessGetData(pfrom, chainparams, connman, interruptMsgProc);
if (pfrom->fDisconnect)
return false;
@@ -3011,7 +3033,9 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
}
catch (const std::ios_base::failure& e)
{
- connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, std::string("error parsing message")));
+ if (g_enable_bip61) {
+ connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, std::string("error parsing message")));
+ }
if (strstr(e.what(), "end of data"))
{
// Allow exceptions from under-length message on vRecv
diff --git a/src/net_processing.h b/src/net_processing.h
index 195d0d2033..b0b905d922 100644
--- a/src/net_processing.h
+++ b/src/net_processing.h
@@ -35,6 +35,11 @@ static constexpr int64_t EXTRA_PEER_CHECK_INTERVAL = 45;
/** Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict, in seconds */
static constexpr int64_t MINIMUM_CONNECT_TIME = 30;
+/** Default for BIP61 (sending reject messages) */
+static constexpr bool DEFAULT_ENABLE_BIP61 = true;
+/** Enable BIP61 (sending reject messages) */
+extern bool g_enable_bip61;
+
class PeerLogicValidation final : public CValidationInterface, public NetEventsInterface {
private:
CConnman* const connman;
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index 6f463cabf5..230f762a1b 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -67,18 +67,18 @@ uint256 CTransaction::ComputeHash() const
return SerializeHash(*this, SER_GETHASH, SERIALIZE_TRANSACTION_NO_WITNESS);
}
-uint256 CTransaction::GetWitnessHash() const
+uint256 CTransaction::ComputeWitnessHash() const
{
if (!HasWitness()) {
- return GetHash();
+ return hash;
}
return SerializeHash(*this, SER_GETHASH, 0);
}
/* For backward compatibility, the hash is initialized to 0. TODO: remove the need for this default constructor entirely. */
-CTransaction::CTransaction() : vin(), vout(), nVersion(CTransaction::CURRENT_VERSION), nLockTime(0), hash() {}
-CTransaction::CTransaction(const CMutableTransaction &tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
-CTransaction::CTransaction(CMutableTransaction &&tx) : vin(std::move(tx.vin)), vout(std::move(tx.vout)), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
+CTransaction::CTransaction() : vin(), vout(), nVersion(CTransaction::CURRENT_VERSION), nLockTime(0), hash{}, m_witness_hash{} {}
+CTransaction::CTransaction(const CMutableTransaction& tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash{ComputeHash()}, m_witness_hash{ComputeWitnessHash()} {}
+CTransaction::CTransaction(CMutableTransaction&& tx) : vin(std::move(tx.vin)), vout(std::move(tx.vout)), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash{ComputeHash()}, m_witness_hash{ComputeWitnessHash()} {}
CAmount CTransaction::GetValueOut() const
{
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index cd348fdbe4..1c846d38ec 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -286,8 +286,10 @@ public:
private:
/** Memory only. */
const uint256 hash;
+ const uint256 m_witness_hash;
uint256 ComputeHash() const;
+ uint256 ComputeWitnessHash() const;
public:
/** Construct a CTransaction that qualifies as IsNull() */
@@ -311,12 +313,8 @@ public:
return vin.empty() && vout.empty();
}
- const uint256& GetHash() const {
- return hash;
- }
-
- // Compute a hash that includes both transaction and witness data
- uint256 GetWitnessHash() const;
+ const uint256& GetHash() const { return hash; }
+ const uint256& GetWitnessHash() const { return m_witness_hash; };
// Return sum of txouts.
CAmount GetValueOut() const;
@@ -367,7 +365,7 @@ struct CMutableTransaction
uint32_t nLockTime;
CMutableTransaction();
- CMutableTransaction(const CTransaction& tx);
+ explicit CMutableTransaction(const CTransaction& tx);
template <typename Stream>
inline void Serialize(Stream& s) const {
diff --git a/src/pubkey.h b/src/pubkey.h
index 9c6c6b085e..bb254547c8 100644
--- a/src/pubkey.h
+++ b/src/pubkey.h
@@ -33,10 +33,10 @@ public:
/**
* secp256k1:
*/
- static const unsigned int PUBLIC_KEY_SIZE = 65;
- static const unsigned int COMPRESSED_PUBLIC_KEY_SIZE = 33;
- static const unsigned int SIGNATURE_SIZE = 72;
- static const unsigned int COMPACT_SIGNATURE_SIZE = 65;
+ static constexpr unsigned int PUBLIC_KEY_SIZE = 65;
+ static constexpr unsigned int COMPRESSED_PUBLIC_KEY_SIZE = 33;
+ static constexpr unsigned int SIGNATURE_SIZE = 72;
+ static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65;
/**
* see www.keylength.com
* script supports up to 75 for single byte push
diff --git a/src/qt/README.md b/src/qt/README.md
index d8acf96ceb..bf8139666c 100644
--- a/src/qt/README.md
+++ b/src/qt/README.md
@@ -4,7 +4,7 @@ The current precise version for Qt 5 is specified in [qt.mk](/depends/packages/q
## Compile and run
-See build instructions ([OSX](/doc/build-osx.md), [Windows](/doc/build-windows.md), [Unix](/doc/build-unix.md), etc).
+See build instructions ([macOS](/doc/build-osx.md), [Windows](/doc/build-windows.md), [Unix](/doc/build-unix.md), etc).
To run:
@@ -65,7 +65,7 @@ Represents the view to a single wallet.
* `guiconstants.h`: UI colors, app name, etc
* `guiutil.h`: several helper functions
* `macdockiconhandler.(h/cpp)`
-* `macdockiconhandler.(h/cpp)`: display notifications in OSX
+* `macdockiconhandler.(h/cpp)`: display notifications in macOS
## Contribute
@@ -81,9 +81,9 @@ the UI layout.
Download and install the community edition of [Qt Creator](https://www.qt.io/download/).
Uncheck everything except Qt Creator during the installation process.
-Instructions for OSX:
+Instructions for macOS:
-1. Make sure you installed everything through Homebrew mentioned in the [OSX build instructions](/doc/build-osx.md)
+1. Make sure you installed everything through Homebrew mentioned in the [macOS build instructions](/doc/build-osx.md)
2. Use `./configure` with the `--enable-debug` flag
3. In Qt Creator do "New Project" -> Import Project -> Import Existing Project
4. Enter "bitcoin-qt" as project name, enter src/qt as location
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index d317070e91..31d9f936e7 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -229,6 +229,9 @@ public:
/// Get window identifier of QMainWindow (BitcoinGUI)
WId getMainWinId() const;
+ /// Setup platform style
+ void setupPlatformStyle();
+
public Q_SLOTS:
void initializeResult(bool success);
void shutdownResult();
@@ -315,10 +318,14 @@ BitcoinApplication::BitcoinApplication(interfaces::Node& node, int &argc, char *
paymentServer(0),
m_wallet_models(),
#endif
- returnValue(0)
+ returnValue(0),
+ platformStyle(0)
{
setQuitOnLastWindowClosed(false);
+}
+void BitcoinApplication::setupPlatformStyle()
+{
// UI per-platform customization
// This must be done inside the BitcoinApplication constructor, or after it, because
// PlatformStyle::instantiate requires a QApplication
@@ -546,12 +553,12 @@ static void SetupUIArgs()
#ifdef ENABLE_WALLET
gArgs.AddArg("-allowselfsignedrootcertificates", strprintf("Allow self signed root certificates (default: %u)", DEFAULT_SELFSIGNED_ROOTCERTS), true, OptionsCategory::GUI);
#endif
- gArgs.AddArg("-choosedatadir", strprintf(QObject::tr("Choose data directory on startup (default: %u)").toStdString(), DEFAULT_CHOOSE_DATADIR), false, OptionsCategory::GUI);
- gArgs.AddArg("-lang=<lang>", QObject::tr("Set language, for example \"de_DE\" (default: system locale)").toStdString(), false, OptionsCategory::GUI);
- gArgs.AddArg("-min", QObject::tr("Start minimized").toStdString(), false, OptionsCategory::GUI);
- gArgs.AddArg("-resetguisettings", QObject::tr("Reset all settings changed in the GUI").toStdString(), false, OptionsCategory::GUI);
- gArgs.AddArg("-rootcertificates=<file>", QObject::tr("Set SSL root certificates for payment request (default: -system-)").toStdString(), false, OptionsCategory::GUI);
- gArgs.AddArg("-splash", strprintf(QObject::tr("Show splash screen on startup (default: %u)").toStdString(), DEFAULT_SPLASHSCREEN), false, OptionsCategory::GUI);
+ gArgs.AddArg("-choosedatadir", strprintf("Choose data directory on startup (default: %u)", DEFAULT_CHOOSE_DATADIR), false, OptionsCategory::GUI);
+ gArgs.AddArg("-lang=<lang>", "Set language, for example \"de_DE\" (default: system locale)", false, OptionsCategory::GUI);
+ gArgs.AddArg("-min", "Start minimized", false, OptionsCategory::GUI);
+ gArgs.AddArg("-resetguisettings", "Reset all settings changed in the GUI", false, OptionsCategory::GUI);
+ gArgs.AddArg("-rootcertificates=<file>", "Set SSL root certificates for payment request (default: -system-)", false, OptionsCategory::GUI);
+ gArgs.AddArg("-splash", strprintf("Show splash screen on startup (default: %u)", DEFAULT_SPLASHSCREEN), false, OptionsCategory::GUI);
gArgs.AddArg("-uiplatform", strprintf("Select platform to customize UI for (one of windows, macosx, other; default: %s)", BitcoinGUI::DEFAULT_UIPLATFORM), true, OptionsCategory::GUI);
}
@@ -562,15 +569,9 @@ int main(int argc, char *argv[])
std::unique_ptr<interfaces::Node> node = interfaces::MakeNode();
- /// 1. Parse command-line options. These take precedence over anything else.
- // Command-line options take precedence:
- node->setupServerArgs();
- SetupUIArgs();
- node->parseParameters(argc, argv);
-
// Do not refer to data directory yet, this can be overridden by Intro::pickDataDirectory
- /// 2. Basic Qt initialization (not dependent on parameters or configuration)
+ /// 1. Basic Qt initialization (not dependent on parameters or configuration)
#if QT_VERSION < 0x050000
// Internal string conversion is all UTF-8
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
@@ -609,6 +610,20 @@ int main(int argc, char *argv[])
qRegisterMetaType<WalletModel*>("WalletModel*");
#endif
+ /// 2. Parse command-line options. We do this after qt in order to show an error if there are problems parsing these
+ // Command-line options take precedence:
+ node->setupServerArgs();
+ SetupUIArgs();
+ std::string error;
+ if (!node->parseParameters(argc, argv, error)) {
+ QMessageBox::critical(0, QObject::tr(PACKAGE_NAME),
+ QObject::tr("Error parsing command line arguments: %1.").arg(QString::fromStdString(error)));
+ return EXIT_FAILURE;
+ }
+
+ // Now that the QApplication is setup and we have parsed our parameters, we can set the platform style
+ app.setupPlatformStyle();
+
/// 3. Application identification
// must be set before OptionsModel is initialized or translations are loaded,
// as it is used to locate QSettings
@@ -644,11 +659,9 @@ int main(int argc, char *argv[])
QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-datadir", ""))));
return EXIT_FAILURE;
}
- try {
- node->readConfigFiles();
- } catch (const std::exception& e) {
+ if (!node->readConfigFiles(error)) {
QMessageBox::critical(0, QObject::tr(PACKAGE_NAME),
- QObject::tr("Error: Cannot parse configuration file: %1. Only use key=value syntax.").arg(e.what()));
+ QObject::tr("Error: Cannot parse configuration file: %1.").arg(QString::fromStdString(error)));
return EXIT_FAILURE;
}
diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp
index e8307ff125..68a9dc4c27 100644
--- a/src/qt/bitcoinamountfield.cpp
+++ b/src/qt/bitcoinamountfield.cpp
@@ -197,7 +197,7 @@ BitcoinAmountField::BitcoinAmountField(QWidget *parent) :
amount = new AmountSpinBox(this);
amount->setLocale(QLocale::c());
amount->installEventFilter(this);
- amount->setMaximumWidth(170);
+ amount->setMaximumWidth(240);
QHBoxLayout *layout = new QHBoxLayout(this);
layout->addWidget(amount);
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 5511ca84e6..9f5ea02e14 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -476,7 +476,7 @@ void BitcoinGUI::createToolBars()
toolbar->addWidget(spacer);
m_wallet_selector = new QComboBox();
- connect(m_wallet_selector, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(setCurrentWallet(const QString&)));
+ connect(m_wallet_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(setCurrentWalletBySelectorIndex(int)));
#endif
}
}
@@ -552,8 +552,9 @@ bool BitcoinGUI::addWallet(WalletModel *walletModel)
if(!walletFrame)
return false;
const QString name = walletModel->getWalletName();
+ QString display_name = name.isEmpty() ? "["+tr("default wallet")+"]" : name;
setWalletActionsEnabled(true);
- m_wallet_selector->addItem(name);
+ m_wallet_selector->addItem(display_name, name);
if (m_wallet_selector->count() == 2) {
m_wallet_selector_label = new QLabel();
m_wallet_selector_label->setText(tr("Wallet:") + " ");
@@ -572,6 +573,12 @@ bool BitcoinGUI::setCurrentWallet(const QString& name)
return walletFrame->setCurrentWallet(name);
}
+bool BitcoinGUI::setCurrentWalletBySelectorIndex(int index)
+{
+ QString internal_name = m_wallet_selector->itemData(index).toString();
+ return setCurrentWallet(internal_name);
+}
+
void BitcoinGUI::removeAllWallets()
{
if(!walletFrame)
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 8ce14f06c6..89c1c73a79 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -186,6 +186,7 @@ public Q_SLOTS:
#ifdef ENABLE_WALLET
bool setCurrentWallet(const QString& name);
+ bool setCurrentWalletBySelectorIndex(int index);
/** Set the UI status indicators based on the currently selected wallet.
*/
void updateWalletStatus();
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 4032729a84..4550ae9396 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -312,7 +312,7 @@ bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strRes
std::string method = stack.back()[0];
std::string uri;
#ifdef ENABLE_WALLET
- if (walletID && !walletID->empty()) {
+ if (walletID) {
QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(*walletID));
uri = "/wallet/"+std::string(encodedName.constData(), encodedName.length());
}
@@ -425,7 +425,7 @@ void RPCExecutor::request(const QString &command, const QString &walletID)
return;
}
std::string wallet_id = walletID.toStdString();
- if(!RPCConsole::RPCExecuteCommandLine(m_node, result, executableCommand, nullptr, &wallet_id))
+ if (!RPCConsole::RPCExecuteCommandLine(m_node, result, executableCommand, nullptr, walletID.isNull() ? nullptr : &wallet_id))
{
Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
return;
@@ -702,7 +702,8 @@ void RPCConsole::addWallet(WalletModel * const walletModel)
{
const QString name = walletModel->getWalletName();
// use name for text and internal data object (to allow to move to a wallet id later)
- ui->WalletSelector->addItem(name, name);
+ QString display_name = name.isEmpty() ? "["+tr("default wallet")+"]" : name;
+ ui->WalletSelector->addItem(display_name, name);
if (ui->WalletSelector->count() == 2 && !isVisible()) {
// First wallet added, set to default so long as the window isn't presently visible (and potentially in use)
ui->WalletSelector->setCurrentIndex(1);
@@ -909,7 +910,7 @@ void RPCConsole::on_lineEdit_returnPressed()
}
if (m_last_wallet_id != walletID) {
- if (walletID.isEmpty()) {
+ if (walletID.isNull()) {
message(CMD_REQUEST, tr("Executing command without any wallet"));
} else {
message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(walletID));
diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp
index 0c2e7ae71d..c3d33c76d4 100644
--- a/src/qt/test/addressbooktests.cpp
+++ b/src/qt/test/addressbooktests.cpp
@@ -56,15 +56,15 @@ void EditAddressAndSubmit(
void TestAddAddressesToSendBook()
{
TestChain100Setup test;
- CWallet wallet("mock", WalletDatabase::CreateMock());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("mock", WalletDatabase::CreateMock());
bool firstRun;
- wallet.LoadWallet(firstRun);
+ wallet->LoadWallet(firstRun);
auto build_address = [&wallet]() {
CKey key;
key.MakeNewKey(true);
CTxDestination dest(GetDestinationForKey(
- key.GetPubKey(), wallet.m_default_address_type));
+ key.GetPubKey(), wallet->m_default_address_type));
return std::make_pair(dest, QString::fromStdString(EncodeDestination(dest)));
};
@@ -87,13 +87,13 @@ void TestAddAddressesToSendBook()
std::tie(std::ignore, new_address) = build_address();
{
- LOCK(wallet.cs_wallet);
- wallet.SetAddressBook(r_key_dest, r_label.toStdString(), "receive");
- wallet.SetAddressBook(s_key_dest, s_label.toStdString(), "send");
+ LOCK(wallet->cs_wallet);
+ wallet->SetAddressBook(r_key_dest, r_label.toStdString(), "receive");
+ wallet->SetAddressBook(s_key_dest, s_label.toStdString(), "send");
}
auto check_addbook_size = [&wallet](int expected_size) {
- QCOMPARE(static_cast<int>(wallet.mapAddressBook.size()), expected_size);
+ QCOMPARE(static_cast<int>(wallet->mapAddressBook.size()), expected_size);
};
// We should start with the two addresses we added earlier and nothing else.
@@ -103,9 +103,9 @@ void TestAddAddressesToSendBook()
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
auto node = interfaces::MakeNode();
OptionsModel optionsModel(*node);
- AddWallet(&wallet);
+ AddWallet(wallet);
WalletModel walletModel(std::move(node->getWallets()[0]), *node, platformStyle.get(), &optionsModel);
- RemoveWallet(&wallet);
+ RemoveWallet(wallet);
EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress);
editAddressDialog.setModel(walletModel.getAddressTableModel());
diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp
index a09d98dfe5..33c49dc7cb 100644
--- a/src/qt/test/wallettests.cpp
+++ b/src/qt/test/wallettests.cpp
@@ -144,21 +144,21 @@ void TestGUI()
for (int i = 0; i < 5; ++i) {
test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey()));
}
- CWallet wallet("mock", WalletDatabase::CreateMock());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("mock", WalletDatabase::CreateMock());
bool firstRun;
- wallet.LoadWallet(firstRun);
+ wallet->LoadWallet(firstRun);
{
- LOCK(wallet.cs_wallet);
- wallet.SetAddressBook(GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet.m_default_address_type), "", "receive");
- wallet.AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
+ LOCK(wallet->cs_wallet);
+ wallet->SetAddressBook(GetDestinationForKey(test.coinbaseKey.GetPubKey(), wallet->m_default_address_type), "", "receive");
+ wallet->AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey());
}
{
LOCK(cs_main);
- WalletRescanReserver reserver(&wallet);
+ WalletRescanReserver reserver(wallet.get());
reserver.reserve();
- wallet.ScanForWalletTransactions(chainActive.Genesis(), nullptr, reserver, true);
+ wallet->ScanForWalletTransactions(chainActive.Genesis(), nullptr, reserver, true);
}
- wallet.SetBroadcastTransactions(true);
+ wallet->SetBroadcastTransactions(true);
// Create widgets for sending coins and listing transactions.
std::unique_ptr<const PlatformStyle> platformStyle(PlatformStyle::instantiate("other"));
@@ -166,17 +166,17 @@ void TestGUI()
TransactionView transactionView(platformStyle.get());
auto node = interfaces::MakeNode();
OptionsModel optionsModel(*node);
- AddWallet(&wallet);
+ AddWallet(wallet);
WalletModel walletModel(std::move(node->getWallets().back()), *node, platformStyle.get(), &optionsModel);
- RemoveWallet(&wallet);
+ RemoveWallet(wallet);
sendCoinsDialog.setModel(&walletModel);
transactionView.setModel(&walletModel);
// Send two transactions, and verify they are added to transaction list.
TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel();
QCOMPARE(transactionTableModel->rowCount({}), 105);
- uint256 txid1 = SendCoins(wallet, sendCoinsDialog, CKeyID(), 5 * COIN, false /* rbf */);
- uint256 txid2 = SendCoins(wallet, sendCoinsDialog, CKeyID(), 10 * COIN, true /* rbf */);
+ uint256 txid1 = SendCoins(*wallet.get(), sendCoinsDialog, CKeyID(), 5 * COIN, false /* rbf */);
+ uint256 txid2 = SendCoins(*wallet.get(), sendCoinsDialog, CKeyID(), 10 * COIN, true /* rbf */);
QCOMPARE(transactionTableModel->rowCount({}), 107);
QVERIFY(FindTx(*transactionTableModel, txid1).isValid());
QVERIFY(FindTx(*transactionTableModel, txid2).isValid());
diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp
index 993d7454d6..1da25b0761 100644
--- a/src/qt/utilitydialog.cpp
+++ b/src/qt/utilitydialog.cpp
@@ -70,8 +70,8 @@ HelpMessageDialog::HelpMessageDialog(interfaces::Node& node, QWidget *parent, bo
ui->helpMessage->setVisible(false);
} else {
setWindowTitle(tr("Command-line options"));
- QString header = tr("Usage:") + "\n" +
- " bitcoin-qt [" + tr("command-line options") + "] " + "\n";
+ QString header = "Usage:\n"
+ " bitcoin-qt [command-line options] \n";
QTextCursor cursor(ui->helpMessage->document());
cursor.insertText(version);
cursor.insertBlock();
diff --git a/src/random.cpp b/src/random.cpp
index 491272d5f3..fee6c2d92a 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -34,6 +34,7 @@
#include <sys/random.h>
#endif
#ifdef HAVE_SYSCTL_ARND
+#include <utilstrencodings.h> // for ARRAYLEN
#include <sys/sysctl.h>
#endif
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 5cfc14e89d..48e0e02d1a 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -12,6 +12,7 @@
#include <consensus/validation.h>
#include <validation.h>
#include <core_io.h>
+#include <index/txindex.h>
#include <policy/feerate.h>
#include <policy/policy.h>
#include <primitives/transaction.h>
@@ -30,6 +31,7 @@
#include <univalue.h>
+#include <boost/algorithm/string.hpp>
#include <boost/thread/thread.hpp> // boost::thread::interrupt
#include <memory>
@@ -727,6 +729,25 @@ static UniValue getblockheader(const JSONRPCRequest& request)
return blockheaderToJSON(pblockindex);
}
+static CBlock GetBlockChecked(const CBlockIndex* pblockindex)
+{
+ CBlock block;
+ if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Block not available (pruned data)");
+ }
+
+ if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) {
+ // Block not found on disk. This could be because we have the block
+ // header in our index but don't have the block (for example if a
+ // non-whitelisted node sends us an unrequested long chain of valid
+ // blocks, we add the headers to our index, but don't accept the
+ // block).
+ throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk");
+ }
+
+ return block;
+}
+
static UniValue getblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
@@ -795,17 +816,7 @@ static UniValue getblock(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
}
- CBlock block;
- if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
- throw JSONRPCError(RPC_MISC_ERROR, "Block not available (pruned data)");
-
- if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
- // Block not found on disk. This could be because we have the block
- // header in our index but don't have the block (for example if a
- // non-whitelisted node sends us an unrequested long chain of valid
- // blocks, we add the headers to our index, but don't accept the
- // block).
- throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk");
+ const CBlock block = GetBlockChecked(pblockindex);
if (verbosity <= 0)
{
@@ -1604,6 +1615,284 @@ static UniValue getchaintxstats(const JSONRPCRequest& request)
return ret;
}
+template<typename T>
+static T CalculateTruncatedMedian(std::vector<T>& scores)
+{
+ size_t size = scores.size();
+ if (size == 0) {
+ return 0;
+ }
+
+ std::sort(scores.begin(), scores.end());
+ if (size % 2 == 0) {
+ return (scores[size / 2 - 1] + scores[size / 2]) / 2;
+ } else {
+ return scores[size / 2];
+ }
+}
+
+template<typename T>
+static inline bool SetHasKeys(const std::set<T>& set) {return false;}
+template<typename T, typename Tk, typename... Args>
+static inline bool SetHasKeys(const std::set<T>& set, const Tk& key, const Args&... args)
+{
+ return (set.count(key) != 0) || SetHasKeys(set, args...);
+}
+
+// outpoint (needed for the utxo index) + nHeight + fCoinBase
+static constexpr size_t PER_UTXO_OVERHEAD = sizeof(COutPoint) + sizeof(uint32_t) + sizeof(bool);
+
+static UniValue getblockstats(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 4) {
+ throw std::runtime_error(
+ "getblockstats hash_or_height ( stats )\n"
+ "\nCompute per block statistics for a given window. All amounts are in satoshis.\n"
+ "It won't work for some heights with pruning.\n"
+ "It won't work without -txindex for utxo_size_inc, *fee or *feerate stats.\n"
+ "\nArguments:\n"
+ "1. \"hash_or_height\" (string or numeric, required) The block hash or height of the target block\n"
+ "2. \"stats\" (array, optional) Values to plot, by default all values (see result below)\n"
+ " [\n"
+ " \"height\", (string, optional) Selected statistic\n"
+ " \"time\", (string, optional) Selected statistic\n"
+ " ,...\n"
+ " ]\n"
+ "\nResult:\n"
+ "{ (json object)\n"
+ " \"avgfee\": xxxxx, (numeric) Average fee in the block\n"
+ " \"avgfeerate\": xxxxx, (numeric) Average feerate (in satoshis per virtual byte)\n"
+ " \"avgtxsize\": xxxxx, (numeric) Average transaction size\n"
+ " \"blockhash\": xxxxx, (string) The block hash (to check for potential reorgs)\n"
+ " \"height\": xxxxx, (numeric) The height of the block\n"
+ " \"ins\": xxxxx, (numeric) The number of inputs (excluding coinbase)\n"
+ " \"maxfee\": xxxxx, (numeric) Maximum fee in the block\n"
+ " \"maxfeerate\": xxxxx, (numeric) Maximum feerate (in satoshis per virtual byte)\n"
+ " \"maxtxsize\": xxxxx, (numeric) Maximum transaction size\n"
+ " \"medianfee\": xxxxx, (numeric) Truncated median fee in the block\n"
+ " \"medianfeerate\": xxxxx, (numeric) Truncated median feerate (in satoshis per virtual byte)\n"
+ " \"mediantime\": xxxxx, (numeric) The block median time past\n"
+ " \"mediantxsize\": xxxxx, (numeric) Truncated median transaction size\n"
+ " \"minfee\": xxxxx, (numeric) Minimum fee in the block\n"
+ " \"minfeerate\": xxxxx, (numeric) Minimum feerate (in satoshis per virtual byte)\n"
+ " \"mintxsize\": xxxxx, (numeric) Minimum transaction size\n"
+ " \"outs\": xxxxx, (numeric) The number of outputs\n"
+ " \"subsidy\": xxxxx, (numeric) The block subsidy\n"
+ " \"swtotal_size\": xxxxx, (numeric) Total size of all segwit transactions\n"
+ " \"swtotal_weight\": xxxxx, (numeric) Total weight of all segwit transactions divided by segwit scale factor (4)\n"
+ " \"swtxs\": xxxxx, (numeric) The number of segwit transactions\n"
+ " \"time\": xxxxx, (numeric) The block time\n"
+ " \"total_out\": xxxxx, (numeric) Total amount in all outputs (excluding coinbase and thus reward [ie subsidy + totalfee])\n"
+ " \"total_size\": xxxxx, (numeric) Total size of all non-coinbase transactions\n"
+ " \"total_weight\": xxxxx, (numeric) Total weight of all non-coinbase transactions divided by segwit scale factor (4)\n"
+ " \"totalfee\": xxxxx, (numeric) The fee total\n"
+ " \"txs\": xxxxx, (numeric) The number of transactions (excluding coinbase)\n"
+ " \"utxo_increase\": xxxxx, (numeric) The increase/decrease in the number of unspent outputs\n"
+ " \"utxo_size_inc\": xxxxx, (numeric) The increase/decrease in size for the utxo index (not discounting op_return and similar)\n"
+ "}\n"
+ "\nExamples:\n"
+ + HelpExampleCli("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'")
+ + HelpExampleRpc("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'")
+ );
+ }
+
+ LOCK(cs_main);
+
+ CBlockIndex* pindex;
+ if (request.params[0].isNum()) {
+ const int height = request.params[0].get_int();
+ const int current_tip = chainActive.Height();
+ if (height < 0) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Target block height %d is negative", height));
+ }
+ if (height > current_tip) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Target block height %d after current tip %d", height, current_tip));
+ }
+
+ pindex = chainActive[height];
+ } else {
+ const std::string strHash = request.params[0].get_str();
+ const uint256 hash(uint256S(strHash));
+ pindex = LookupBlockIndex(hash);
+ if (!pindex) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
+ }
+ if (!chainActive.Contains(pindex)) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Block is not in chain %s", Params().NetworkIDString()));
+ }
+ }
+
+ assert(pindex != nullptr);
+
+ std::set<std::string> stats;
+ if (!request.params[1].isNull()) {
+ const UniValue stats_univalue = request.params[1].get_array();
+ for (unsigned int i = 0; i < stats_univalue.size(); i++) {
+ const std::string stat = stats_univalue[i].get_str();
+ stats.insert(stat);
+ }
+ }
+
+ const CBlock block = GetBlockChecked(pindex);
+
+ const bool do_all = stats.size() == 0; // Calculate everything if nothing selected (default)
+ const bool do_mediantxsize = do_all || stats.count("mediantxsize") != 0;
+ const bool do_medianfee = do_all || stats.count("medianfee") != 0;
+ const bool do_medianfeerate = do_all || stats.count("medianfeerate") != 0;
+ const bool loop_inputs = do_all || do_medianfee || do_medianfeerate ||
+ SetHasKeys(stats, "utxo_size_inc", "totalfee", "avgfee", "avgfeerate", "minfee", "maxfee", "minfeerate", "maxfeerate");
+ const bool loop_outputs = do_all || loop_inputs || stats.count("total_out");
+ const bool do_calculate_size = do_mediantxsize ||
+ SetHasKeys(stats, "total_size", "avgtxsize", "mintxsize", "maxtxsize", "swtotal_size");
+ const bool do_calculate_weight = do_all || SetHasKeys(stats, "total_weight", "avgfeerate", "swtotal_weight", "avgfeerate", "medianfeerate", "minfeerate", "maxfeerate");
+ const bool do_calculate_sw = do_all || SetHasKeys(stats, "swtxs", "swtotal_size", "swtotal_weight");
+
+ CAmount maxfee = 0;
+ CAmount maxfeerate = 0;
+ CAmount minfee = MAX_MONEY;
+ CAmount minfeerate = MAX_MONEY;
+ CAmount total_out = 0;
+ CAmount totalfee = 0;
+ int64_t inputs = 0;
+ int64_t maxtxsize = 0;
+ int64_t mintxsize = MAX_BLOCK_SERIALIZED_SIZE;
+ int64_t outputs = 0;
+ int64_t swtotal_size = 0;
+ int64_t swtotal_weight = 0;
+ int64_t swtxs = 0;
+ int64_t total_size = 0;
+ int64_t total_weight = 0;
+ int64_t utxo_size_inc = 0;
+ std::vector<CAmount> fee_array;
+ std::vector<CAmount> feerate_array;
+ std::vector<int64_t> txsize_array;
+
+ for (const auto& tx : block.vtx) {
+ outputs += tx->vout.size();
+
+ CAmount tx_total_out = 0;
+ if (loop_outputs) {
+ for (const CTxOut& out : tx->vout) {
+ tx_total_out += out.nValue;
+ utxo_size_inc += GetSerializeSize(out, SER_NETWORK, PROTOCOL_VERSION) + PER_UTXO_OVERHEAD;
+ }
+ }
+
+ if (tx->IsCoinBase()) {
+ continue;
+ }
+
+ inputs += tx->vin.size(); // Don't count coinbase's fake input
+ total_out += tx_total_out; // Don't count coinbase reward
+
+ int64_t tx_size = 0;
+ if (do_calculate_size) {
+
+ tx_size = tx->GetTotalSize();
+ if (do_mediantxsize) {
+ txsize_array.push_back(tx_size);
+ }
+ maxtxsize = std::max(maxtxsize, tx_size);
+ mintxsize = std::min(mintxsize, tx_size);
+ total_size += tx_size;
+ }
+
+ int64_t weight = 0;
+ if (do_calculate_weight) {
+ weight = GetTransactionWeight(*tx);
+ total_weight += weight;
+ }
+
+ if (do_calculate_sw && tx->HasWitness()) {
+ ++swtxs;
+ swtotal_size += tx_size;
+ swtotal_weight += weight;
+ }
+
+ if (loop_inputs) {
+
+ if (!g_txindex) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "One or more of the selected stats requires -txindex enabled");
+ }
+ CAmount tx_total_in = 0;
+ for (const CTxIn& in : tx->vin) {
+ CTransactionRef tx_in;
+ uint256 hashBlock;
+ if (!GetTransaction(in.prevout.hash, tx_in, Params().GetConsensus(), hashBlock, false)) {
+ throw JSONRPCError(RPC_INTERNAL_ERROR, std::string("Unexpected internal error (tx index seems corrupt)"));
+ }
+
+ CTxOut prevoutput = tx_in->vout[in.prevout.n];
+
+ tx_total_in += prevoutput.nValue;
+ utxo_size_inc -= GetSerializeSize(prevoutput, SER_NETWORK, PROTOCOL_VERSION) + PER_UTXO_OVERHEAD;
+ }
+
+ CAmount txfee = tx_total_in - tx_total_out;
+ assert(MoneyRange(txfee));
+ if (do_medianfee) {
+ fee_array.push_back(txfee);
+ }
+ maxfee = std::max(maxfee, txfee);
+ minfee = std::min(minfee, txfee);
+ totalfee += txfee;
+
+ // New feerate uses satoshis per virtual byte instead of per serialized byte
+ CAmount feerate = weight ? (txfee * WITNESS_SCALE_FACTOR) / weight : 0;
+ if (do_medianfeerate) {
+ feerate_array.push_back(feerate);
+ }
+ maxfeerate = std::max(maxfeerate, feerate);
+ minfeerate = std::min(minfeerate, feerate);
+ }
+ }
+
+ UniValue ret_all(UniValue::VOBJ);
+ ret_all.pushKV("avgfee", (block.vtx.size() > 1) ? totalfee / (block.vtx.size() - 1) : 0);
+ ret_all.pushKV("avgfeerate", total_weight ? (totalfee * WITNESS_SCALE_FACTOR) / total_weight : 0); // Unit: sat/vbyte
+ ret_all.pushKV("avgtxsize", (block.vtx.size() > 1) ? total_size / (block.vtx.size() - 1) : 0);
+ ret_all.pushKV("blockhash", pindex->GetBlockHash().GetHex());
+ ret_all.pushKV("height", (int64_t)pindex->nHeight);
+ ret_all.pushKV("ins", inputs);
+ ret_all.pushKV("maxfee", maxfee);
+ ret_all.pushKV("maxfeerate", maxfeerate);
+ ret_all.pushKV("maxtxsize", maxtxsize);
+ ret_all.pushKV("medianfee", CalculateTruncatedMedian(fee_array));
+ ret_all.pushKV("medianfeerate", CalculateTruncatedMedian(feerate_array));
+ ret_all.pushKV("mediantime", pindex->GetMedianTimePast());
+ ret_all.pushKV("mediantxsize", CalculateTruncatedMedian(txsize_array));
+ ret_all.pushKV("minfee", (minfee == MAX_MONEY) ? 0 : minfee);
+ ret_all.pushKV("minfeerate", (minfeerate == MAX_MONEY) ? 0 : minfeerate);
+ ret_all.pushKV("mintxsize", mintxsize == MAX_BLOCK_SERIALIZED_SIZE ? 0 : mintxsize);
+ ret_all.pushKV("outs", outputs);
+ ret_all.pushKV("subsidy", GetBlockSubsidy(pindex->nHeight, Params().GetConsensus()));
+ ret_all.pushKV("swtotal_size", swtotal_size);
+ ret_all.pushKV("swtotal_weight", swtotal_weight);
+ ret_all.pushKV("swtxs", swtxs);
+ ret_all.pushKV("time", pindex->GetBlockTime());
+ ret_all.pushKV("total_out", total_out);
+ ret_all.pushKV("total_size", total_size);
+ ret_all.pushKV("total_weight", total_weight);
+ ret_all.pushKV("totalfee", totalfee);
+ ret_all.pushKV("txs", (int64_t)block.vtx.size());
+ ret_all.pushKV("utxo_increase", outputs - inputs);
+ ret_all.pushKV("utxo_size_inc", utxo_size_inc);
+
+ if (do_all) {
+ return ret_all;
+ }
+
+ UniValue ret(UniValue::VOBJ);
+ for (const std::string& stat : stats) {
+ const UniValue& value = ret_all[stat];
+ if (value.isNull()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid selected statistic %s", stat));
+ }
+ ret.pushKV(stat, value);
+ }
+ return ret;
+}
+
static UniValue savemempool(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0) {
@@ -1632,6 +1921,7 @@ static const CRPCCommand commands[] =
// --------------------- ------------------------ ----------------------- ----------
{ "blockchain", "getblockchaininfo", &getblockchaininfo, {} },
{ "blockchain", "getchaintxstats", &getchaintxstats, {"nblocks", "blockhash"} },
+ { "blockchain", "getblockstats", &getblockstats, {"hash_or_height", "stats"} },
{ "blockchain", "getbestblockhash", &getbestblockhash, {} },
{ "blockchain", "getblockcount", &getblockcount, {} },
{ "blockchain", "getblock", &getblock, {"blockhash","verbosity|verbose"} },
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index 475fe1e274..bb68f72ccc 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -123,6 +123,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "importmulti", 1, "options" },
{ "verifychain", 0, "checklevel" },
{ "verifychain", 1, "nblocks" },
+ { "getblockstats", 0, "hash_or_height" },
+ { "getblockstats", 1, "stats" },
{ "pruneblockchain", 0, "height" },
{ "keypoolrefill", 0, "newsize" },
{ "getrawmempool", 0, "verbose" },
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index c5185ca599..3b3f43edea 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -748,7 +748,7 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request)
}
}
- UpdateTransaction(mergedTx, i, sigdata);
+ UpdateInput(txin, sigdata);
}
return EncodeHexTx(mergedTx);
@@ -882,7 +882,7 @@ UniValue SignTransaction(CMutableTransaction& mtx, const UniValue& prevTxsUnival
}
sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(mtx, i));
- UpdateTransaction(mtx, i, sigdata);
+ UpdateInput(txin, sigdata);
ScriptError serror = SCRIPT_ERR_OK;
if (!VerifyScript(txin.scriptSig, prevPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
@@ -988,7 +988,8 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
UniValue signrawtransaction(const JSONRPCRequest& request)
{
#ifdef ENABLE_WALLET
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
#endif
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 13f41a7cbf..4b982d647d 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1089,9 +1089,11 @@ namespace {
* Wrapper that serializes like CTransaction, but with the modifications
* required for the signature hash done in-place
*/
-class CTransactionSignatureSerializer {
+template <class T>
+class CTransactionSignatureSerializer
+{
private:
- const CTransaction& txTo; //!< reference to the spending transaction (the one being serialized)
+ const T& txTo; //!< reference to the spending transaction (the one being serialized)
const CScript& scriptCode; //!< output script being consumed
const unsigned int nIn; //!< input index of txTo being signed
const bool fAnyoneCanPay; //!< whether the hashtype has the SIGHASH_ANYONECANPAY flag set
@@ -1099,7 +1101,7 @@ private:
const bool fHashNone; //!< whether the hashtype is SIGHASH_NONE
public:
- CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
+ CTransactionSignatureSerializer(const T& txToIn, const CScript& scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
txTo(txToIn), scriptCode(scriptCodeIn), nIn(nInIn),
fAnyoneCanPay(!!(nHashTypeIn & SIGHASH_ANYONECANPAY)),
fHashSingle((nHashTypeIn & 0x1f) == SIGHASH_SINGLE),
@@ -1180,7 +1182,9 @@ public:
}
};
-uint256 GetPrevoutHash(const CTransaction& txTo) {
+template <class T>
+uint256 GetPrevoutHash(const T& txTo)
+{
CHashWriter ss(SER_GETHASH, 0);
for (const auto& txin : txTo.vin) {
ss << txin.prevout;
@@ -1188,7 +1192,9 @@ uint256 GetPrevoutHash(const CTransaction& txTo) {
return ss.GetHash();
}
-uint256 GetSequenceHash(const CTransaction& txTo) {
+template <class T>
+uint256 GetSequenceHash(const T& txTo)
+{
CHashWriter ss(SER_GETHASH, 0);
for (const auto& txin : txTo.vin) {
ss << txin.nSequence;
@@ -1196,7 +1202,9 @@ uint256 GetSequenceHash(const CTransaction& txTo) {
return ss.GetHash();
}
-uint256 GetOutputsHash(const CTransaction& txTo) {
+template <class T>
+uint256 GetOutputsHash(const T& txTo)
+{
CHashWriter ss(SER_GETHASH, 0);
for (const auto& txout : txTo.vout) {
ss << txout;
@@ -1206,7 +1214,8 @@ uint256 GetOutputsHash(const CTransaction& txTo) {
} // namespace
-PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo)
+template <class T>
+PrecomputedTransactionData::PrecomputedTransactionData(const T& txTo)
{
// Cache is calculated only for transactions with witness
if (txTo.HasWitness()) {
@@ -1217,7 +1226,12 @@ PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo)
}
}
-uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
+// explicit instantiation
+template PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo);
+template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo);
+
+template <class T>
+uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
{
assert(nIn < txTo.vin.size());
@@ -1278,7 +1292,7 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
}
// Wrapper to serialize only the necessary parts of the transaction being signed
- CTransactionSignatureSerializer txTmp(txTo, scriptCode, nIn, nHashType);
+ CTransactionSignatureSerializer<T> txTmp(txTo, scriptCode, nIn, nHashType);
// Serialize and hash
CHashWriter ss(SER_GETHASH, 0);
@@ -1286,12 +1300,14 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig
return ss.GetHash();
}
-bool TransactionSignatureChecker::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
+template <class T>
+bool GenericTransactionSignatureChecker<T>::VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& pubkey, const uint256& sighash) const
{
return pubkey.Verify(sighash, vchSig);
}
-bool TransactionSignatureChecker::CheckSig(const std::vector<unsigned char>& vchSigIn, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
+template <class T>
+bool GenericTransactionSignatureChecker<T>::CheckSig(const std::vector<unsigned char>& vchSigIn, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
{
CPubKey pubkey(vchPubKey);
if (!pubkey.IsValid())
@@ -1312,7 +1328,8 @@ bool TransactionSignatureChecker::CheckSig(const std::vector<unsigned char>& vch
return true;
}
-bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) const
+template <class T>
+bool GenericTransactionSignatureChecker<T>::CheckLockTime(const CScriptNum& nLockTime) const
{
// There are two kinds of nLockTime: lock-by-blockheight
// and lock-by-blocktime, distinguished by whether
@@ -1348,7 +1365,8 @@ bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) con
return true;
}
-bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) const
+template <class T>
+bool GenericTransactionSignatureChecker<T>::CheckSequence(const CScriptNum& nSequence) const
{
// Relative lock times are supported by comparing the passed
// in operand to the sequence number of the input.
@@ -1394,6 +1412,10 @@ bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) con
return true;
}
+// explicit instantiation
+template class GenericTransactionSignatureChecker<CTransaction>;
+template class GenericTransactionSignatureChecker<CMutableTransaction>;
+
static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion, const std::vector<unsigned char>& program, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
{
std::vector<std::vector<unsigned char> > stack;
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 2800473a68..2d21aa81df 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -124,7 +124,8 @@ struct PrecomputedTransactionData
uint256 hashPrevouts, hashSequence, hashOutputs;
bool ready = false;
- explicit PrecomputedTransactionData(const CTransaction& tx);
+ template <class T>
+ explicit PrecomputedTransactionData(const T& tx);
};
enum class SigVersion
@@ -137,7 +138,8 @@ enum class SigVersion
static constexpr size_t WITNESS_V0_SCRIPTHASH_SIZE = 32;
static constexpr size_t WITNESS_V0_KEYHASH_SIZE = 20;
-uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = nullptr);
+template <class T>
+uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = nullptr);
class BaseSignatureChecker
{
@@ -160,10 +162,11 @@ public:
virtual ~BaseSignatureChecker() {}
};
-class TransactionSignatureChecker : public BaseSignatureChecker
+template <class T>
+class GenericTransactionSignatureChecker : public BaseSignatureChecker
{
private:
- const CTransaction* txTo;
+ const T* txTo;
unsigned int nIn;
const CAmount amount;
const PrecomputedTransactionData* txdata;
@@ -172,21 +175,15 @@ protected:
virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
public:
- TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(nullptr) {}
- TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {}
+ GenericTransactionSignatureChecker(const T* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(nullptr) {}
+ GenericTransactionSignatureChecker(const T* txToIn, unsigned int nInIn, const CAmount& amountIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {}
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override;
bool CheckLockTime(const CScriptNum& nLockTime) const override;
bool CheckSequence(const CScriptNum& nSequence) const override;
};
-class MutableTransactionSignatureChecker : public TransactionSignatureChecker
-{
-private:
- const CTransaction txTo;
-
-public:
- MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : TransactionSignatureChecker(&txTo, nInIn, amountIn), txTo(*txToIn) {}
-};
+using TransactionSignatureChecker = GenericTransactionSignatureChecker<CTransaction>;
+using MutableTransactionSignatureChecker = GenericTransactionSignatureChecker<CMutableTransaction>;
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = nullptr);
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror = nullptr);
diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp
index fefa02fdef..43dd9e582e 100644
--- a/src/script/ismine.cpp
+++ b/src/script/ismine.cpp
@@ -28,6 +28,19 @@ enum class IsMineSigVersion
WITNESS_V0 = 2 //! P2WSH witness script execution
};
+/**
+ * This is an internal representation of isminetype + invalidity.
+ * Its order is significant, as we return the max of all explored
+ * possibilities.
+ */
+enum class IsMineResult
+{
+ NO = 0, //! Not ours
+ WATCH_ONLY = 1, //! Included in watch-only balance
+ SPENDABLE = 2, //! Included in all balances
+ INVALID = 3, //! Not spendable by anyone
+};
+
bool PermitsUncompressed(IsMineSigVersion sigversion)
{
return sigversion == IsMineSigVersion::TOP || sigversion == IsMineSigVersion::P2SH;
@@ -42,17 +55,13 @@ bool HaveKeys(const std::vector<valtype>& pubkeys, const CKeyStore& keystore)
return true;
}
-isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, bool& isInvalid, IsMineSigVersion sigversion)
+IsMineResult IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, IsMineSigVersion sigversion)
{
- isInvalid = false;
+ IsMineResult ret = IsMineResult::NO;
std::vector<valtype> vSolutions;
txnouttype whichType;
- if (!Solver(scriptPubKey, whichType, vSolutions)) {
- if (keystore.HaveWatchOnly(scriptPubKey))
- return ISMINE_WATCH_UNSOLVABLE;
- return ISMINE_NO;
- }
+ Solver(scriptPubKey, whichType, vSolutions);
CKeyID keyID;
switch (whichType)
@@ -64,23 +73,25 @@ isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, b
case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID();
if (!PermitsUncompressed(sigversion) && vSolutions[0].size() != 33) {
- isInvalid = true;
- return ISMINE_NO;
+ return IsMineResult::INVALID;
+ }
+ if (keystore.HaveKey(keyID)) {
+ ret = std::max(ret, IsMineResult::SPENDABLE);
}
- if (keystore.HaveKey(keyID))
- return ISMINE_SPENDABLE;
break;
case TX_WITNESS_V0_KEYHASH:
{
+ if (sigversion == IsMineSigVersion::WITNESS_V0) {
+ // P2WPKH inside P2WSH is invalid.
+ return IsMineResult::INVALID;
+ }
if (sigversion == IsMineSigVersion::TOP && !keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
// We do not support bare witness outputs unless the P2SH version of it would be
// acceptable as well. This protects against matching before segwit activates.
// This also applies to the P2WSH case.
break;
}
- isminetype ret = IsMineInner(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), isInvalid, IsMineSigVersion::WITNESS_V0);
- if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
- return ret;
+ ret = std::max(ret, IsMineInner(keystore, GetScriptForDestination(CKeyID(uint160(vSolutions[0]))), IsMineSigVersion::WITNESS_V0));
break;
}
case TX_PUBKEYHASH:
@@ -88,26 +99,32 @@ isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, b
if (!PermitsUncompressed(sigversion)) {
CPubKey pubkey;
if (keystore.GetPubKey(keyID, pubkey) && !pubkey.IsCompressed()) {
- isInvalid = true;
- return ISMINE_NO;
+ return IsMineResult::INVALID;
}
}
- if (keystore.HaveKey(keyID))
- return ISMINE_SPENDABLE;
+ if (keystore.HaveKey(keyID)) {
+ ret = std::max(ret, IsMineResult::SPENDABLE);
+ }
break;
case TX_SCRIPTHASH:
{
+ if (sigversion != IsMineSigVersion::TOP) {
+ // P2SH inside P2WSH or P2SH is invalid.
+ return IsMineResult::INVALID;
+ }
CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
CScript subscript;
if (keystore.GetCScript(scriptID, subscript)) {
- isminetype ret = IsMineInner(keystore, subscript, isInvalid, IsMineSigVersion::P2SH);
- if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
- return ret;
+ ret = std::max(ret, IsMineInner(keystore, subscript, IsMineSigVersion::P2SH));
}
break;
}
case TX_WITNESS_V0_SCRIPTHASH:
{
+ if (sigversion == IsMineSigVersion::WITNESS_V0) {
+ // P2WSH inside P2WSH is invalid.
+ return IsMineResult::INVALID;
+ }
if (sigversion == IsMineSigVersion::TOP && !keystore.HaveCScript(CScriptID(CScript() << OP_0 << vSolutions[0]))) {
break;
}
@@ -116,9 +133,7 @@ isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, b
CScriptID scriptID = CScriptID(hash);
CScript subscript;
if (keystore.GetCScript(scriptID, subscript)) {
- isminetype ret = IsMineInner(keystore, subscript, isInvalid, IsMineSigVersion::WITNESS_V0);
- if (ret == ISMINE_SPENDABLE || ret == ISMINE_WATCH_SOLVABLE || (ret == ISMINE_NO && isInvalid))
- return ret;
+ ret = std::max(ret, IsMineInner(keystore, subscript, IsMineSigVersion::WITNESS_V0));
}
break;
}
@@ -126,7 +141,9 @@ isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, b
case TX_MULTISIG:
{
// Never treat bare multisig outputs as ours (they can still be made watchonly-though)
- if (sigversion == IsMineSigVersion::TOP) break;
+ if (sigversion == IsMineSigVersion::TOP) {
+ break;
+ }
// Only consider transactions "mine" if we own ALL the
// keys involved. Multi-signature transactions that are
@@ -137,30 +154,39 @@ isminetype IsMineInner(const CKeyStore& keystore, const CScript& scriptPubKey, b
if (!PermitsUncompressed(sigversion)) {
for (size_t i = 0; i < keys.size(); i++) {
if (keys[i].size() != 33) {
- isInvalid = true;
- return ISMINE_NO;
+ return IsMineResult::INVALID;
}
}
}
- if (HaveKeys(keys, keystore))
- return ISMINE_SPENDABLE;
+ if (HaveKeys(keys, keystore)) {
+ ret = std::max(ret, IsMineResult::SPENDABLE);
+ }
break;
}
}
- if (keystore.HaveWatchOnly(scriptPubKey)) {
- // TODO: This could be optimized some by doing some work after the above solver
- SignatureData sigs;
- return ProduceSignature(keystore, DUMMY_SIGNATURE_CREATOR, scriptPubKey, sigs) ? ISMINE_WATCH_SOLVABLE : ISMINE_WATCH_UNSOLVABLE;
+ if (ret == IsMineResult::NO && keystore.HaveWatchOnly(scriptPubKey)) {
+ ret = std::max(ret, IsMineResult::WATCH_ONLY);
}
- return ISMINE_NO;
+ return ret;
}
} // namespace
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey, bool& isInvalid)
{
- return IsMineInner(keystore, scriptPubKey, isInvalid, IsMineSigVersion::TOP);
+ isInvalid = false;
+ switch (IsMineInner(keystore, scriptPubKey, IsMineSigVersion::TOP)) {
+ case IsMineResult::INVALID:
+ isInvalid = true;
+ case IsMineResult::NO:
+ return ISMINE_NO;
+ case IsMineResult::WATCH_ONLY:
+ return ISMINE_WATCH_ONLY;
+ case IsMineResult::SPENDABLE:
+ return ISMINE_SPENDABLE;
+ }
+ assert(false);
}
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey)
diff --git a/src/script/ismine.h b/src/script/ismine.h
index 8573bdfbd2..a15768aecb 100644
--- a/src/script/ismine.h
+++ b/src/script/ismine.h
@@ -17,12 +17,8 @@ class CScript;
enum isminetype
{
ISMINE_NO = 0,
- //! Indicates that we don't know how to create a scriptSig that would solve this if we were given the appropriate private keys
- ISMINE_WATCH_UNSOLVABLE = 1,
- //! Indicates that we know how to create a scriptSig that would solve this if we were given the appropriate private keys
- ISMINE_WATCH_SOLVABLE = 2,
- ISMINE_WATCH_ONLY = ISMINE_WATCH_SOLVABLE | ISMINE_WATCH_UNSOLVABLE,
- ISMINE_SPENDABLE = 4,
+ ISMINE_WATCH_ONLY = 1,
+ ISMINE_SPENDABLE = 2,
ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE
};
/** used for bitflags of isminetype */
diff --git a/src/script/script.cpp b/src/script/script.cpp
index 7f25d915a8..c84c7b8ec1 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -141,11 +141,6 @@ const char* GetOpName(opcodetype opcode)
case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE";
- // Note:
- // The template matching params OP_SMALLINTEGER/etc are defined in opcodetype enum
- // as kind of implementation hack, they are *NOT* real opcodes. If found in real
- // Script, just let the default: case deal with them.
-
default:
return "OP_UNKNOWN";
}
diff --git a/src/script/script.h b/src/script/script.h
index d8b7c06013..a4f377dd94 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -181,13 +181,6 @@ enum opcodetype
OP_NOP9 = 0xb8,
OP_NOP10 = 0xb9,
-
- // template matching params
- OP_SMALLINTEGER = 0xfa,
- OP_PUBKEYS = 0xfb,
- OP_PUBKEYHASH = 0xfd,
- OP_PUBKEY = 0xfe,
-
OP_INVALIDOPCODE = 0xff,
};
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index ac35f17f3e..6dbfbda029 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -14,9 +14,9 @@
typedef std::vector<unsigned char> valtype;
-TransactionSignatureCreator::TransactionSignatureCreator(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
+MutableTransactionSignatureCreator::MutableTransactionSignatureCreator(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
-bool TransactionSignatureCreator::CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const
+bool MutableTransactionSignatureCreator::CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const
{
CKey key;
if (!provider.GetKey(address, key))
@@ -199,22 +199,15 @@ void UpdateInput(CTxIn& input, const SignatureData& data)
input.scriptWitness = data.scriptWitness;
}
-void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const SignatureData& data)
-{
- assert(tx.vin.size() > nIn);
- UpdateInput(tx.vin[nIn], data);
-}
-
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType)
{
assert(nIn < txTo.vin.size());
- CTransaction txToConst(txTo);
- TransactionSignatureCreator creator(&txToConst, nIn, amount, nHashType);
+ MutableTransactionSignatureCreator creator(&txTo, nIn, amount, nHashType);
SignatureData sigdata;
bool ret = ProduceSignature(provider, creator, fromPubKey, sigdata);
- UpdateTransaction(txTo, nIn, sigdata);
+ UpdateInput(txTo.vin.at(nIn), sigdata);
return ret;
}
diff --git a/src/script/sign.h b/src/script/sign.h
index cf3651c1de..8ef0306bfe 100644
--- a/src/script/sign.h
+++ b/src/script/sign.h
@@ -37,26 +37,19 @@ public:
};
/** A signature creator for transactions. */
-class TransactionSignatureCreator : public BaseSignatureCreator {
- const CTransaction* txTo;
+class MutableTransactionSignatureCreator : public BaseSignatureCreator {
+ const CMutableTransaction* txTo;
unsigned int nIn;
int nHashType;
CAmount amount;
- const TransactionSignatureChecker checker;
+ const MutableTransactionSignatureChecker checker;
public:
- TransactionSignatureCreator(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL);
+ MutableTransactionSignatureCreator(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn = SIGHASH_ALL);
const BaseSignatureChecker& Checker() const override { return checker; }
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override;
};
-class MutableTransactionSignatureCreator : public TransactionSignatureCreator {
- CTransaction tx;
-
-public:
- MutableTransactionSignatureCreator(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : TransactionSignatureCreator(&tx, nInIn, amountIn, nHashTypeIn), tx(*txToIn) {}
-};
-
/** A signature creator that just produces 72-byte empty signatures. */
extern const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR;
@@ -80,7 +73,6 @@ SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignature
/** Extract signature data from a transaction, and insert it. */
SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn);
-void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const SignatureData& data);
void UpdateInput(CTxIn& input, const SignatureData& data);
/* Check whether we know how to sign for an output like this, assuming we
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index 76778112aa..d9269d6147 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -35,22 +35,54 @@ const char* GetTxnOutputType(txnouttype t)
return nullptr;
}
-bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet)
+static bool MatchPayToPubkey(const CScript& script, valtype& pubkey)
{
- // Templates
- static std::multimap<txnouttype, CScript> mTemplates;
- if (mTemplates.empty())
- {
- // Standard tx, sender provides pubkey, receiver adds signature
- mTemplates.insert(std::make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));
+ if (script.size() == CPubKey::PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) {
+ pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::PUBLIC_KEY_SIZE + 1);
+ return CPubKey::ValidSize(pubkey);
+ }
+ if (script.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) {
+ pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1);
+ return CPubKey::ValidSize(pubkey);
+ }
+ return false;
+}
- // Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
- mTemplates.insert(std::make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG));
+static bool MatchPayToPubkeyHash(const CScript& script, valtype& pubkeyhash)
+{
+ if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 && script[2] == 20 && script[23] == OP_EQUALVERIFY && script[24] == OP_CHECKSIG) {
+ pubkeyhash = valtype(script.begin () + 3, script.begin() + 23);
+ return true;
+ }
+ return false;
+}
+
+/** Test for "small positive integer" script opcodes - OP_1 through OP_16. */
+static constexpr bool IsSmallInteger(opcodetype opcode)
+{
+ return opcode >= OP_1 && opcode <= OP_16;
+}
- // Sender provides N pubkeys, receivers provides M signatures
- mTemplates.insert(std::make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));
+static bool MatchMultisig(const CScript& script, unsigned int& required, std::vector<valtype>& pubkeys)
+{
+ opcodetype opcode;
+ valtype data;
+ CScript::const_iterator it = script.begin();
+ if (script.size() < 1 || script.back() != OP_CHECKMULTISIG) return false;
+
+ if (!script.GetOp(it, opcode, data) || !IsSmallInteger(opcode)) return false;
+ required = CScript::DecodeOP_N(opcode);
+ while (script.GetOp(it, opcode, data) && CPubKey::ValidSize(data)) {
+ pubkeys.emplace_back(std::move(data));
}
+ if (!IsSmallInteger(opcode)) return false;
+ unsigned int keys = CScript::DecodeOP_N(opcode);
+ if (pubkeys.size() != keys || keys < required) return false;
+ return (it + 1 == script.end());
+}
+bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet)
+{
vSolutionsRet.clear();
// Shortcut for pay-to-script-hash, which are more constrained than the other types:
@@ -82,6 +114,7 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v
vSolutionsRet.push_back(std::move(witnessprogram));
return true;
}
+ typeRet = TX_NONSTANDARD;
return false;
}
@@ -95,84 +128,27 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::v
return true;
}
- // Scan templates
- const CScript& script1 = scriptPubKey;
- for (const std::pair<txnouttype, CScript>& tplate : mTemplates)
- {
- const CScript& script2 = tplate.second;
- vSolutionsRet.clear();
+ std::vector<unsigned char> data;
+ if (MatchPayToPubkey(scriptPubKey, data)) {
+ typeRet = TX_PUBKEY;
+ vSolutionsRet.push_back(std::move(data));
+ return true;
+ }
- opcodetype opcode1, opcode2;
- std::vector<unsigned char> vch1, vch2;
+ if (MatchPayToPubkeyHash(scriptPubKey, data)) {
+ typeRet = TX_PUBKEYHASH;
+ vSolutionsRet.push_back(std::move(data));
+ return true;
+ }
- // Compare
- CScript::const_iterator pc1 = script1.begin();
- CScript::const_iterator pc2 = script2.begin();
- while (true)
- {
- if (pc1 == script1.end() && pc2 == script2.end())
- {
- // Found a match
- typeRet = tplate.first;
- if (typeRet == TX_MULTISIG)
- {
- // Additional checks for TX_MULTISIG:
- unsigned char m = vSolutionsRet.front()[0];
- unsigned char n = vSolutionsRet.back()[0];
- if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n)
- return false;
- }
- return true;
- }
- if (!script1.GetOp(pc1, opcode1, vch1))
- break;
- if (!script2.GetOp(pc2, opcode2, vch2))
- break;
-
- // Template matching opcodes:
- if (opcode2 == OP_PUBKEYS)
- {
- while (CPubKey::ValidSize(vch1))
- {
- vSolutionsRet.push_back(vch1);
- if (!script1.GetOp(pc1, opcode1, vch1))
- break;
- }
- if (!script2.GetOp(pc2, opcode2, vch2))
- break;
- // Normal situation is to fall through
- // to other if/else statements
- }
-
- if (opcode2 == OP_PUBKEY)
- {
- if (!CPubKey::ValidSize(vch1))
- break;
- vSolutionsRet.push_back(vch1);
- }
- else if (opcode2 == OP_PUBKEYHASH)
- {
- if (vch1.size() != sizeof(uint160))
- break;
- vSolutionsRet.push_back(vch1);
- }
- else if (opcode2 == OP_SMALLINTEGER)
- { // Single-byte small integer pushed onto vSolutions
- if (opcode1 == OP_0 ||
- (opcode1 >= OP_1 && opcode1 <= OP_16))
- {
- char n = (char)CScript::DecodeOP_N(opcode1);
- vSolutionsRet.push_back(valtype(1, n));
- }
- else
- break;
- }
- else if (opcode1 != opcode2 || vch1 != vch2)
- {
- // Others must match exactly
- break;
- }
- }
+ unsigned int required;
+ std::vector<std::vector<unsigned char>> keys;
+ if (MatchMultisig(scriptPubKey, required, keys)) {
+ typeRet = TX_MULTISIG;
+ vSolutionsRet.push_back({static_cast<unsigned char>(required)}); // safe as required is in range 1..16
+ vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end());
+ vSolutionsRet.push_back({static_cast<unsigned char>(keys.size())}); // safe as size is in range 1..16
+ return true;
}
vSolutionsRet.clear();
diff --git a/src/sync.cpp b/src/sync.cpp
index 1f27aeb40b..28a4e37e68 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -75,7 +75,7 @@ struct LockData {
std::mutex dd_mutex;
} static lockdata;
-static thread_local std::unique_ptr<LockStack> lockstack;
+static thread_local LockStack g_lockstack;
static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
{
@@ -105,21 +105,18 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch,
static void push_lock(void* c, const CLockLocation& locklocation)
{
- if (!lockstack)
- lockstack.reset(new LockStack);
-
std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
- lockstack->push_back(std::make_pair(c, locklocation));
+ g_lockstack.push_back(std::make_pair(c, locklocation));
- for (const std::pair<void*, CLockLocation> & i : (*lockstack)) {
+ for (const std::pair<void*, CLockLocation>& i : g_lockstack) {
if (i.first == c)
break;
std::pair<void*, void*> p1 = std::make_pair(i.first, c);
if (lockdata.lockorders.count(p1))
continue;
- lockdata.lockorders[p1] = (*lockstack);
+ lockdata.lockorders[p1] = g_lockstack;
std::pair<void*, void*> p2 = std::make_pair(c, i.first);
lockdata.invlockorders.insert(p2);
@@ -130,7 +127,7 @@ static void push_lock(void* c, const CLockLocation& locklocation)
static void pop_lock()
{
- (*lockstack).pop_back();
+ g_lockstack.pop_back();
}
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
@@ -146,14 +143,14 @@ void LeaveCritical()
std::string LocksHeld()
{
std::string result;
- for (const std::pair<void*, CLockLocation> & i : *lockstack)
+ for (const std::pair<void*, CLockLocation>& i : g_lockstack)
result += i.second.ToString() + std::string("\n");
return result;
}
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
{
- for (const std::pair<void*, CLockLocation> & i : *lockstack)
+ for (const std::pair<void*, CLockLocation>& i : g_lockstack)
if (i.first == cs)
return;
fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
@@ -162,7 +159,7 @@ void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine,
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
{
- for (const std::pair<void*, CLockLocation>& i : *lockstack) {
+ for (const std::pair<void*, CLockLocation>& i : g_lockstack) {
if (i.first == cs) {
fprintf(stderr, "Assertion failed: lock %s held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
abort();
diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp
index 51308847f6..2c625c089c 100644
--- a/src/test/bip32_tests.cpp
+++ b/src/test/bip32_tests.cpp
@@ -91,7 +91,7 @@ static void RunTest(const TestVector &test) {
std::vector<unsigned char> seed = ParseHex(test.strHexMaster);
CExtKey key;
CExtPubKey pubkey;
- key.SetMaster(seed.data(), seed.size());
+ key.SetSeed(seed.data(), seed.size());
pubkey = key.Neuter();
for (const TestDerivation &derive : test.vDerive) {
unsigned char data[74];
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
index 276d5b80ee..b792ff8b45 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -312,7 +312,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
if (InsecureRandRange(10) == 0 && coinbase_coins.size()) {
auto utxod = FindRandomFrom(coinbase_coins);
// Reuse the exact same coinbase
- tx = std::get<0>(utxod->second);
+ tx = CMutableTransaction{std::get<0>(utxod->second)};
// shouldn't be available for reconnection if it's been duplicated
disconnected_coins.erase(utxod->first);
@@ -331,7 +331,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
// 1/20 times reconnect a previously disconnected tx
if (randiter % 20 == 2 && disconnected_coins.size()) {
auto utxod = FindRandomFrom(disconnected_coins);
- tx = std::get<0>(utxod->second);
+ tx = CMutableTransaction{std::get<0>(utxod->second)};
prevout = tx.vin[0].prevout;
if (!CTransaction(tx).IsCoinBase() && !utxoset.count(prevout)) {
disconnected_coins.erase(utxod->first);
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
index 518cb849bb..d701f3bc4e 100644
--- a/src/test/crypto_tests.cpp
+++ b/src/test/crypto_tests.cpp
@@ -546,4 +546,20 @@ BOOST_AUTO_TEST_CASE(countbits_tests)
}
}
+BOOST_AUTO_TEST_CASE(sha256d64)
+{
+ for (int i = 0; i <= 32; ++i) {
+ unsigned char in[64 * 32];
+ unsigned char out1[32 * 32], out2[32 * 32];
+ for (int j = 0; j < 64 * i; ++j) {
+ in[j] = InsecureRandBits(8);
+ }
+ for (int j = 0; j < i; ++j) {
+ CHash256().Write(in + 64 * j, 64).Finalize(out1 + 32 * j);
+ }
+ SHA256D64(out2, in, i);
+ BOOST_CHECK(memcmp(out1, out2, 32 * i) == 0);
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp
index cd603b7f58..c065e25676 100644
--- a/src/test/getarg_tests.cpp
+++ b/src/test/getarg_tests.cpp
@@ -27,11 +27,21 @@ static void ResetArgs(const std::string& strArg)
for (std::string& s : vecArg)
vecChar.push_back(s.c_str());
- gArgs.ParseParameters(vecChar.size(), vecChar.data());
+ std::string error;
+ gArgs.ParseParameters(vecChar.size(), vecChar.data(), error);
+}
+
+static void SetupArgs(const std::vector<std::string>& args)
+{
+ gArgs.ClearArgs();
+ for (const std::string& arg : args) {
+ gArgs.AddArg(arg, "", false, OptionsCategory::OPTIONS);
+ }
}
BOOST_AUTO_TEST_CASE(boolarg)
{
+ SetupArgs({"-foo"});
ResetArgs("-foo");
BOOST_CHECK(gArgs.GetBoolArg("-foo", false));
BOOST_CHECK(gArgs.GetBoolArg("-foo", true));
@@ -84,6 +94,7 @@ BOOST_AUTO_TEST_CASE(boolarg)
BOOST_AUTO_TEST_CASE(stringarg)
{
+ SetupArgs({"-foo", "-bar"});
ResetArgs("");
BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", ""), "");
BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", "eleven"), "eleven");
@@ -108,6 +119,7 @@ BOOST_AUTO_TEST_CASE(stringarg)
BOOST_AUTO_TEST_CASE(intarg)
{
+ SetupArgs({"-foo", "-bar"});
ResetArgs("");
BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", 11), 11);
BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", 0), 0);
@@ -127,6 +139,7 @@ BOOST_AUTO_TEST_CASE(intarg)
BOOST_AUTO_TEST_CASE(doubledash)
{
+ SetupArgs({"-foo", "-bar"});
ResetArgs("--foo");
BOOST_CHECK_EQUAL(gArgs.GetBoolArg("-foo", false), true);
@@ -137,6 +150,7 @@ BOOST_AUTO_TEST_CASE(doubledash)
BOOST_AUTO_TEST_CASE(boolargno)
{
+ SetupArgs({"-foo", "-bar"});
ResetArgs("-nofoo");
BOOST_CHECK(!gArgs.GetBoolArg("-foo", true));
BOOST_CHECK(!gArgs.GetBoolArg("-foo", false));
diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp
index 72a2672352..259e45dacf 100644
--- a/src/test/merkle_tests.cpp
+++ b/src/test/merkle_tests.cpp
@@ -9,6 +9,123 @@
BOOST_FIXTURE_TEST_SUITE(merkle_tests, TestingSetup)
+static uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector<uint256>& vMerkleBranch, uint32_t nIndex) {
+ uint256 hash = leaf;
+ for (std::vector<uint256>::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;
+}
+
+/* This implements a constant-space merkle root/path calculator, limited to 2^32 leaves. */
+static void MerkleComputation(const std::vector<uint256>& leaves, uint256* proot, bool* pmutated, uint32_t branchpos, std::vector<uint256>* 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;
+}
+
+static std::vector<uint256> ComputeMerkleBranch(const std::vector<uint256>& leaves, uint32_t position) {
+ std::vector<uint256> ret;
+ MerkleComputation(leaves, nullptr, nullptr, position, &ret);
+ return ret;
+}
+
+static std::vector<uint256> BlockMerkleBranch(const CBlock& block, uint32_t position)
+{
+ std::vector<uint256> 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);
+}
+
// Older version of the merkle root computation code, for comparison.
static uint256 BlockBuildMerkleTree(const CBlock& block, bool* fMutated, std::vector<uint256>& vMerkleTree)
{
diff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp
index ff0bf6c66d..7ab0978228 100644
--- a/src/test/script_standard_tests.cpp
+++ b/src/test/script_standard_tests.cpp
@@ -726,6 +726,32 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
BOOST_CHECK(!isInvalid);
}
+ // witness unspendable
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(keys[0]);
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_0 << ToByteVector(ParseHex("aabb"));
+
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+ }
+
+ // witness unknown
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(keys[0]);
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_16 << ToByteVector(ParseHex("aabb"));
+
+ result = IsMine(keystore, scriptPubKey, isInvalid);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ BOOST_CHECK(!isInvalid);
+ }
+
// Nonstandard
{
CBasicKeyStore keystore;
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 33b31565a6..c05e60996d 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -137,7 +137,7 @@ CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int n
return txCredit;
}
-CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CMutableTransaction& txCredit)
+CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit)
{
CMutableTransaction txSpend;
txSpend.nVersion = 1;
@@ -163,7 +163,7 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScript
flags |= SCRIPT_VERIFY_WITNESS;
}
ScriptError err;
- CMutableTransaction txCredit = BuildCreditingTransaction(scriptPubKey, nValue);
+ const CTransaction txCredit{BuildCreditingTransaction(scriptPubKey, nValue)};
CMutableTransaction tx = BuildSpendingTransaction(scriptSig, scriptWitness, txCredit);
CMutableTransaction tx2 = tx;
BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message);
@@ -1073,7 +1073,7 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
CScript scriptPubKey12;
scriptPubKey12 << OP_1 << ToByteVector(key1.GetPubKey()) << ToByteVector(key2.GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
- CMutableTransaction txFrom12 = BuildCreditingTransaction(scriptPubKey12);
+ const CTransaction txFrom12{BuildCreditingTransaction(scriptPubKey12)};
CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom12);
CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12);
@@ -1104,7 +1104,7 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
CScript scriptPubKey23;
scriptPubKey23 << OP_2 << ToByteVector(key1.GetPubKey()) << ToByteVector(key2.GetPubKey()) << ToByteVector(key3.GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
- CMutableTransaction txFrom23 = BuildCreditingTransaction(scriptPubKey23);
+ const CTransaction txFrom23{BuildCreditingTransaction(scriptPubKey23)};
CMutableTransaction txTo23 = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom23);
std::vector<CKey> keys;
diff --git a/src/test/torcontrol_tests.cpp b/src/test/torcontrol_tests.cpp
index 8bd5ce1222..c7ceb2f1e9 100644
--- a/src/test/torcontrol_tests.cpp
+++ b/src/test/torcontrol_tests.cpp
@@ -3,10 +3,18 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
#include <test/test_bitcoin.h>
-#include <torcontrol.cpp>
+#include <torcontrol.h>
#include <boost/test/unit_test.hpp>
+#include <map>
+#include <string>
+#include <utility>
+
+
+std::pair<std::string, std::string> SplitTorReplyLine(const std::string& s);
+std::map<std::string, std::string> ParseTorReplyMapping(const std::string& s);
+
BOOST_FIXTURE_TEST_SUITE(torcontrol_tests, BasicTestingSetup)
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index cc72e96eb1..65c5b8ea1d 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -629,7 +629,7 @@ BOOST_AUTO_TEST_CASE(test_witness)
CreateCreditAndSpend(keystore2, scriptMulti, output2, input2, false);
CheckWithFlag(output2, input2, 0, false);
BOOST_CHECK(*output1 == *output2);
- UpdateTransaction(input1, 0, CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
+ UpdateInput(input1.vin[0], CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
// P2SH 2-of-2 multisig
@@ -640,7 +640,7 @@ BOOST_AUTO_TEST_CASE(test_witness)
CheckWithFlag(output2, input2, 0, true);
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, false);
BOOST_CHECK(*output1 == *output2);
- UpdateTransaction(input1, 0, CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
+ UpdateInput(input1.vin[0], CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
@@ -652,7 +652,7 @@ BOOST_AUTO_TEST_CASE(test_witness)
CheckWithFlag(output2, input2, 0, true);
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
BOOST_CHECK(*output1 == *output2);
- UpdateTransaction(input1, 0, CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
+ UpdateInput(input1.vin[0], CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true);
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
@@ -664,7 +664,7 @@ BOOST_AUTO_TEST_CASE(test_witness)
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, true);
CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
BOOST_CHECK(*output1 == *output2);
- UpdateTransaction(input1, 0, CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
+ UpdateInput(input1.vin[0], CombineSignatures(output1->vout[0].scriptPubKey, MutableTransactionSignatureChecker(&input1, 0, output1->vout[0].nValue), DataFromTransaction(input1, 0), DataFromTransaction(input2, 0)));
CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true);
CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
}
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index eb23ba5ad2..2b00064cd0 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -24,7 +24,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
BOOST_AUTO_TEST_SUITE(tx_validationcache_tests)
static bool
-ToMemPool(CMutableTransaction& tx)
+ToMemPool(const CMutableTransaction& tx)
{
LOCK(cs_main);
@@ -315,7 +315,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
// Sign
SignatureData sigdata;
ProduceSignature(keystore, MutableTransactionSignatureCreator(&valid_with_witness_tx, 0, 11*CENT, SIGHASH_ALL), spend_tx.vout[1].scriptPubKey, sigdata);
- UpdateTransaction(valid_with_witness_tx, 0, sigdata);
+ UpdateInput(valid_with_witness_tx.vin[0], sigdata);
// This should be valid under all script flags.
ValidateCheckInputsForAllFlags(valid_with_witness_tx, 0, true);
@@ -343,7 +343,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
for (int i=0; i<2; ++i) {
SignatureData sigdata;
ProduceSignature(keystore, MutableTransactionSignatureCreator(&tx, i, 11*CENT, SIGHASH_ALL), spend_tx.vout[i].scriptPubKey, sigdata);
- UpdateTransaction(tx, i, sigdata);
+ UpdateInput(tx.vin[i], sigdata);
}
// This should be valid under all script flags
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 2af6d9e0f3..611ccc9b77 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -186,27 +186,37 @@ struct TestArgsManager : public ArgsManager
LOCK(cs_args);
m_config_args.clear();
}
- ReadConfigStream(streamConfig);
+ std::string error;
+ ReadConfigStream(streamConfig, error);
}
void SetNetworkOnlyArg(const std::string arg)
{
LOCK(cs_args);
m_network_only_args.insert(arg);
}
+ void SetupArgs(int argv, const char* args[])
+ {
+ for (int i = 0; i < argv; ++i) {
+ AddArg(args[i], "", false, OptionsCategory::OPTIONS);
+ }
+ }
};
BOOST_AUTO_TEST_CASE(util_ParseParameters)
{
TestArgsManager testArgs;
+ const char* avail_args[] = {"-a", "-b", "-ccc", "-d"};
const char *argv_test[] = {"-ignored", "-a", "-b", "-ccc=argument", "-ccc=multiple", "f", "-d=e"};
- testArgs.ParseParameters(0, (char**)argv_test);
+ std::string error;
+ testArgs.SetupArgs(4, avail_args);
+ testArgs.ParseParameters(0, (char**)argv_test, error);
BOOST_CHECK(testArgs.GetOverrideArgs().empty() && testArgs.GetConfigArgs().empty());
- testArgs.ParseParameters(1, (char**)argv_test);
+ testArgs.ParseParameters(1, (char**)argv_test, error);
BOOST_CHECK(testArgs.GetOverrideArgs().empty() && testArgs.GetConfigArgs().empty());
- testArgs.ParseParameters(7, (char**)argv_test);
+ testArgs.ParseParameters(7, (char**)argv_test, error);
// expectation: -ignored is ignored (program name argument),
// -a, -b and -ccc end up in map, -d ignored because it is after
// a non-option argument (non-GNU option parsing)
@@ -227,9 +237,12 @@ BOOST_AUTO_TEST_CASE(util_ParseParameters)
BOOST_AUTO_TEST_CASE(util_GetBoolArg)
{
TestArgsManager testArgs;
+ const char* avail_args[] = {"-a", "-b", "-c", "-d", "-e", "-f"};
const char *argv_test[] = {
"ignored", "-a", "-nob", "-c=0", "-d=1", "-e=false", "-f=true"};
- testArgs.ParseParameters(7, (char**)argv_test);
+ std::string error;
+ testArgs.SetupArgs(6, avail_args);
+ testArgs.ParseParameters(7, (char**)argv_test, error);
// Each letter should be set.
for (char opt : "abcdef")
@@ -261,8 +274,11 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases)
TestArgsManager testArgs;
// Params test
+ const char* avail_args[] = {"-foo", "-bar"};
const char *argv_test[] = {"ignored", "-nofoo", "-foo", "-nobar=0"};
- testArgs.ParseParameters(4, (char**)argv_test);
+ testArgs.SetupArgs(2, avail_args);
+ std::string error;
+ testArgs.ParseParameters(4, (char**)argv_test, error);
// This was passed twice, second one overrides the negative setting.
BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
@@ -274,7 +290,7 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases)
// Config test
const char *conf_test = "nofoo=1\nfoo=1\nnobar=0\n";
- testArgs.ParseParameters(1, (char**)argv_test);
+ testArgs.ParseParameters(1, (char**)argv_test, error);
testArgs.ReadConfigString(conf_test);
// This was passed twice, second one overrides the negative setting,
@@ -289,7 +305,7 @@ BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases)
// Combined test
const char *combo_test_args[] = {"ignored", "-nofoo", "-bar"};
const char *combo_test_conf = "foo=1\nnobar=1\n";
- testArgs.ParseParameters(3, (char**)combo_test_args);
+ testArgs.ParseParameters(3, (char**)combo_test_args, error);
testArgs.ReadConfigString(combo_test_conf);
// Command line overrides, but doesn't erase old setting
@@ -329,6 +345,8 @@ BOOST_AUTO_TEST_CASE(util_ReadConfigStream)
"iii=2\n";
TestArgsManager test_args;
+ const char* avail_args[] = {"-a", "-b", "-ccc", "-d", "-e", "-fff", "-ggg", "-h", "-i", "-iii"};
+ test_args.SetupArgs(10, avail_args);
test_args.ReadConfigString(str_config);
// expectation: a, b, ccc, d, fff, ggg, h, i end up in map
@@ -526,6 +544,8 @@ BOOST_AUTO_TEST_CASE(util_GetArg)
BOOST_AUTO_TEST_CASE(util_GetChainName)
{
TestArgsManager test_args;
+ const char* avail_args[] = {"-testnet", "-regtest"};
+ test_args.SetupArgs(2, avail_args);
const char* argv_testnet[] = {"cmd", "-testnet"};
const char* argv_regtest[] = {"cmd", "-regtest"};
@@ -535,39 +555,40 @@ BOOST_AUTO_TEST_CASE(util_GetChainName)
// equivalent to "-testnet"
// regtest in testnet section is ignored
const char* testnetconf = "testnet=1\nregtest=0\n[test]\nregtest=1";
+ std::string error;
- test_args.ParseParameters(0, (char**)argv_testnet);
+ test_args.ParseParameters(0, (char**)argv_testnet, error);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "main");
- test_args.ParseParameters(2, (char**)argv_testnet);
+ test_args.ParseParameters(2, (char**)argv_testnet, error);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(2, (char**)argv_regtest);
+ test_args.ParseParameters(2, (char**)argv_regtest, error);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "regtest");
- test_args.ParseParameters(3, (char**)argv_test_no_reg);
+ test_args.ParseParameters(3, (char**)argv_test_no_reg, error);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(3, (char**)argv_both);
+ test_args.ParseParameters(3, (char**)argv_both, error);
BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
- test_args.ParseParameters(0, (char**)argv_testnet);
+ test_args.ParseParameters(0, (char**)argv_testnet, error);
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(2, (char**)argv_testnet);
+ test_args.ParseParameters(2, (char**)argv_testnet, error);
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(2, (char**)argv_regtest);
+ test_args.ParseParameters(2, (char**)argv_regtest, error);
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
- test_args.ParseParameters(3, (char**)argv_test_no_reg);
+ test_args.ParseParameters(3, (char**)argv_test_no_reg, error);
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(3, (char**)argv_both);
+ test_args.ParseParameters(3, (char**)argv_both, error);
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
@@ -575,23 +596,23 @@ BOOST_AUTO_TEST_CASE(util_GetChainName)
// [test] regtest=1 potentially relevant) doesn't break things
test_args.SelectConfigNetwork("test");
- test_args.ParseParameters(0, (char**)argv_testnet);
+ test_args.ParseParameters(0, (char**)argv_testnet, error);
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(2, (char**)argv_testnet);
+ test_args.ParseParameters(2, (char**)argv_testnet, error);
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(2, (char**)argv_regtest);
+ test_args.ParseParameters(2, (char**)argv_regtest, error);
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
- test_args.ParseParameters(2, (char**)argv_test_no_reg);
+ test_args.ParseParameters(2, (char**)argv_test_no_reg, error);
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
- test_args.ParseParameters(3, (char**)argv_both);
+ test_args.ParseParameters(3, (char**)argv_both, error);
test_args.ReadConfigString(testnetconf);
BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
}
diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp
index f835570168..37c4f79133 100644
--- a/src/test/validation_block_tests.cpp
+++ b/src/test/validation_block_tests.cpp
@@ -25,12 +25,12 @@ struct TestSubscriber : public CValidationInterface {
TestSubscriber(uint256 tip) : m_expected_tip(tip) {}
- void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload)
+ void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) override
{
BOOST_CHECK_EQUAL(m_expected_tip, pindexNew->GetBlockHash());
}
- void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex, const std::vector<CTransactionRef>& txnConflicted)
+ void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex, const std::vector<CTransactionRef>& txnConflicted) override
{
BOOST_CHECK_EQUAL(m_expected_tip, block->hashPrevBlock);
BOOST_CHECK_EQUAL(m_expected_tip, pindex->pprev->GetBlockHash());
@@ -38,7 +38,7 @@ struct TestSubscriber : public CValidationInterface {
m_expected_tip = block->GetHash();
}
- void BlockDisconnected(const std::shared_ptr<const CBlock>& block)
+ void BlockDisconnected(const std::shared_ptr<const CBlock>& block) override
{
BOOST_CHECK_EQUAL(m_expected_tip, block->GetHash());
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index 717d1cf7e5..1791bfd7f7 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -251,7 +251,7 @@ bool TorControlConnection::Command(const std::string &cmd, const ReplyHandlerCB&
* Grammar is implicitly defined in https://spec.torproject.org/control-spec by
* the server reply formats for PROTOCOLINFO (S3.21) and AUTHCHALLENGE (S3.24).
*/
-static std::pair<std::string,std::string> SplitTorReplyLine(const std::string &s)
+std::pair<std::string,std::string> SplitTorReplyLine(const std::string &s)
{
size_t ptr=0;
std::string type;
@@ -270,7 +270,7 @@ static std::pair<std::string,std::string> SplitTorReplyLine(const std::string &s
* the server reply formats for PROTOCOLINFO (S3.21), AUTHCHALLENGE (S3.24),
* and ADD_ONION (S3.27). See also sections 2.1 and 2.3.
*/
-static std::map<std::string,std::string> ParseTorReplyMapping(const std::string &s)
+std::map<std::string,std::string> ParseTorReplyMapping(const std::string &s)
{
std::map<std::string,std::string> mapping;
size_t ptr=0;
@@ -773,4 +773,3 @@ void StopTorControl()
gBase = nullptr;
}
}
-
diff --git a/src/ui_interface.h b/src/ui_interface.h
index 33099b4e73..3add369df0 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -6,6 +6,7 @@
#ifndef BITCOIN_UI_INTERFACE_H
#define BITCOIN_UI_INTERFACE_H
+#include <memory>
#include <stdint.h>
#include <string>
@@ -92,7 +93,7 @@ public:
boost::signals2::signal<void ()> NotifyAlertChanged;
/** A wallet has been loaded. */
- boost::signals2::signal<void (CWallet* wallet)> LoadWallet;
+ boost::signals2::signal<void (std::shared_ptr<CWallet> wallet)> LoadWallet;
/**
* Show progress e.g. for verifychain.
diff --git a/src/util.cpp b/src/util.cpp
index 6a2b2c1ed4..48d64e3eec 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -412,7 +412,7 @@ void ArgsManager::SelectConfigNetwork(const std::string& network)
m_network = network;
}
-void ArgsManager::ParseParameters(int argc, const char* const argv[])
+bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::string& error)
{
LOCK(cs_args);
m_override_args.clear();
@@ -444,6 +444,14 @@ void ArgsManager::ParseParameters(int argc, const char* const argv[])
} else {
m_override_args[key].push_back(val);
}
+
+ // Check that the arg is known
+ if (!(IsSwitchChar(key[0]) && key.size() == 1)) {
+ if (!IsArgKnown(key, error)) {
+ error = strprintf("Invalid parameter %s", key.c_str());
+ return false;
+ }
+ }
}
// we do not allow -includeconf from command line, so we clear it here
@@ -451,11 +459,28 @@ void ArgsManager::ParseParameters(int argc, const char* const argv[])
if (it != m_override_args.end()) {
if (it->second.size() > 0) {
for (const auto& ic : it->second) {
- fprintf(stderr, "warning: -includeconf cannot be used from commandline; ignoring -includeconf=%s\n", ic.c_str());
+ error += "-includeconf cannot be used from commandline; -includeconf=" + ic + "\n";
}
- m_override_args.erase(it);
+ return false;
}
}
+ return true;
+}
+
+bool ArgsManager::IsArgKnown(const std::string& key, std::string& error)
+{
+ size_t option_index = key.find('.');
+ std::string arg_no_net;
+ if (option_index == std::string::npos) {
+ arg_no_net = key;
+ } else {
+ arg_no_net = std::string("-") + key.substr(option_index + 1, std::string::npos);
+ }
+
+ for (const auto& arg_map : m_available_args) {
+ if (arg_map.second.count(arg_no_net)) return true;
+ }
+ return false;
}
std::vector<std::string> ArgsManager::GetArgs(const std::string& strArg) const
@@ -549,48 +574,80 @@ void ArgsManager::ForceSetArg(const std::string& strArg, const std::string& strV
void ArgsManager::AddArg(const std::string& name, const std::string& help, const bool debug_only, const OptionsCategory& cat)
{
- std::pair<OptionsCategory, std::string> key(cat, name);
- assert(m_available_args.count(key) == 0);
- m_available_args.emplace(key, std::pair<std::string, bool>(help, debug_only));
+ // Split arg name from its help param
+ size_t eq_index = name.find('=');
+ if (eq_index == std::string::npos) {
+ eq_index = name.size();
+ }
+
+ std::map<std::string, Arg>& arg_map = m_available_args[cat];
+ auto ret = arg_map.emplace(name.substr(0, eq_index), Arg(name.substr(eq_index, name.size() - eq_index), help, debug_only));
+ assert(ret.second); // Make sure an insertion actually happened
}
std::string ArgsManager::GetHelpMessage()
{
const bool show_debug = gArgs.GetBoolArg("-help-debug", false);
- std::string usage = HelpMessageGroup(_("Options:"));
-
- OptionsCategory last_cat = OptionsCategory::OPTIONS;
- for (auto& arg : m_available_args) {
- if (arg.first.first != last_cat) {
- last_cat = arg.first.first;
- if (last_cat == OptionsCategory::CONNECTION)
- usage += HelpMessageGroup(_("Connection options:"));
- else if (last_cat == OptionsCategory::ZMQ)
- usage += HelpMessageGroup(_("ZeroMQ notification options:"));
- else if (last_cat == OptionsCategory::DEBUG_TEST)
- usage += HelpMessageGroup(_("Debugging/Testing options:"));
- else if (last_cat == OptionsCategory::NODE_RELAY)
- usage += HelpMessageGroup(_("Node relay options:"));
- else if (last_cat == OptionsCategory::BLOCK_CREATION)
- usage += HelpMessageGroup(_("Block creation options:"));
- else if (last_cat == OptionsCategory::RPC)
- usage += HelpMessageGroup(_("RPC server options:"));
- else if (last_cat == OptionsCategory::WALLET)
- usage += HelpMessageGroup(_("Wallet options:"));
- else if (last_cat == OptionsCategory::WALLET_DEBUG_TEST && show_debug)
- usage += HelpMessageGroup(_("Wallet debugging/testing options:"));
- else if (last_cat == OptionsCategory::CHAINPARAMS)
- usage += HelpMessageGroup(_("Chain selection options:"));
- else if (last_cat == OptionsCategory::GUI)
- usage += HelpMessageGroup(_("UI Options:"));
- else if (last_cat == OptionsCategory::COMMANDS)
- usage += HelpMessageGroup(_("Commands:"));
- else if (last_cat == OptionsCategory::REGISTER_COMMANDS)
- usage += HelpMessageGroup(_("Register Commands:"));
+ std::string usage = "";
+ for (const auto& arg_map : m_available_args) {
+ switch(arg_map.first) {
+ case OptionsCategory::OPTIONS:
+ usage += HelpMessageGroup("Options:");
+ break;
+ case OptionsCategory::CONNECTION:
+ usage += HelpMessageGroup("Connection options:");
+ break;
+ case OptionsCategory::ZMQ:
+ usage += HelpMessageGroup("ZeroMQ notification options:");
+ break;
+ case OptionsCategory::DEBUG_TEST:
+ usage += HelpMessageGroup("Debugging/Testing options:");
+ break;
+ case OptionsCategory::NODE_RELAY:
+ usage += HelpMessageGroup("Node relay options:");
+ break;
+ case OptionsCategory::BLOCK_CREATION:
+ usage += HelpMessageGroup("Block creation options:");
+ break;
+ case OptionsCategory::RPC:
+ usage += HelpMessageGroup("RPC server options:");
+ break;
+ case OptionsCategory::WALLET:
+ usage += HelpMessageGroup("Wallet options:");
+ break;
+ case OptionsCategory::WALLET_DEBUG_TEST:
+ if (show_debug) usage += HelpMessageGroup("Wallet debugging/testing options:");
+ break;
+ case OptionsCategory::CHAINPARAMS:
+ usage += HelpMessageGroup("Chain selection options:");
+ break;
+ case OptionsCategory::GUI:
+ usage += HelpMessageGroup("UI Options:");
+ break;
+ case OptionsCategory::COMMANDS:
+ usage += HelpMessageGroup("Commands:");
+ break;
+ case OptionsCategory::REGISTER_COMMANDS:
+ usage += HelpMessageGroup("Register Commands:");
+ break;
+ default:
+ break;
}
- if (show_debug || !arg.second.second) {
- usage += HelpMessageOpt(arg.first.second, arg.second.first);
+
+ // When we get to the hidden options, stop
+ if (arg_map.first == OptionsCategory::HIDDEN) break;
+
+ for (const auto& arg : arg_map.second) {
+ if (show_debug || !arg.second.m_debug_only) {
+ std::string name;
+ if (arg.second.m_help_param.empty()) {
+ name = arg.first;
+ } else {
+ name = arg.first + arg.second.m_help_param;
+ }
+ usage += HelpMessageOpt(name, arg.second.m_help_text);
+ }
}
}
return usage;
@@ -747,7 +804,7 @@ fs::path GetConfigFile(const std::string& confPath)
return AbsPathForConfigVal(fs::path(confPath), false);
}
-void ArgsManager::ReadConfigStream(std::istream& stream)
+bool ArgsManager::ReadConfigStream(std::istream& stream, std::string& error, bool ignore_invalid_keys)
{
LOCK(cs_args);
@@ -758,15 +815,23 @@ void ArgsManager::ReadConfigStream(std::istream& stream)
{
std::string strKey = std::string("-") + it->string_key;
std::string strValue = it->value[0];
+
if (InterpretNegatedOption(strKey, strValue)) {
m_config_args[strKey].clear();
} else {
m_config_args[strKey].push_back(strValue);
}
+
+ // Check that the arg is known
+ if (!IsArgKnown(strKey, error) && !ignore_invalid_keys) {
+ error = strprintf("Invalid configuration value %s", it->string_key.c_str());
+ return false;
+ }
}
+ return true;
}
-void ArgsManager::ReadConfigFiles()
+bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
{
{
LOCK(cs_args);
@@ -778,15 +843,18 @@ void ArgsManager::ReadConfigFiles()
// ok to not have a config file
if (stream.good()) {
- ReadConfigStream(stream);
+ if (!ReadConfigStream(stream, error, ignore_invalid_keys)) {
+ return false;
+ }
// if there is an -includeconf in the override args, but it is empty, that means the user
// passed '-noincludeconf' on the command line, in which case we should not include anything
if (m_override_args.count("-includeconf") == 0) {
+ std::string chain_id = GetChainName();
std::vector<std::string> includeconf(GetArgs("-includeconf"));
{
// We haven't set m_network yet (that happens in SelectParams()), so manually check
// for network.includeconf args.
- std::vector<std::string> includeconf_net(GetArgs(std::string("-") + GetChainName() + ".includeconf"));
+ std::vector<std::string> includeconf_net(GetArgs(std::string("-") + chain_id + ".includeconf"));
includeconf.insert(includeconf.end(), includeconf_net.begin(), includeconf_net.end());
}
@@ -795,24 +863,33 @@ void ArgsManager::ReadConfigFiles()
{
LOCK(cs_args);
m_config_args.erase("-includeconf");
- m_config_args.erase(std::string("-") + GetChainName() + ".includeconf");
+ m_config_args.erase(std::string("-") + chain_id + ".includeconf");
}
for (const std::string& to_include : includeconf) {
fs::ifstream include_config(GetConfigFile(to_include));
if (include_config.good()) {
- ReadConfigStream(include_config);
+ if (!ReadConfigStream(include_config, error, ignore_invalid_keys)) {
+ return false;
+ }
LogPrintf("Included configuration file %s\n", to_include.c_str());
} else {
- fprintf(stderr, "Failed to include configuration file %s\n", to_include.c_str());
+ error = "Failed to include configuration file " + to_include;
+ return false;
}
}
// Warn about recursive -includeconf
includeconf = GetArgs("-includeconf");
{
- std::vector<std::string> includeconf_net(GetArgs(std::string("-") + GetChainName() + ".includeconf"));
+ std::vector<std::string> includeconf_net(GetArgs(std::string("-") + chain_id + ".includeconf"));
includeconf.insert(includeconf.end(), includeconf_net.begin(), includeconf_net.end());
+ std::string chain_id_final = GetChainName();
+ if (chain_id_final != chain_id) {
+ // Also warn about recursive includeconf for the chain that was specified in one of the includeconfs
+ includeconf_net = GetArgs(std::string("-") + chain_id_final + ".includeconf");
+ includeconf.insert(includeconf.end(), includeconf_net.begin(), includeconf_net.end());
+ }
}
for (const std::string& to_include : includeconf) {
fprintf(stderr, "warning: -includeconf cannot be used from included files; ignoring -includeconf=%s\n", to_include.c_str());
@@ -823,8 +900,10 @@ void ArgsManager::ReadConfigFiles()
// If datadir is changed in .conf file:
ClearDatadirCache();
if (!fs::is_directory(GetDataDir(false))) {
- throw std::runtime_error(strprintf("specified data directory \"%s\" does not exist.", gArgs.GetArg("-datadir", "").c_str()));
+ error = strprintf("specified data directory \"%s\" does not exist.", gArgs.GetArg("-datadir", "").c_str());
+ return false;
}
+ return true;
}
std::string ArgsManager::GetChainName() const
diff --git a/src/util.h b/src/util.h
index 17dd5c0683..efd8a4bd9d 100644
--- a/src/util.h
+++ b/src/util.h
@@ -118,8 +118,7 @@ inline bool IsSwitchChar(char c)
#endif
}
-enum class OptionsCategory
-{
+enum class OptionsCategory {
OPTIONS,
CONNECTION,
WALLET,
@@ -132,7 +131,9 @@ enum class OptionsCategory
RPC,
GUI,
COMMANDS,
- REGISTER_COMMANDS
+ REGISTER_COMMANDS,
+
+ HIDDEN // Always the last option to avoid printing these in the help
};
class ArgsManager
@@ -140,14 +141,23 @@ class ArgsManager
protected:
friend class ArgsManagerHelper;
+ struct Arg
+ {
+ std::string m_help_param;
+ std::string m_help_text;
+ bool m_debug_only;
+
+ Arg(const std::string& help_param, const std::string& help_text, bool debug_only) : m_help_param(help_param), m_help_text(help_text), m_debug_only(debug_only) {};
+ };
+
mutable CCriticalSection cs_args;
std::map<std::string, std::vector<std::string>> m_override_args;
std::map<std::string, std::vector<std::string>> m_config_args;
std::string m_network;
std::set<std::string> m_network_only_args;
- std::map<std::pair<OptionsCategory, std::string>, std::pair<std::string, bool>> m_available_args;
+ std::map<OptionsCategory, std::map<std::string, Arg>> m_available_args;
- void ReadConfigStream(std::istream& stream);
+ bool ReadConfigStream(std::istream& stream, std::string& error, bool ignore_invalid_keys = false);
public:
ArgsManager();
@@ -157,8 +167,8 @@ public:
*/
void SelectConfigNetwork(const std::string& network);
- void ParseParameters(int argc, const char*const argv[]);
- void ReadConfigFiles();
+ bool ParseParameters(int argc, const char* const argv[], std::string& error);
+ bool ReadConfigFiles(std::string& error, bool ignore_invalid_keys = false);
/**
* Log warnings for options in m_section_only_args when
@@ -254,9 +264,19 @@ public:
void AddArg(const std::string& name, const std::string& help, const bool debug_only, const OptionsCategory& cat);
/**
+ * Clear available arguments
+ */
+ void ClearArgs() { m_available_args.clear(); }
+
+ /**
* Get the help string
*/
std::string GetHelpMessage();
+
+ /**
+ * Check whether we know of this arg
+ */
+ bool IsArgKnown(const std::string& key, std::string& error);
};
extern ArgsManager gArgs;
@@ -333,7 +353,7 @@ std::unique_ptr<T> MakeUnique(Args&&... args)
* CPU-intensive and non-interactive. See SCHED_BATCH in sched(7) for details.
*
* @return The return value of sched_setschedule(), or 1 on systems without
- * sched_setchedule().
+ * sched_setschedule().
*/
int ScheduleBatchPriority(void);
diff --git a/src/validation.cpp b/src/validation.cpp
index 3971906424..9791d6e2d8 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -1137,6 +1137,52 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus
return true;
}
+bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& message_start)
+{
+ CDiskBlockPos hpos = pos;
+ hpos.nPos -= 8; // Seek back 8 bytes for meta header
+ CAutoFile filein(OpenBlockFile(hpos, true), SER_DISK, CLIENT_VERSION);
+ if (filein.IsNull()) {
+ return error("%s: OpenBlockFile failed for %s", __func__, pos.ToString());
+ }
+
+ try {
+ CMessageHeader::MessageStartChars blk_start;
+ unsigned int blk_size;
+
+ filein >> blk_start >> blk_size;
+
+ if (memcmp(blk_start, message_start, CMessageHeader::MESSAGE_START_SIZE)) {
+ return error("%s: Block magic mismatch for %s: %s versus expected %s", __func__, pos.ToString(),
+ HexStr(blk_start, blk_start + CMessageHeader::MESSAGE_START_SIZE),
+ HexStr(message_start, message_start + CMessageHeader::MESSAGE_START_SIZE));
+ }
+
+ if (blk_size > MAX_SIZE) {
+ return error("%s: Block data is larger than maximum deserialization size for %s: %s versus %s", __func__, pos.ToString(),
+ blk_size, MAX_SIZE);
+ }
+
+ block.resize(blk_size); // Zeroing of memory is intentional here
+ filein.read((char*)block.data(), blk_size);
+ } catch(const std::exception& e) {
+ return error("%s: Read from block file failed: %s for %s", __func__, e.what(), pos.ToString());
+ }
+
+ return true;
+}
+
+bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CBlockIndex* pindex, const CMessageHeader::MessageStartChars& message_start)
+{
+ CDiskBlockPos block_pos;
+ {
+ LOCK(cs_main);
+ block_pos = pindex->GetBlockPos();
+ }
+
+ return ReadRawBlockFromDisk(block, block_pos, message_start);
+}
+
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
{
int halvings = nHeight / consensusParams.nSubsidyHalvingInterval;
diff --git a/src/validation.h b/src/validation.h
index 9b40100765..b5ab10786a 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -398,6 +398,8 @@ void InitScriptExecutionCache();
/** Functions for disk access for blocks */
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams);
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams);
+bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& message_start);
+bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const CBlockIndex* pindex, const CMessageHeader::MessageStartChars& message_start);
/** Functions for validating blocks and updating the block tree */
diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h
index 2f08162ee4..98b4298507 100644
--- a/src/wallet/coincontrol.h
+++ b/src/wallet/coincontrol.h
@@ -22,7 +22,7 @@ public:
boost::optional<OutputType> m_change_type;
//! If false, allows unselected inputs, but requires all selected inputs be used
bool fAllowOtherInputs;
- //! Includes watch only addresses which match the ISMINE_WATCH_SOLVABLE criteria
+ //! Includes watch only addresses which are solvable
bool fAllowWatchOnly;
//! Override automatic min/max checks on fee, m_feerate must be set if true
bool fOverrideFeeRate;
diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp
index 7742d5cec4..0eb85a6e5c 100644
--- a/src/wallet/feebumper.cpp
+++ b/src/wallet/feebumper.cpp
@@ -185,7 +185,7 @@ Result CreateTransaction(const CWallet* wallet, const uint256& txid, const CCoin
// If the output is not large enough to pay the fee, fail.
CAmount nDelta = new_fee - old_fee;
assert(nDelta > 0);
- mtx = *wtx.tx;
+ mtx = CMutableTransaction{*wtx.tx};
CTxOut* poutput = &(mtx.vout[nOutput]);
if (poutput->nValue < nDelta) {
errors.push_back("Change output is too small to bump the fee");
diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp
index 5cfa864512..daeff1d0e8 100644
--- a/src/wallet/init.cpp
+++ b/src/wallet/init.cpp
@@ -54,34 +54,34 @@ void WalletInit::AddWalletOptions() const
{
gArgs.AddArg("-addresstype", strprintf("What type of addresses to use (\"legacy\", \"p2sh-segwit\", or \"bech32\", default: \"%s\")", FormatOutputType(DEFAULT_ADDRESS_TYPE)), false, OptionsCategory::WALLET);
gArgs.AddArg("-changetype", "What type of change to use (\"legacy\", \"p2sh-segwit\", or \"bech32\"). Default is same as -addresstype, except when -addresstype=p2sh-segwit a native segwit output is used when sending to a native segwit address)", false, OptionsCategory::WALLET);
- gArgs.AddArg("-disablewallet", _("Do not load the wallet and disable wallet RPC calls"), false, OptionsCategory::WALLET);
- gArgs.AddArg("-discardfee=<amt>", strprintf(_("The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). "
- "Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target"),
+ gArgs.AddArg("-disablewallet", "Do not load the wallet and disable wallet RPC calls", false, OptionsCategory::WALLET);
+ gArgs.AddArg("-discardfee=<amt>", strprintf("The fee rate (in %s/kB) that indicates your tolerance for discarding change by adding it to the fee (default: %s). "
+ "Note: An output is discarded if it is dust at this rate, but we will always discard up to the dust relay fee and a discard fee above that is limited by the fee estimate for the longest target",
CURRENCY_UNIT, FormatMoney(DEFAULT_DISCARD_FEE)), false, OptionsCategory::WALLET);
- gArgs.AddArg("-fallbackfee=<amt>", strprintf(_("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)"),
+ gArgs.AddArg("-fallbackfee=<amt>", strprintf("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)",
CURRENCY_UNIT, FormatMoney(DEFAULT_FALLBACK_FEE)), false, OptionsCategory::WALLET);
- gArgs.AddArg("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), DEFAULT_KEYPOOL_SIZE), false, OptionsCategory::WALLET);
- gArgs.AddArg("-mintxfee=<amt>", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)"),
+ gArgs.AddArg("-keypool=<n>", strprintf("Set key pool size to <n> (default: %u)", DEFAULT_KEYPOOL_SIZE), false, OptionsCategory::WALLET);
+ gArgs.AddArg("-mintxfee=<amt>", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)",
CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)), false, OptionsCategory::WALLET);
- gArgs.AddArg("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"),
+ gArgs.AddArg("-paytxfee=<amt>", strprintf("Fee (in %s/kB) to add to transactions you send (default: %s)",
CURRENCY_UNIT, FormatMoney(CFeeRate{DEFAULT_PAY_TX_FEE}.GetFeePerK())), false, OptionsCategory::WALLET);
- gArgs.AddArg("-rescan", _("Rescan the block chain for missing wallet transactions on startup"), false, OptionsCategory::WALLET);
- gArgs.AddArg("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet on startup"), false, OptionsCategory::WALLET);
- gArgs.AddArg("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE), false, OptionsCategory::WALLET);
- gArgs.AddArg("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET), false, OptionsCategory::WALLET);
- gArgs.AddArg("-upgradewallet", _("Upgrade wallet to latest format on startup"), false, OptionsCategory::WALLET);
- gArgs.AddArg("-wallet=<path>", _("Specify wallet database path. Can be specified multiple times to load multiple wallets. Path is interpreted relative to <walletdir> if it is not absolute, and will be created if it does not exist (as a directory containing a wallet.dat file and log files). For backwards compatibility this will also accept names of existing data files in <walletdir>.)"), false, OptionsCategory::WALLET);
- gArgs.AddArg("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST), false, OptionsCategory::WALLET);
- gArgs.AddArg("-walletdir=<dir>", _("Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)"), false, OptionsCategory::WALLET);
- gArgs.AddArg("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"), false, OptionsCategory::WALLET);
- gArgs.AddArg("-walletrbf", strprintf(_("Send transactions with full-RBF opt-in enabled (RPC only, default: %u)"), DEFAULT_WALLET_RBF), false, OptionsCategory::WALLET);
- gArgs.AddArg("-zapwallettxes=<mode>", _("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)"), false, OptionsCategory::WALLET);
+ gArgs.AddArg("-rescan", "Rescan the block chain for missing wallet transactions on startup", false, OptionsCategory::WALLET);
+ gArgs.AddArg("-salvagewallet", "Attempt to recover private keys from a corrupt wallet on startup", false, OptionsCategory::WALLET);
+ gArgs.AddArg("-spendzeroconfchange", strprintf("Spend unconfirmed change when sending transactions (default: %u)", DEFAULT_SPEND_ZEROCONF_CHANGE), false, OptionsCategory::WALLET);
+ gArgs.AddArg("-txconfirmtarget=<n>", strprintf("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)", DEFAULT_TX_CONFIRM_TARGET), false, OptionsCategory::WALLET);
+ gArgs.AddArg("-upgradewallet", "Upgrade wallet to latest format on startup", false, OptionsCategory::WALLET);
+ gArgs.AddArg("-wallet=<path>", "Specify wallet database path. Can be specified multiple times to load multiple wallets. Path is interpreted relative to <walletdir> if it is not absolute, and will be created if it does not exist (as a directory containing a wallet.dat file and log files). For backwards compatibility this will also accept names of existing data files in <walletdir>.)", false, OptionsCategory::WALLET);
+ gArgs.AddArg("-walletbroadcast", strprintf("Make the wallet broadcast transactions (default: %u)", DEFAULT_WALLETBROADCAST), false, OptionsCategory::WALLET);
+ gArgs.AddArg("-walletdir=<dir>", "Specify directory to hold wallets (default: <datadir>/wallets if it exists, otherwise <datadir>)", false, OptionsCategory::WALLET);
+ gArgs.AddArg("-walletnotify=<cmd>", "Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)", false, OptionsCategory::WALLET);
+ gArgs.AddArg("-walletrbf", strprintf("Send transactions with full-RBF opt-in enabled (RPC only, default: %u)", DEFAULT_WALLET_RBF), false, OptionsCategory::WALLET);
+ gArgs.AddArg("-zapwallettxes=<mode>", "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)", false, OptionsCategory::WALLET);
gArgs.AddArg("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE), true, OptionsCategory::WALLET_DEBUG_TEST);
gArgs.AddArg("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET), true, OptionsCategory::WALLET_DEBUG_TEST);
gArgs.AddArg("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB), true, OptionsCategory::WALLET_DEBUG_TEST);
- gArgs.AddArg("-walletrejectlongchains", strprintf(_("Wallet will not create transactions that violate mempool chain limits (default: %u)"), DEFAULT_WALLET_REJECT_LONG_CHAINS), true, OptionsCategory::WALLET_DEBUG_TEST);
+ gArgs.AddArg("-walletrejectlongchains", strprintf("Wallet will not create transactions that violate mempool chain limits (default: %u)", DEFAULT_WALLET_REJECT_LONG_CHAINS), true, OptionsCategory::WALLET_DEBUG_TEST);
}
bool WalletInit::ParameterInteraction() const
@@ -226,7 +226,7 @@ bool WalletInit::Open() const
}
for (const std::string& walletFile : gArgs.GetArgs("-wallet")) {
- CWallet * const pwallet = CWallet::CreateWalletFromFile(walletFile, fs::absolute(walletFile, GetWalletDir()));
+ std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(walletFile, fs::absolute(walletFile, GetWalletDir()));
if (!pwallet) {
return false;
}
@@ -238,7 +238,7 @@ bool WalletInit::Open() const
void WalletInit::Start(CScheduler& scheduler) const
{
- for (CWallet* pwallet : GetWallets()) {
+ for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
pwallet->postInitProcess();
}
@@ -248,22 +248,21 @@ void WalletInit::Start(CScheduler& scheduler) const
void WalletInit::Flush() const
{
- for (CWallet* pwallet : GetWallets()) {
+ for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
pwallet->Flush(false);
}
}
void WalletInit::Stop() const
{
- for (CWallet* pwallet : GetWallets()) {
+ for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
pwallet->Flush(true);
}
}
void WalletInit::Close() const
{
- for (CWallet* pwallet : GetWallets()) {
+ for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
RemoveWallet(pwallet);
- delete pwallet;
}
}
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 4fe630b660..d09af1dbd1 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -56,7 +56,7 @@ static std::string DecodeDumpString(const std::string &str) {
for (unsigned int pos = 0; pos < str.length(); pos++) {
unsigned char c = str[pos];
if (c == '%' && pos+2 < str.length()) {
- c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) |
+ c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) |
((str[pos+2]>>6)*9+((str[pos+2]-'0')&15));
pos += 2;
}
@@ -89,7 +89,8 @@ static bool GetWalletAddressesForKey(CWallet * const pwallet, const CKeyID &keyi
UniValue importprivkey(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -185,7 +186,8 @@ UniValue importprivkey(const JSONRPCRequest& request)
UniValue abortrescan(const JSONRPCRequest& request)
{
- CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -246,7 +248,8 @@ static void ImportAddress(CWallet* const pwallet, const CTxDestination& dest, co
UniValue importaddress(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -330,7 +333,8 @@ UniValue importaddress(const JSONRPCRequest& request)
UniValue importprunedfunds(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -392,7 +396,8 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
UniValue removeprunedfunds(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -430,7 +435,8 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
UniValue importpubkey(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -506,7 +512,8 @@ UniValue importpubkey(const JSONRPCRequest& request)
UniValue importwallet(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -552,7 +559,7 @@ UniValue importwallet(const JSONRPCRequest& request)
file.seekg(0, file.beg);
// Use uiInterface.ShowProgress instead of pwallet.ShowProgress because pwallet.ShowProgress has a cancel button tied to AbortRescan which
- // we don't want for this progress bar shoing the import progress. uiInterface.ShowProgress does not have a cancel button.
+ // we don't want for this progress bar showing the import progress. uiInterface.ShowProgress does not have a cancel button.
uiInterface.ShowProgress(_("Importing..."), 0, false); // show progress dialog in GUI
while (file.good()) {
uiInterface.ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))), false);
@@ -640,7 +647,8 @@ UniValue importwallet(const JSONRPCRequest& request)
UniValue dumpprivkey(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -683,7 +691,8 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
UniValue dumpwallet(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -752,13 +761,13 @@ UniValue dumpwallet(const JSONRPCRequest& request)
file << "\n";
// add the base58check encoded extended master if the wallet uses HD
- CKeyID masterKeyID = pwallet->GetHDChain().masterKeyID;
- if (!masterKeyID.IsNull())
+ CKeyID seed_id = pwallet->GetHDChain().seed_id;
+ if (!seed_id.IsNull())
{
- CKey key;
- if (pwallet->GetKey(masterKeyID, key)) {
+ CKey seed;
+ if (pwallet->GetKey(seed_id, seed)) {
CExtKey masterKey;
- masterKey.SetMaster(key.begin(), key.size());
+ masterKey.SetSeed(seed.begin(), seed.size());
file << "# extended private masterkey: " << EncodeExtKey(masterKey) << "\n\n";
}
@@ -773,12 +782,12 @@ UniValue dumpwallet(const JSONRPCRequest& request)
file << strprintf("%s %s ", EncodeSecret(key), strTime);
if (GetWalletAddressesForKey(pwallet, keyid, strAddr, strLabel)) {
file << strprintf("label=%s", strLabel);
- } else if (keyid == masterKeyID) {
- file << "hdmaster=1";
+ } else if (keyid == seed_id) {
+ file << "hdseed=1";
} else if (mapKeyPool.count(keyid)) {
file << "reserve=1";
- } else if (pwallet->mapKeyMetadata[keyid].hdKeypath == "m") {
- file << "inactivehdmaster=1";
+ } else if (pwallet->mapKeyMetadata[keyid].hdKeypath == "s") {
+ file << "inactivehdseed=1";
} else {
file << "change=1";
}
@@ -1127,7 +1136,8 @@ static int64_t GetImportTimestamp(const UniValue& data, int64_t now)
UniValue importmulti(const JSONRPCRequest& mainRequest)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(mainRequest);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(mainRequest);
+ CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, mainRequest.fHelp)) {
return NullUniValue;
}
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 8cd3952837..456f08bc14 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -40,17 +40,17 @@
static const std::string WALLET_ENDPOINT_BASE = "/wallet/";
-CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
+std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request)
{
if (request.URI.substr(0, WALLET_ENDPOINT_BASE.size()) == WALLET_ENDPOINT_BASE) {
// wallet endpoint was used
std::string requestedWallet = urlDecode(request.URI.substr(WALLET_ENDPOINT_BASE.size()));
- CWallet* pwallet = GetWallet(requestedWallet);
+ std::shared_ptr<CWallet> pwallet = GetWallet(requestedWallet);
if (!pwallet) throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
return pwallet;
}
- std::vector<CWallet*> wallets = GetWallets();
+ std::vector<std::shared_ptr<CWallet>> wallets = GetWallets();
return wallets.size() == 1 || (request.fHelp && wallets.size() > 0) ? wallets[0] : nullptr;
}
@@ -134,7 +134,9 @@ static std::string LabelFromValue(const UniValue& value)
static UniValue getnewaddress(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -198,7 +200,9 @@ CTxDestination GetLabelDestination(CWallet* const pwallet, const std::string& la
static UniValue getlabeladdress(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -256,7 +260,9 @@ static UniValue getlabeladdress(const JSONRPCRequest& request)
static UniValue getrawchangeaddress(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -304,7 +310,9 @@ static UniValue getrawchangeaddress(const JSONRPCRequest& request)
static UniValue setlabel(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -358,7 +366,9 @@ static UniValue setlabel(const JSONRPCRequest& request)
static UniValue getaccount(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -401,7 +411,9 @@ static UniValue getaccount(const JSONRPCRequest& request)
static UniValue getaddressesbyaccount(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -487,7 +499,9 @@ static CTransactionRef SendMoney(CWallet * const pwallet, const CTxDestination &
static UniValue sendtoaddress(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -574,7 +588,9 @@ static UniValue sendtoaddress(const JSONRPCRequest& request)
static UniValue listaddressgroupings(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -631,7 +647,9 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request)
static UniValue signmessage(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -692,7 +710,9 @@ static UniValue signmessage(const JSONRPCRequest& request)
static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -757,7 +777,9 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request)
static UniValue getreceivedbylabel(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -827,7 +849,9 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request)
static UniValue getbalance(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -910,7 +934,9 @@ static UniValue getbalance(const JSONRPCRequest& request)
static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -932,7 +958,9 @@ static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
static UniValue movecmd(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -989,7 +1017,9 @@ static UniValue movecmd(const JSONRPCRequest& request)
static UniValue sendfrom(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -1062,7 +1092,9 @@ static UniValue sendfrom(const JSONRPCRequest& request)
static UniValue sendmany(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -1257,7 +1289,9 @@ static UniValue sendmany(const JSONRPCRequest& request)
static UniValue addmultisigaddress(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -1392,7 +1426,9 @@ public:
static UniValue addwitnessaddress(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -1624,7 +1660,9 @@ static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bo
static UniValue listreceivedbyaddress(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -1673,7 +1711,9 @@ static UniValue listreceivedbyaddress(const JSONRPCRequest& request)
static UniValue listreceivedbylabel(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -1838,7 +1878,9 @@ static void AcentryToJSON(const CAccountingEntry& acentry, const std::string& st
UniValue listtransactions(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -2026,7 +2068,9 @@ UniValue listtransactions(const JSONRPCRequest& request)
static UniValue listaccounts(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -2119,7 +2163,9 @@ static UniValue listaccounts(const JSONRPCRequest& request)
static UniValue listsinceblock(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -2258,7 +2304,9 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
static UniValue gettransaction(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -2352,7 +2400,9 @@ static UniValue gettransaction(const JSONRPCRequest& request)
static UniValue abandontransaction(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -2396,7 +2446,9 @@ static UniValue abandontransaction(const JSONRPCRequest& request)
static UniValue backupwallet(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -2429,7 +2481,9 @@ static UniValue backupwallet(const JSONRPCRequest& request)
static UniValue keypoolrefill(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -2476,7 +2530,9 @@ static void LockWallet(CWallet* pWallet)
static UniValue walletpassphrase(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -2549,7 +2605,9 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
static UniValue walletpassphrasechange(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -2598,7 +2656,9 @@ static UniValue walletpassphrasechange(const JSONRPCRequest& request)
static UniValue walletlock(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -2636,7 +2696,9 @@ static UniValue walletlock(const JSONRPCRequest& request)
static UniValue encryptwallet(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -2696,7 +2758,9 @@ static UniValue encryptwallet(const JSONRPCRequest& request)
static UniValue lockunspent(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -2823,7 +2887,9 @@ static UniValue lockunspent(const JSONRPCRequest& request)
static UniValue listlockunspent(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -2874,7 +2940,9 @@ static UniValue listlockunspent(const JSONRPCRequest& request)
static UniValue settxfee(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -2903,7 +2971,9 @@ static UniValue settxfee(const JSONRPCRequest& request)
static UniValue getwalletinfo(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -2925,7 +2995,8 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
" \"keypoolsize_hd_internal\": xxxx, (numeric) how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)\n"
" \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
" \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n"
- " \"hdmasterkeyid\": \"<hash160>\" (string, optional) the Hash160 of the HD master pubkey (only present when HD is enabled)\n"
+ " \"hdseedid\": \"<hash160>\" (string, optional) the Hash160 of the HD seed (only present when HD is enabled)\n"
+ " \"hdmasterkeyid\": \"<hash160>\" (string, optional) alias for hdseedid retained for backwards-compatibility. Will be removed in V0.18.\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getwalletinfo", "")
@@ -2949,16 +3020,18 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
obj.pushKV("txcount", (int)pwallet->mapWallet.size());
obj.pushKV("keypoololdest", pwallet->GetOldestKeyPoolTime());
obj.pushKV("keypoolsize", (int64_t)kpExternalSize);
- CKeyID masterKeyID = pwallet->GetHDChain().masterKeyID;
- if (!masterKeyID.IsNull() && pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
+ CKeyID seed_id = pwallet->GetHDChain().seed_id;
+ if (!seed_id.IsNull() && pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) {
obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize));
}
if (pwallet->IsCrypted()) {
obj.pushKV("unlocked_until", pwallet->nRelockTime);
}
obj.pushKV("paytxfee", ValueFromAmount(pwallet->m_pay_tx_fee.GetFeePerK()));
- if (!masterKeyID.IsNull())
- obj.pushKV("hdmasterkeyid", masterKeyID.GetHex());
+ if (!seed_id.IsNull()) {
+ obj.pushKV("hdseedid", seed_id.GetHex());
+ obj.pushKV("hdmasterkeyid", seed_id.GetHex());
+ }
return obj;
}
@@ -2981,14 +3054,14 @@ static UniValue listwallets(const JSONRPCRequest& request)
UniValue obj(UniValue::VARR);
- for (CWallet* pwallet : GetWallets()) {
- if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
+ for (const std::shared_ptr<CWallet>& wallet : GetWallets()) {
+ if (!EnsureWalletIsAvailable(wallet.get(), request.fHelp)) {
return NullUniValue;
}
- LOCK(pwallet->cs_wallet);
+ LOCK(wallet->cs_wallet);
- obj.push_back(pwallet->GetName());
+ obj.push_back(wallet->GetName());
}
return obj;
@@ -3026,7 +3099,7 @@ UniValue loadwallet(const JSONRPCRequest& request)
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet file verification failed: " + error);
}
- CWallet * const wallet = CWallet::CreateWalletFromFile(wallet_file, fs::absolute(wallet_file, GetWalletDir()));
+ std::shared_ptr<CWallet> const wallet = CWallet::CreateWalletFromFile(wallet_file, fs::absolute(wallet_file, GetWalletDir()));
if (!wallet) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet loading failed.");
}
@@ -3041,9 +3114,58 @@ UniValue loadwallet(const JSONRPCRequest& request)
return obj;
}
+UniValue createwallet(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() != 1) {
+ throw std::runtime_error(
+ "createwallet \"wallet_name\"\n"
+ "\nCreates and loads a new wallet.\n"
+ "\nArguments:\n"
+ "1. \"wallet_name\" (string, required) The name for the new wallet. If this is a path, the wallet will be created at the path location.\n"
+ "\nResult:\n"
+ "{\n"
+ " \"name\" : <wallet_name>, (string) The wallet name if created successfully. If the wallet was created using a full path, the wallet_name will be the full path.\n"
+ " \"warning\" : <warning>, (string) Warning message if wallet was not loaded cleanly.\n"
+ "}\n"
+ "\nExamples:\n"
+ + HelpExampleCli("createwallet", "\"testwallet\"")
+ + HelpExampleRpc("createwallet", "\"testwallet\"")
+ );
+ }
+ std::string wallet_name = request.params[0].get_str();
+ std::string error;
+ std::string warning;
+
+ fs::path wallet_path = fs::absolute(wallet_name, GetWalletDir());
+ if (fs::symlink_status(wallet_path).type() != fs::file_not_found) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Wallet " + wallet_name + " already exists.");
+ }
+
+ // Wallet::Verify will check if we're trying to create a wallet with a duplication name.
+ if (!CWallet::Verify(wallet_name, false, error, warning)) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Wallet file verification failed: " + error);
+ }
+
+ std::shared_ptr<CWallet> const wallet = CWallet::CreateWalletFromFile(wallet_name, fs::absolute(wallet_name, GetWalletDir()));
+ if (!wallet) {
+ throw JSONRPCError(RPC_WALLET_ERROR, "Wallet creation failed.");
+ }
+ AddWallet(wallet);
+
+ wallet->postInitProcess();
+
+ UniValue obj(UniValue::VOBJ);
+ obj.pushKV("name", wallet->GetName());
+ obj.pushKV("warning", warning);
+
+ return obj;
+}
+
static UniValue resendwallettransactions(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -3078,7 +3200,9 @@ static UniValue resendwallettransactions(const JSONRPCRequest& request)
static UniValue listunspent(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -3249,7 +3373,9 @@ static UniValue listunspent(const JSONRPCRequest& request)
static UniValue fundrawtransaction(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -3449,7 +3575,9 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request)
UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -3518,7 +3646,9 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
static UniValue bumpfee(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
@@ -3667,7 +3797,9 @@ static UniValue bumpfee(const JSONRPCRequest& request)
UniValue generate(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -3712,7 +3844,9 @@ UniValue generate(const JSONRPCRequest& request)
UniValue rescanblockchain(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -3917,7 +4051,9 @@ static UniValue AddressBookDataToJSON(const CAddressBookData& data, const bool v
UniValue getaddressinfo(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -3948,13 +4084,14 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
" ]\n"
" \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output (only if \"script\" is \"multisig\")\n"
" \"pubkey\" : \"publickeyhex\", (string, optional) The hex value of the raw public key, for single-key addresses (possibly embedded in P2SH or P2WSH)\n"
- " \"embedded\" : {...}, (object, optional) Information about the address embedded in P2SH or P2WSH, if relevant and known. It includes all getaddressinfo output fields for the embedded address, excluding metadata (\"timestamp\", \"hdkeypath\", \"hdmasterkeyid\") and relation to the wallet (\"ismine\", \"iswatchonly\", \"account\").\n"
+ " \"embedded\" : {...}, (object, optional) Information about the address embedded in P2SH or P2WSH, if relevant and known. It includes all getaddressinfo output fields for the embedded address, excluding metadata (\"timestamp\", \"hdkeypath\", \"hdseedid\") and relation to the wallet (\"ismine\", \"iswatchonly\", \"account\").\n"
" \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
" \"label\" : \"label\" (string) The label associated with the address, \"\" is the default account\n"
" \"account\" : \"account\" (string) DEPRECATED. This field will be removed in V0.18. To see this deprecated field, start bitcoind with -deprecatedrpc=accounts. The account associated with the address, \"\" is the default account\n"
" \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n"
" \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n"
- " \"hdmasterkeyid\" : \"<hash160>\" (string, optional) The Hash160 of the HD master pubkey\n"
+ " \"hdseedid\" : \"<hash160>\" (string, optional) The Hash160 of the HD seed\n"
+ " \"hdmasterkeyid\" : \"<hash160>\" (string, optional) alias for hdseedid maintained for backwards compatibility. Will be removed in V0.18.\n"
" \"labels\" (object) Array of labels associated with the address.\n"
" [\n"
" { (json object of label data)\n"
@@ -4014,7 +4151,8 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
ret.pushKV("timestamp", meta->nCreateTime);
if (!meta->hdKeypath.empty()) {
ret.pushKV("hdkeypath", meta->hdKeypath);
- ret.pushKV("hdmasterkeyid", meta->hdMasterKeyID.GetHex());
+ ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
+ ret.pushKV("hdmasterkeyid", meta->hd_seed_id.GetHex());
}
}
@@ -4033,7 +4171,9 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
static UniValue getaddressesbylabel(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -4076,7 +4216,9 @@ static UniValue getaddressesbylabel(const JSONRPCRequest& request)
static UniValue listlabels(const JSONRPCRequest& request)
{
- CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
+
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
}
@@ -4128,7 +4270,8 @@ static UniValue listlabels(const JSONRPCRequest& request)
UniValue sethdseed(const JSONRPCRequest& request)
{
- CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
+ std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
+ CWallet* const pwallet = wallet.get();
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
return NullUniValue;
@@ -4147,7 +4290,7 @@ UniValue sethdseed(const JSONRPCRequest& request)
" If false, addresses (including change addresses if the wallet already had HD Chain Split enabled) from the existing\n"
" keypool will be used until it has been depleted.\n"
"2. \"seed\" (string, optional) The WIF private key to use as the new HD seed; if not provided a random seed will be used.\n"
- " The seed value can be retrieved using the dumpwallet command. It is the private key marked hdmaster=1\n"
+ " The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1\n"
"\nExamples:\n"
+ HelpExampleCli("sethdseed", "")
+ HelpExampleCli("sethdseed", "false")
@@ -4176,7 +4319,7 @@ UniValue sethdseed(const JSONRPCRequest& request)
CPubKey master_pub_key;
if (request.params[1].isNull()) {
- master_pub_key = pwallet->GenerateNewHDMasterKey();
+ master_pub_key = pwallet->GenerateNewSeed();
} else {
CKey key = DecodeSecret(request.params[1].get_str());
if (!key.IsValid()) {
@@ -4187,10 +4330,10 @@ UniValue sethdseed(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key (either as an HD seed or as a loose private key)");
}
- master_pub_key = pwallet->DeriveNewMasterHDKey(key);
+ master_pub_key = pwallet->DeriveNewSeed(key);
}
- pwallet->SetHDMasterKey(master_pub_key);
+ pwallet->SetHDSeed(master_pub_key);
if (flush_key_pool) pwallet->NewKeyPool();
return NullUniValue;
@@ -4219,6 +4362,7 @@ static const CRPCCommand commands[] =
{ "hidden", "addwitnessaddress", &addwitnessaddress, {"address","p2sh"} },
{ "wallet", "backupwallet", &backupwallet, {"destination"} },
{ "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
+ { "wallet", "createwallet", &createwallet, {"wallet_name"} },
{ "wallet", "dumpprivkey", &dumpprivkey, {"address"} },
{ "wallet", "dumpwallet", &dumpwallet, {"filename"} },
{ "wallet", "encryptwallet", &encryptwallet, {"passphrase"} },
diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h
index 84f161abb5..b841f3e424 100644
--- a/src/wallet/rpcwallet.h
+++ b/src/wallet/rpcwallet.h
@@ -20,7 +20,7 @@ void RegisterWalletRPCCommands(CRPCTable &t);
* @param[in] request JSONRPCRequest that wishes to access a wallet
* @return nullptr if no wallet should be used, or a pointer to the CWallet
*/
-CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request);
+std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request);
std::string HelpRequiringPassphrase(CWallet *);
void EnsureWalletIsUnlocked(CWallet *);
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 99c963a348..03754154fc 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -73,8 +73,8 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
// before the missing block, and success for a key whose creation time is
// after.
{
- CWallet wallet("dummy", WalletDatabase::CreateDummy());
- AddWallet(&wallet);
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy());
+ AddWallet(wallet);
UniValue keys;
keys.setArray();
UniValue key;
@@ -105,7 +105,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
"downloading and rescanning the relevant blocks (see -reindex and -rescan "
"options).\"}},{\"success\":true}]",
0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW));
- RemoveWallet(&wallet);
+ RemoveWallet(wallet);
}
}
@@ -132,36 +132,36 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// Import key into wallet and call dumpwallet to create backup file.
{
- CWallet wallet("dummy", WalletDatabase::CreateDummy());
- LOCK(wallet.cs_wallet);
- wallet.mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME;
- wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy());
+ LOCK(wallet->cs_wallet);
+ wallet->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME;
+ wallet->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
JSONRPCRequest request;
request.params.setArray();
request.params.push_back((pathTemp / "wallet.backup").string());
- AddWallet(&wallet);
+ AddWallet(wallet);
::dumpwallet(request);
- RemoveWallet(&wallet);
+ RemoveWallet(wallet);
}
// Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME
// were scanned, and no prior blocks were scanned.
{
- CWallet wallet("dummy", WalletDatabase::CreateDummy());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>("dummy", WalletDatabase::CreateDummy());
JSONRPCRequest request;
request.params.setArray();
request.params.push_back((pathTemp / "wallet.backup").string());
- AddWallet(&wallet);
+ AddWallet(wallet);
::importwallet(request);
- RemoveWallet(&wallet);
+ RemoveWallet(wallet);
- LOCK(wallet.cs_wallet);
- BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3U);
+ LOCK(wallet->cs_wallet);
+ BOOST_CHECK_EQUAL(wallet->mapWallet.size(), 3U);
BOOST_CHECK_EQUAL(m_coinbase_txns.size(), 103U);
for (size_t i = 0; i < m_coinbase_txns.size(); ++i) {
- bool found = wallet.GetWalletTx(m_coinbase_txns[i]->GetHash());
+ bool found = wallet->GetWalletTx(m_coinbase_txns[i]->GetHash());
bool expected = i >= 100;
BOOST_CHECK_EQUAL(found, expected);
}
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 2a2f8b5b20..c3597aace8 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -36,23 +36,23 @@
#include <boost/algorithm/string/replace.hpp>
static CCriticalSection cs_wallets;
-static std::vector<CWallet*> vpwallets GUARDED_BY(cs_wallets);
+static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets);
-bool AddWallet(CWallet* wallet)
+bool AddWallet(const std::shared_ptr<CWallet>& wallet)
{
LOCK(cs_wallets);
assert(wallet);
- std::vector<CWallet*>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
+ std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
if (i != vpwallets.end()) return false;
vpwallets.push_back(wallet);
return true;
}
-bool RemoveWallet(CWallet* wallet)
+bool RemoveWallet(const std::shared_ptr<CWallet>& wallet)
{
LOCK(cs_wallets);
assert(wallet);
- std::vector<CWallet*>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
+ std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
if (i == vpwallets.end()) return false;
vpwallets.erase(i);
return true;
@@ -64,16 +64,16 @@ bool HasWallets()
return !vpwallets.empty();
}
-std::vector<CWallet*> GetWallets()
+std::vector<std::shared_ptr<CWallet>> GetWallets()
{
LOCK(cs_wallets);
return vpwallets;
}
-CWallet* GetWallet(const std::string& name)
+std::shared_ptr<CWallet> GetWallet(const std::string& name)
{
LOCK(cs_wallets);
- for (CWallet* wallet : vpwallets) {
+ for (const std::shared_ptr<CWallet>& wallet : vpwallets) {
if (wallet->GetName() == name) return wallet;
}
return nullptr;
@@ -191,17 +191,17 @@ CPubKey CWallet::GenerateNewKey(WalletBatch &batch, bool internal)
void CWallet::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey& secret, bool internal)
{
// for now we use a fixed keypath scheme of m/0'/0'/k
- CKey key; //master key seed (256bit)
+ CKey seed; //seed (256bit)
CExtKey masterKey; //hd master key
CExtKey accountKey; //key at m/0'
CExtKey chainChildKey; //key at m/0'/0' (external) or m/0'/1' (internal)
CExtKey childKey; //key at m/0'/0'/<n>'
- // try to get the master key
- if (!GetKey(hdChain.masterKeyID, key))
- throw std::runtime_error(std::string(__func__) + ": Master key not found");
+ // try to get the seed
+ if (!GetKey(hdChain.seed_id, seed))
+ throw std::runtime_error(std::string(__func__) + ": seed not found");
- masterKey.SetMaster(key.begin(), key.size());
+ masterKey.SetSeed(seed.begin(), seed.size());
// derive m/0'
// use hardened derivation (child keys >= 0x80000000 are hardened after bip32)
@@ -228,7 +228,7 @@ void CWallet::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey
}
} while (HaveKey(childKey.key.GetPubKey().GetID()));
secret = childKey.key;
- metadata.hdMasterKeyID = hdChain.masterKeyID;
+ metadata.hd_seed_id = hdChain.seed_id;
// update the chain model in the database
if (!batch.WriteHDChain(hdChain))
throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed");
@@ -689,9 +689,9 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
Lock();
Unlock(strWalletPassphrase);
- // if we are using HD, replace the HD master key (seed) with a new one
+ // if we are using HD, replace the HD seed with a new one
if (IsHDEnabled()) {
- if (!SetHDMasterKey(GenerateNewHDMasterKey())) {
+ if (!SetHDSeed(GenerateNewSeed())) {
return false;
}
}
@@ -1450,41 +1450,41 @@ CAmount CWallet::GetChange(const CTransaction& tx) const
return nChange;
}
-CPubKey CWallet::GenerateNewHDMasterKey()
+CPubKey CWallet::GenerateNewSeed()
{
CKey key;
key.MakeNewKey(true);
- return DeriveNewMasterHDKey(key);
+ return DeriveNewSeed(key);
}
-CPubKey CWallet::DeriveNewMasterHDKey(const CKey& key)
+CPubKey CWallet::DeriveNewSeed(const CKey& key)
{
int64_t nCreationTime = GetTime();
CKeyMetadata metadata(nCreationTime);
- // calculate the pubkey
- CPubKey pubkey = key.GetPubKey();
- assert(key.VerifyPubKey(pubkey));
+ // calculate the seed
+ CPubKey seed = key.GetPubKey();
+ assert(key.VerifyPubKey(seed));
- // set the hd keypath to "m" -> Master, refers the masterkeyid to itself
- metadata.hdKeypath = "m";
- metadata.hdMasterKeyID = pubkey.GetID();
+ // set the hd keypath to "s" -> Seed, refers the seed to itself
+ metadata.hdKeypath = "s";
+ metadata.hd_seed_id = seed.GetID();
{
LOCK(cs_wallet);
// mem store the metadata
- mapKeyMetadata[pubkey.GetID()] = metadata;
+ mapKeyMetadata[seed.GetID()] = metadata;
// write the key&metadata to the database
- if (!AddKeyPubKey(key, pubkey))
+ if (!AddKeyPubKey(key, seed))
throw std::runtime_error(std::string(__func__) + ": AddKeyPubKey failed");
}
- return pubkey;
+ return seed;
}
-bool CWallet::SetHDMasterKey(const CPubKey& pubkey)
+bool CWallet::SetHDSeed(const CPubKey& seed)
{
LOCK(cs_wallet);
// store the keyid (hash160) together with
@@ -1492,7 +1492,7 @@ bool CWallet::SetHDMasterKey(const CPubKey& pubkey)
// as a hdchain object
CHDChain newHdChain;
newHdChain.nVersion = CanSupportFeature(FEATURE_HD_SPLIT) ? CHDChain::VERSION_HD_CHAIN_SPLIT : CHDChain::VERSION_HD_BASE;
- newHdChain.masterKeyID = pubkey.GetID();
+ newHdChain.seed_id = seed.GetID();
SetHDChain(newHdChain, false);
return true;
@@ -1510,7 +1510,7 @@ bool CWallet::SetHDChain(const CHDChain& chain, bool memonly)
bool CWallet::IsHDEnabled() const
{
- return !hdChain.masterKeyID.IsNull();
+ return !hdChain.seed_id.IsNull();
}
int64_t CWalletTx::GetTxTime() const
@@ -2075,8 +2075,8 @@ bool CWalletTx::IsTrusted() const
bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const
{
- CMutableTransaction tx1 = *this->tx;
- CMutableTransaction tx2 = *_tx.tx;
+ CMutableTransaction tx1 {*this->tx};
+ CMutableTransaction tx2 {*_tx.tx};
for (auto& txin : tx1.vin) txin.scriptSig = CScript();
for (auto& txin : tx2.vin) txin.scriptSig = CScript();
return CTransaction(tx1) == CTransaction(tx2);
@@ -2376,10 +2376,10 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
continue;
}
- bool fSpendableIn = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (coinControl && coinControl->fAllowWatchOnly && (mine & ISMINE_WATCH_SOLVABLE) != ISMINE_NO);
- bool fSolvableIn = (mine & (ISMINE_SPENDABLE | ISMINE_WATCH_SOLVABLE)) != ISMINE_NO;
+ bool solvable = IsSolvable(*this, pcoin->tx->vout[i].scriptPubKey);
+ bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
- vCoins.push_back(COutput(pcoin, i, nDepth, fSpendableIn, fSolvableIn, safeTx));
+ vCoins.push_back(COutput(pcoin, i, nDepth, spendable, solvable, safeTx));
// Checks the sum amount of all UTXO's.
if (nMinimumSumAmount != MAX_MONEY) {
@@ -2608,9 +2608,8 @@ bool CWallet::SignTransaction(CMutableTransaction &tx)
AssertLockHeld(cs_wallet); // mapWallet
// sign the new tx
- CTransaction txNewConst(tx);
int nIn = 0;
- for (const auto& input : tx.vin) {
+ for (auto& input : tx.vin) {
std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(input.prevout.hash);
if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
return false;
@@ -2618,10 +2617,10 @@ bool CWallet::SignTransaction(CMutableTransaction &tx)
const CScript& scriptPubKey = mi->second.tx->vout[input.prevout.n].scriptPubKey;
const CAmount& amount = mi->second.tx->vout[input.prevout.n].nValue;
SignatureData sigdata;
- if (!ProduceSignature(*this, TransactionSignatureCreator(&txNewConst, nIn, amount, SIGHASH_ALL), scriptPubKey, sigdata)) {
+ if (!ProduceSignature(*this, MutableTransactionSignatureCreator(&tx, nIn, amount, SIGHASH_ALL), scriptPubKey, sigdata)) {
return false;
}
- UpdateTransaction(tx, nIn, sigdata);
+ UpdateInput(input, sigdata);
nIn++;
}
return true;
@@ -3040,19 +3039,18 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
if (sign)
{
- CTransaction txNewConst(txNew);
int nIn = 0;
for (const auto& coin : selected_coins)
{
const CScript& scriptPubKey = coin.txout.scriptPubKey;
SignatureData sigdata;
- if (!ProduceSignature(*this, TransactionSignatureCreator(&txNewConst, nIn, coin.txout.nValue, SIGHASH_ALL), scriptPubKey, sigdata))
+ if (!ProduceSignature(*this, MutableTransactionSignatureCreator(&txNew, nIn, coin.txout.nValue, SIGHASH_ALL), scriptPubKey, sigdata))
{
strFailReason = _("Signing transaction failed");
return false;
} else {
- UpdateTransaction(txNew, nIn, sigdata);
+ UpdateInput(txNew.vin.at(nIn), sigdata);
}
nIn++;
@@ -3201,8 +3199,6 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
if (nLoadWalletRet != DBErrors::LOAD_OK)
return nLoadWalletRet;
- uiInterface.LoadWallet(this);
-
return DBErrors::LOAD_OK;
}
@@ -3429,7 +3425,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
return true;
}
-void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal)
+bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal)
{
nIndex = -1;
keypool.vchPubKey = CPubKey();
@@ -3440,11 +3436,13 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
TopUpKeyPool();
bool fReturningInternal = IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT) && fRequestedInternal;
- std::set<int64_t>& setKeyPool = set_pre_split_keypool.empty() ? (fReturningInternal ? setInternalKeyPool : setExternalKeyPool) : set_pre_split_keypool;
+ bool use_split_keypool = set_pre_split_keypool.empty();
+ std::set<int64_t>& setKeyPool = use_split_keypool ? (fReturningInternal ? setInternalKeyPool : setExternalKeyPool) : set_pre_split_keypool;
// Get the oldest key
- if(setKeyPool.empty())
- return;
+ if (setKeyPool.empty()) {
+ return false;
+ }
WalletBatch batch(*database);
@@ -3458,14 +3456,17 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
throw std::runtime_error(std::string(__func__) + ": unknown key in key pool");
}
// If the key was pre-split keypool, we don't care about what type it is
- if (set_pre_split_keypool.size() == 0 && keypool.fInternal != fReturningInternal) {
+ if (use_split_keypool && keypool.fInternal != fReturningInternal) {
throw std::runtime_error(std::string(__func__) + ": keypool entry misclassified");
}
+ if (!keypool.vchPubKey.IsValid()) {
+ throw std::runtime_error(std::string(__func__) + ": keypool entry invalid");
+ }
- assert(keypool.vchPubKey.IsValid());
m_pool_key_to_index.erase(keypool.vchPubKey.GetID());
LogPrintf("keypool reserve %d\n", nIndex);
}
+ return true;
}
void CWallet::KeepKey(int64_t nIndex)
@@ -3498,10 +3499,8 @@ bool CWallet::GetKeyFromPool(CPubKey& result, bool internal)
CKeyPool keypool;
{
LOCK(cs_wallet);
- int64_t nIndex = 0;
- ReserveKeyFromKeyPool(nIndex, keypool, internal);
- if (nIndex == -1)
- {
+ int64_t nIndex;
+ if (!ReserveKeyFromKeyPool(nIndex, keypool, internal)) {
if (IsLocked()) return false;
WalletBatch batch(*database);
result = GenerateNewKey(batch, internal);
@@ -3703,12 +3702,10 @@ bool CReserveKey::GetReservedKey(CPubKey& pubkey, bool internal)
if (nIndex == -1)
{
CKeyPool keypool;
- pwallet->ReserveKeyFromKeyPool(nIndex, keypool, internal);
- if (nIndex != -1)
- vchPubKey = keypool.vchPubKey;
- else {
+ if (!pwallet->ReserveKeyFromKeyPool(nIndex, keypool, internal)) {
return false;
}
+ vchPubKey = keypool.vchPubKey;
fInternal = keypool.fInternal;
}
assert(vchPubKey.IsValid());
@@ -4038,7 +4035,7 @@ bool CWallet::Verify(std::string wallet_file, bool salvage_wallet, std::string&
return WalletBatch::VerifyDatabaseFile(wallet_path, warning_string, error_string);
}
-CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& path)
+std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name, const fs::path& path)
{
const std::string& walletFile = name;
@@ -4060,10 +4057,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
int64_t nStart = GetTimeMillis();
bool fFirstRun = true;
- // Make a temporary wallet unique pointer so memory doesn't get leaked if
- // wallet creation fails.
- auto temp_wallet = MakeUnique<CWallet>(name, WalletDatabase::Create(path));
- CWallet* walletInstance = temp_wallet.get();
+ std::shared_ptr<CWallet> walletInstance = std::make_shared<CWallet>(name, WalletDatabase::Create(path));
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
if (nLoadWalletRet != DBErrors::LOAD_OK)
{
@@ -4092,6 +4086,8 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
}
}
+ uiInterface.LoadWallet(walletInstance);
+
int prev_version = walletInstance->nWalletVersion;
if (gArgs.GetBoolArg("-upgradewallet", fFirstRun))
{
@@ -4130,8 +4126,8 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
walletInstance->SetMinVersion(FEATURE_HD);
// generate a new master key
- CPubKey masterPubKey = walletInstance->GenerateNewHDMasterKey();
- if (!walletInstance->SetHDMasterKey(masterPubKey)) {
+ CPubKey masterPubKey = walletInstance->GenerateNewSeed();
+ if (!walletInstance->SetHDSeed(masterPubKey)) {
throw std::runtime_error(std::string(__func__) + ": Storing master key failed");
}
hd_upgrade = true;
@@ -4164,10 +4160,10 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
}
walletInstance->SetMinVersion(FEATURE_LATEST);
- // generate a new master key
- CPubKey masterPubKey = walletInstance->GenerateNewHDMasterKey();
- if (!walletInstance->SetHDMasterKey(masterPubKey))
- throw std::runtime_error(std::string(__func__) + ": Storing master key failed");
+ // generate a new seed
+ CPubKey seed = walletInstance->GenerateNewSeed();
+ if (!walletInstance->SetHDSeed(seed))
+ throw std::runtime_error(std::string(__func__) + ": Storing HD seed failed");
// Top up the keypool
if (!walletInstance->TopUpKeyPool()) {
@@ -4304,7 +4300,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
nStart = GetTimeMillis();
{
- WalletRescanReserver reserver(walletInstance);
+ WalletRescanReserver reserver(walletInstance.get());
if (!reserver.reserve()) {
InitError(_("Failed to rescan the wallet during initialization"));
return nullptr;
@@ -4342,7 +4338,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
}
// Register with the validation interface. It's ok to do this after rescan since we're still holding cs_main.
- RegisterValidationInterface(temp_wallet.release());
+ RegisterValidationInterface(walletInstance.get());
walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index fecc2178e4..f1761b0fcf 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -32,11 +32,11 @@
#include <utility>
#include <vector>
-bool AddWallet(CWallet* wallet);
-bool RemoveWallet(CWallet* wallet);
+bool AddWallet(const std::shared_ptr<CWallet>& wallet);
+bool RemoveWallet(const std::shared_ptr<CWallet>& wallet);
bool HasWallets();
-std::vector<CWallet*> GetWallets();
-CWallet* GetWallet(const std::string& name);
+std::vector<std::shared_ptr<CWallet>> GetWallets();
+std::shared_ptr<CWallet> GetWallet(const std::string& name);
//! Default for -keypool
static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
@@ -999,7 +999,22 @@ public:
bool NewKeyPool();
size_t KeypoolCountExternalKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool TopUpKeyPool(unsigned int kpSize = 0);
- void ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal);
+
+ /**
+ * Reserves a key from the keypool and sets nIndex to its index
+ *
+ * @param[out] nIndex the index of the key in keypool
+ * @param[out] keypool the keypool the key was drawn from, which could be the
+ * the pre-split pool if present, or the internal or external pool
+ * @param fRequestedInternal true if the caller would like the key drawn
+ * from the internal keypool, false if external is preferred
+ *
+ * @return true if succeeded, false if failed due to empty keypool
+ * @throws std::runtime_error if keypool read failed, key was invalid,
+ * was not found in the wallet, or was misclassified in the internal
+ * or external keypool
+ */
+ bool ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal);
void KeepKey(int64_t nIndex);
void ReturnKey(int64_t nIndex, bool fInternal, const CPubKey& pubkey);
bool GetKeyFromPool(CPubKey &key, bool internal = false);
@@ -1122,7 +1137,7 @@ public:
static bool Verify(std::string wallet_file, bool salvage_wallet, std::string& error_string, std::string& warning_string);
/* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
- static CWallet* CreateWalletFromFile(const std::string& name, const fs::path& path);
+ static std::shared_ptr<CWallet> CreateWalletFromFile(const std::string& name, const fs::path& path);
/**
* Wallet post-init setup
@@ -1139,17 +1154,17 @@ public:
/* Returns true if HD is enabled */
bool IsHDEnabled() const;
- /* Generates a new HD master key (will not be activated) */
- CPubKey GenerateNewHDMasterKey();
+ /* Generates a new HD seed (will not be activated) */
+ CPubKey GenerateNewSeed();
- /* Derives a new HD master key (will not be activated) */
- CPubKey DeriveNewMasterHDKey(const CKey& key);
+ /* Derives a new HD seed (will not be activated) */
+ CPubKey DeriveNewSeed(const CKey& key);
- /* Set the current HD master key (will reset the chain child index counters)
- Sets the master key's version based on the current wallet version (so the
+ /* Set the current HD seed (will reset the chain child index counters)
+ Sets the seed's version based on the current wallet version (so the
caller must ensure the current wallet version is correct before calling
this function). */
- bool SetHDMasterKey(const CPubKey& key);
+ bool SetHDSeed(const CPubKey& key);
/**
* Blocks until the wallet state is up-to-date to /at least/ the current
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 66a50db15d..4b4460a794 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -756,7 +756,7 @@ void MaybeCompactWalletDB()
return;
}
- for (CWallet* pwallet : GetWallets()) {
+ for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
WalletDatabase& dbh = pwallet->GetDBHandle();
unsigned int nUpdateCounter = dbh.nUpdateCounter;
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index a73d727c0c..3237376f63 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -62,7 +62,7 @@ class CHDChain
public:
uint32_t nExternalChainCounter;
uint32_t nInternalChainCounter;
- CKeyID masterKeyID; //!< master key hash160
+ CKeyID seed_id; //!< seed hash160
static const int VERSION_HD_BASE = 1;
static const int VERSION_HD_CHAIN_SPLIT = 2;
@@ -76,7 +76,7 @@ public:
{
READWRITE(this->nVersion);
READWRITE(nExternalChainCounter);
- READWRITE(masterKeyID);
+ READWRITE(seed_id);
if (this->nVersion >= VERSION_HD_CHAIN_SPLIT)
READWRITE(nInternalChainCounter);
}
@@ -86,7 +86,7 @@ public:
nVersion = CHDChain::CURRENT_VERSION;
nExternalChainCounter = 0;
nInternalChainCounter = 0;
- masterKeyID.SetNull();
+ seed_id.SetNull();
}
};
@@ -99,7 +99,7 @@ public:
int nVersion;
int64_t nCreateTime; // 0 means unknown
std::string hdKeypath; //optional HD/bip32 keypath
- CKeyID hdMasterKeyID; //id of the HD masterkey used to derive this key
+ CKeyID hd_seed_id; //id of the HD seed used to derive this key
CKeyMetadata()
{
@@ -120,7 +120,7 @@ public:
if (this->nVersion >= VERSION_WITH_HDDATA)
{
READWRITE(hdKeypath);
- READWRITE(hdMasterKeyID);
+ READWRITE(hd_seed_id);
}
}
@@ -129,7 +129,7 @@ public:
nVersion = CKeyMetadata::CURRENT_VERSION;
nCreateTime = 0;
hdKeypath.clear();
- hdMasterKeyID.SetNull();
+ hd_seed_id.SetNull();
}
};
diff --git a/test/functional/README.md b/test/functional/README.md
index 21050cc2fa..fdd7c339c5 100644
--- a/test/functional/README.md
+++ b/test/functional/README.md
@@ -20,6 +20,8 @@ don't have test cases for.
- Where possible, try to adhere to [PEP-8 guidelines](https://www.python.org/dev/peps/pep-0008/)
- Use a python linter like flake8 before submitting PRs to catch common style
nits (eg trailing whitespace, unused imports, etc)
+- See [the python lint script](/test/lint/lint-python.sh) that checks for violations that
+ could lead to bugs and issues in the test code.
- Avoid wildcard imports where possible
- Use a module-level docstring to describe what the test is testing, and how it
is testing it.
diff --git a/test/functional/data/rpc_getblockstats.json b/test/functional/data/rpc_getblockstats.json
new file mode 100644
index 0000000000..750abc5c42
--- /dev/null
+++ b/test/functional/data/rpc_getblockstats.json
@@ -0,0 +1,204 @@
+{
+ "blocks": [
+ "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff7f20020000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000",
+ "0000002006226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f1cd16b94f20a8a3dda91027c888025f2ec1a07ddcb2786bdff5916e66c00406f194ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002014341131c18d3b3aa30056a0f7a97c9ac852d3fd0ec9c76f7a25e83c01e7f821bf83574fb606f25c59200c844443201faf923ef5284fd4401f3104a323c601491a4ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03520101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002078616da95299bd42cd8f813c8043816ec5741de466be3162e16bfff471808461f671e694afaf534d37df484f1990fc19a65fc26964b38141b7f8ecf61b8a50241a4ae75affff7f200500000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03530101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020a08613f37d305835a3a1553e77a479eba0f34c06c52e429ece54f5973cd77a7086a1efcaf75f1cd5be2c9deb6a7850225757a2cfc3031a91cc1330b3af4acc891b4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03540101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000203b304fa1ce0505c2366982939ac148d9124c5ac747cc9aea133cea9916484966305de0e8d049f2be65c68d64d2c45746def5a9b4fcb8e298692b53b83b4690241b4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03550101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020fbdf49978ec4f0b23704b6772a614336872587e29c463f375836ffd775248837fed9f3fdfc33f076c6663ae78070fad7263c1e24161f3ee1a4857b8931815e2c1b4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03560101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020c37548b9ca256b9ff17187d4d4309cf3143845b0a5811d3ca5427b2fddf000731a10985dfd473561c070c3527c3fe3941834cf51b3dfbacb501b44c69c9745ce1b4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03570101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020383dd3766c0675440f26370ad62d687e335ea3a650dec9b02fe544107cc1823a13b98696d41562945457d655f4c6921f736068f7a72afd1ad6b335f2857d16631c4ae75affff7f200400000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03580101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000207476dd96d81f53e63934ce28c9e89022e0f24d040ec3c838443e925fc3a2f230a94d0cbcefb4a151191dd7664153944d9eee3b7b46d4ba997f397ed2b72c3afe1c4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03590101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000209e425c73eea16cce98c0d47d6070aca29f0524eab4b97af84c386aa5322dd43055002f097e929bc6ad88ce869968e1b049aab7f6e45a5b869cf4349afd5d43e01c4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000202090e16a514fad40386413a100bbaa4fc14086a8d3501ac64c91fdef922e834a369e409444d0ec496eb0dd9a47f1fe81a7ab974bab28c50a912b994acf13b5f91c4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020777b767e42624c52775b331f19e81ba03be2f51a0608166cd5388c1a47d5e776473570bb9bba553a7db4a9a3083533027c54af1fea3ef6ef67757ef2255d64631c4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002076bb2bf3251a51ec367a42f8584043171a5d53157394cd776ebd017e2982127653d953aca3e2217f56533c043c07b9a926a30672ebce2562f1d06a6dc5044e7b1c4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020e6d7f02292655b73fc1f1958b09633ba07265d71d2a2784060b354cbbf1900202e9c9b02b63170002a94a0c9d8d787e2faa4c074a1ebdeb2855555347321dd101d4ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020d61f077b0ed326e17f0a3d5af3fa876b72b434a252c9c3248d20130ed744287fcb10da470222dd29c7a07e2da7eb25d6499ed3919676df89cc630bd1b23fbb411d4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000205efa9741cf51533ed6e07a97c71768372f53ca9c6df83894d64fe94c718eee23a207441e79ecdcf99ef3326385f5f675e2dea84c85ab8973219c63f92847ed5b1d4ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03600101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020368386b0a0f46b2a2c4648eb9cb5dd1380c4f22e437e0bd49420670993361e5b9026632c2ddbb4b31b3c3118c51e43ea4d78e05c0aca0956278ead26a263d1521d4ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401110101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020dd0a1594bbff6345a3e34f326e5ee605c855f5e0a5c363fc39615a8b1539b736200b51297dbee4aadf9b536cd2afe7617651e0a1d0f0610f436518a2a4dc54621d4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401120101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020f302a1092709dc27a32d7229d391b90824a75828692c4bb2ca8f0ca5c88b3613c2e18797ffe8b367336338f90b2cf8c3f66277eb1e1ddbe18c052977294f10691d4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401130101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000203dcc77aac703a8cd0e799384b74383c1d5f236426f77d516694607fc88fe85581276a20ceb98d02e6355c9dba4312e2fdc9832f4302cc307e1263f2df0aadd6a1e4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401140101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020dfe109704a0b2801aee4232c31fb744145a7c80dd91a7727e16d4057719d5c3730f8296243521d82d96ed75c5af800a722fc9dde2e02af95c8c9822190ba07b21e4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401150101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000201ef9ef2699bc36fd646bb9ba8629644bc98396122f6753710caf0315d7539f751382d3d85f17eb8b42cf17e54baa327886dcf6fa63207e097df8f9b84cc5422f1e4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401160101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020834c91f23cd91b727be08b892f1c1a2f33c1e66d66f35607925fa1be4bca2c25b4145a73b1c71b945f5bb9ede3d8d95c9a3b12a0a81b7b14f440ec5146dd4ec71e4ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401170101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000205743202bf1e543a9be2a59b62be6a5a494511fab96968007b8d7199ea60a524697227ba473ceaf48d4f48ee17f8ee6cd2f1f5ddff03a641642ece240e7872f8f1e4ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401180101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000207469f5c1841bf57275d82db23e5a8f0e8512af1eb10119c238519cdd6cdced34fd96dc659a874b3f5d30fbe6ea421a6b9791dfce8450f8851e4b90d80f0f794e1e4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401190101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020b6338f55fcc473b744d53d675b4a83dcd80ddec9d02ad3323cf1ff50ac0412239d986ec20885d772fdc67803273aaec43871426ac93d3815846a8cd13dea5af11f4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020a19d9edf2d22415cf226b4e1416c8a3097e0af222efac2bfeab15fa1f07b3f24c18580c4004de6d6244a30ce431c4be3ca44731509fc6b11710c792efed5e9191f4ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000208f9f29a27424ec01ce77485617088506ca8faeef69300f0a474ad63ca5d32972d6049609fa3588d6ffab4d9d89a90636ac94c0ca1995f7768163abeb25dbf2bc1f4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020fbd87d530a9ec3835ab579337fd16e512cec6c4779ab4d84e7256b3333dece28de1065c8c3d3d166e057139ac59af6f4f2c0d241b6269bbea6f61c5eff3dba431f4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020dc6ef4f436baab2d6880f242a2588313a2739ac694e30319344045ee318c9524d0ec7fbcaca30ce85392cb03b64015ece769afb50fd07db05c15ec49abf7d71c1f4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020386bf4cbb3708ae6345b9f2459bdd99d07422b05f9b005d2d4d1d3bf87d47359ebb22b3a15c8e94ddd8129527873b9bebfa10c54d11196961376efbcaad3c4681f4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020600e892f12ad82a23ce12684d3ffa0887eab5e3e97804fa651050b23366cc55ef2468e65c3d3cf49650657eb47d0b0b7949c71dcc0922eb824523157b7eff478204ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401200101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002068e4aec52a3f4e44279e3a65cd476237bdfcc2328390bb31b8a903f89ddfa70e8d669f61b469acb31b1d4ecdc238e6616a83a30644a5d06fc2ca1aad6449d09b204ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401210101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020cf2428ae9a5014b910275807f54a8bbbeec47d462f9d284ada60329b4955ff10cf83c44ddde39a709aef54fb302c7f1cb36db8fe7c3befce20dcc3729767518c204ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401220101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000205801eef8cca082407ce4798648c4d3ba0fc4dd2d4459eccfe5300c7960760d16cb3dd78a2f22fb88717a175e45c53d34f970b94ef9f7cd1b6c279294d427d163204ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401230101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002088320983a4bcb95b9f342994c6943c227f3102d3b16282f048ceb8e15748662a52d1207591a0a364bc9245a76e36530f147ec4d1b4e1917676b4071f542c3b19204ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401240101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020acd85b6d8087d3b6bd2a208a2e39b75da459c0e0eb14088075a23a2e043e8a4ed5a1754491f8180d293b42e6c04ec3f82e29c1f2600dc8607616f69a4a464e6e204ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401250101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204873bcb379f78da4497ce1e22f6bfb63537b89c8c522257a7b7bef74e515ed1b6b235faab048fa73a76c68fdbdde6a4ee7ebe0a3b7b23df24ce75dbd2cf49c33214ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401260101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020a87f6d13bae8e2e07996c3316e8e0da6aec7d1aee6b80aa5883018e4d136db3e9a498ff7d322ad93863e0a5318af7e7d0ed683fd2e4ecf523f2b7369106dbe4a214ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401270101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020d9b0618450a51c08f43187c479e20d351f0466464409bb3071dc0af7c51d65498a198cef23dddd2c4b93d9d3288ae922584e221a9ef1ded3dba5a2ad494d9237214ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401280101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020167dff31847b8dcad472bb6bb7d0af53b245f0f1d4c9f83d4ce14a0f05d42d7f0f2638ffc0e6896230f28df1865ef133dccb1f027545c6a1177dffd1fecf8a01214ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401290101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000208236c04424573692504e777e179b9247e54622b118239311413812f13cefbf6e39a639143f599dc76208b2014de12a364716df2918af9186453e3676dca743d7214ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020fab7b55aeb59f63315dbc10784c55e55635a7600cc4f3b94a00003007e7fc90b4af016248e9908882f8a7f0bd8743c8da82da119446e8b02e4d3b8d1d938a3aa214ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020794b4160d8fd4ebe7611d0fc9d3e04f3038a485669f74075aa153852ed181121c577f4c0b7151f6d78a16e3c21ab291b53ced8a5c4f05a22caf24a25ed029d56224ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204a8acdb549d2ed922360ae0e81de6c913c3fd84b0de51abacbf97162a99f7c26c656b252d3259c33ffc7e5d403843accc6ace9b7e60e911e2347a6a0b0abd122224ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020dee6d00c7058b3422e4273c98c16181e04ea93116496a8442de546c2ee9fd86b550013f39e004b3829dc3717b17fcfedc87de9450315fcca540963119cb264c1224ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000202ebca471f5fb2226a790233c3d0bc323f73d935872f3e15b66bd5fdcb822101d7b68788ed61d3fb8cb746f627e09db2fc09d8a07672747709d92ae400e053e78224ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020ee500470fc1c71a82f2cbb9f8d5723bcdf57b8051fc458a8dbd8d0dbf60d0e40d1a0be0e50f3312d4830e3900186e5a6760d44006c164b4f0758218ef2b2de8e224ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401300101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000205057e8d8a7451d79325851dc8e0f4dfdb1dfaaab637509d9e61f0e064af5ee5c185221c53c0cf43261b3c238c0e8117da5d6ac60085615f7a3d8027726cb2143224ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401310101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000200907f01d9c5c872296796ca77feb62eb414cc080e13a93e59e181528bc19c336eaabacb1ebcbd20b26f6bacdc712ffe17d4c8131e7f99b9cac309c0683737c04234ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401320101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000209bd6a4ec962d9e6199c0a2f39481a7ecc322fedbd2320cbe7dc984c6ab958421fe7a5c7f2513a3c3de9ddf7b211f5bfe85675b31183c4bb98ae79ab28cd055ac234ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401330101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000202b8a6381b7c9476fd77be379a929863db6b7edd9858d6eca0f68a430dc87cc3a9c6c8b34bfadfdacbe95cb1d4ae5ce4e4f4ccf0300171d7a91cdc97f620c7b37234ae75affff7f200400000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401340101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000203d3e9a0b4decf12b4402a2178b60599311c8a9c7d50ece365a61ca29530da7056754ddf7d77a11cc8ce680a74fae01d851bda024fc9c51712c55b4a190caef24234ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401350101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002067fa05082d4f7a29a3985f30798940cd854c76a2b20e9560b2047f7753193f71ac61b8df17a8a63f099c8f55869301fc2a0aa37355a4a2f89078135ee72a1362234ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401360101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020249684272865fec3ad62ecb73dfd930500e32e475306c9e5d4b6d545e3687b0a48deaeebfafa213f0a560994b3f4000d5e2b93951d7e5be40073503877292dc7234ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401370101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204671db1df91098669bb03c3e8504d432da99853601366c7de7585bb8f23a6e1e2996a16c11a0f9ae87d937f566c8bbd919040528c1bf8dae4e22a8f0ac5f935a244ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401380101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000203046500cabfee552ed114c505279cd75c28faa811adcb5010c53c14df5de3216d265321a4168c70fff1c85fd83bd976cc03c8c1fb6567398cc24053e343ad137244ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401390101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020591533cf8dd1fa1872c7e6d62ef714b28886f38f7921ee614e13b748eaf923282a96287277f18b1113a9c3ac384fd7b43bccd0e45114908ca5396a76cbd736fd244ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000205286b5747d0244a55e1dce435fdbb9f300d7138fff3b16767bc09196eb00256c6795e3f372a2d5d137244a4fd72fd799e8de913f868f22269eaa628d7d2970a1244ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000209649b55f6a5ff0d5db73aeb7089fcce605fb9dd23971e577b73747ffab586f4edf84581240223e2d8912a6eca049e06aa46ddbf271af08e9ac9605505311418b244ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020fe7ff82c11ad3a3db3dc11a03a67e0b86b727d232c80f37209b028bc2689296c0da76fb756e1c9833f38b198cfe843ab820fbc0c38e30f8f858f6ffdbd64e834244ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020c02e6109b6aaf6643cac109ad5b5be7f7ec47c7993335bdceea6e0e490ae9067eb1fcee49ecc40a61477f934e3b9821f2cc7ada429fcca2cd645866742854c40254ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020956c46fce0adfc8a30d91c7b7f328f17c2a90771083884c4fdb7f24640598f6fa69c4e5971bd3b6cdc7e3ee98e03a969b28c3220fdc685cc2eb77293763ca4ba254ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000203eec7d0ea9c539f47e684eec9dba900e27c805b8200f237924c7df8065957726c83caf659fa341bf45f733a92cf76daf2cfb6bccbf969a2753f5f7d9cda4bd1e254ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401400101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000203c022b42283bf651ee4d536fe71b7e5382e9783d4a85f8bc159f00b97f16d82d312ac4f89f1b1496de576811f2ff17de44b512db0beddae59e030e2ce3eba4df254ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401410101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000205da9709dea4bea4f3229d0eed439a4820a0e817f9fbbcd8bb355cd8052702973403358080a2881b823a740f58b6b0c922b42189e06326478cc33390f2c704743254ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401420101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020447c49f664916cc13a839e27f7cbe0b09dea990dec71dd479b537ecfb771c7159ae6241727c2645ce00817909ba97d43447fe2e146bce55b7dccd5bcd27d2e3d254ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401430101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020ae3b214b1495953eea3b99af7ade4b8d22d615d598dd6c790c6576d6453ef35d37fbd3446f8431f00052f278c3e0359beba54a2f5064bc6be4990478fcf4e086264ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401440101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204cc68f9f571f59145e1f7505550d56da13a797fbc7e5a178dd7f6f9241d91f007f2400f7aa1b32b30bf869e4da86f75eaf2baae182efc45c42c6245f06aba675264ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401450101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002096d55714a83c3d030cc72141eac3577b8a394b8366b2c93354fcecdafeab025022f5e26de7e4eba3f8e4a09f243b55ea6f08bfd013e2051cf1d5df20dcb3331b264ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401460101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000202ccf49665bd46e4915dcc9221f5fc72124bb73fb11fed8869dc5862a47950c0d654693a1d86098212d68fa9a27f9df0faafea4aecebd8b203f2ab8f3f0b86196264ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401470101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000205d0be5aea546eab7734cbee757ea5f4983ab3a3f202323c1c88590bdbc8b561974cb0de6549bfdec92322ad53d8a4192433edab0e33a10e7561d2e27c7759f8a264ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401480101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020fc3d70d4f690d7d7da90b1c832a51c2a92940cdd9fccda6a909c7256ad567160550e1089b48fe75f0f1e6f712cc2a1d4aad384a4ceacf1c71576420fe8e7de46264ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401490101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020995ab1f2293e3aa1e7bef418919bdce60032e89e60223b8c12b17488c50af83b3a360b4f89551aa0ced646a6210b0c3d3f7d0464faa248b9d252c89615babc9f274ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020e02dd5e1201ebe7ef453e77df3021cffde1b5447b9eced017963489e005ac247e1f2b80e91180cd9744c3e126eb8a0fb34ced45587da6b0fa9fd1c6946f049bf274ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002081b265800d61feb37525c58aacc7e6d32cfc6b6579784f9952dca51c3addeb37da900ae4ec1b2075056001a361c0fc8f9ac1ca018bde2a2bd8fc587424dfe18f274ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000207daba0dc6fccc067a19dec46770d1443fc715b50540242ff26073a6748bcd9583804c315b783d4f9aac4dc8f109fa60bcbf1c3cf98a7e1e593fcb969e88aafae274ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204a35ab2d9c4656c4992d2445ee566e4f5cd0468358292c94839de2b270ba0628de9148db03da59ca2eb727a4f7a03f2b9ee1e4045f37bdaa4b75a89de56b63ee274ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020215ed7b31d118a45a06407133e41f3f9d25c913ff98f3e798144f981d9145305266efc9274f7c836aa0f8b831732aec2c1d85c5bb9176af4c889a707cca380fc274ae75affff7f200400000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020425321a1f12ed4613b63b3cc5b4c7674242c3de67ea86984f2d9bb2766f6220a5c460ce6840832b7ef05f206c5d255bc2d8ea83753a7f5ef5c0bf3dbcbc7c74a284ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401500101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204e088cfd312091bf589f0fc24131dba20ed83f716530a7b033356e9ec803be23a73c4af5b64fc631d20aa1f646c7c61c4cc5d4be6e2fa29570030d72219726a0284ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401510101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204287a2bf40300e39b45d6667d6e17abba37d98c41efc7023fd21b643fb2f6b76d915d10e1f9e224d3bfdf5203da57173f0b8d8eedc92ed9ff23372927e86073b284ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401520101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002083137929ca902f409a1f35385b4d31e0f5163d488d71b00ade724d7831986a280a187c13fe0db45aed5fa4f5089d544a617da9f4f80fe6ce1d0711b228f3a6bd284ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401530101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020b38c074d78cbcc8bbbf20c48e30639c2dcf444488efee59f5aa01c48322a30418009c11df7e14de6a6d0d72cc22f20ff5fdba3a7dbe409409ff92b1302340fb8284ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401540101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020a6865148220c7f5ac3259f57fa381676d6be5fdab56eed8e060808fcce4118492476fe6d5ecc681e7a18c20a04239143de1c2cddefbb08f15153b8e9b0c22f62284ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401550101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020ae146263f4087106b8c51ffb5cdddb03a4e593ea1a22a8f6580eaa374185126db2187dbe694a1b17b7c5664115307965407274c25bf6ae02049817685f923256294ae75affff7f200600000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401560101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020718abe22705f33134812b56d04c129d453da890e27caf6e77d2bfb3f9be460083634f35fc8ea4a29b0f30d6c6b4926455a31de62d2f763bc95c8cd1a7a425599294ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401570101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002084537c50520f4e6b0173926320c3193f6b4259c9a724fe202337d3d5cf7da70b1104e1d6f25c411165a856a0bfdd5ddbe168238425c05271962aa6e5ebb676fb294ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401580101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204bae65b948c9790468cfc8fbf78a81e7aec5407dbab18c18ef1ab37a13f0c257792cd1246dac5ce265a8439e539db1aebe4776535d422315bac8e57a51605aa6294ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401590101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000201e68985b2a15920524c3c2da77354c0ccfb202c3ab4005128eb2743aa33f0a5b0527a624a6d1f808c896d8cd1552c251a4ae5310e6c62493977b0965d17f580d294ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020ab1d90854505caa1ee748c1987f4cb6674844b84d17224bc3983fdd6e44a930b2edf3e5a90be7a9080ad15014ce796b38b6c19ddd3754443243fc277bcd2368a294ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002062242f316efa083c17e2173d9f9831afc1465f3fe84431d8e52fec71ae358b243e29246e0db770708987f2cff380920321636926d9c66c2c808d2d5f0ed27d672a4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020258c1a9b0ca17819d8d7fea5178e9c72c2e7c6769696f70098e0d5d2a9dc0e5cf039f5f686d727c6158ef5405ee8794ec2f89c641093a1dff0f5240263a441bc2a4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020434ce26cddae99571a1d663419d715f88e6ff0e413c45f21c44b1991d041fd2745534db221054e2233052aaffe7d7232a91b3f0918c14eac74b2f704b37bfb8e2a4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020ec94475f112ea37dddd84f066e61446b431d28d2d9b6fbb336d16295e7eece52f1dc01abb3b27e71d8a25c3ed2d6fbbc5900bf954738ed63d57689ba5e68f6532a4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000206188cca18a2be3b7f0b500a724f1b73312873488f04c5082abd81ca0b2250a75ec0efb2fa994ad23e1f39416e69976e66fc4ef9f101bd4f60fcee1f8c45a2b802a4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401600101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000202384b91bd0bfb1385ef42bda9b2fa43930aa8889214bb14f63c61a74f380dc7f9d547f2925ad39b9161fa55b9cd258463fd058234778a7c7b3061113d64179812a4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401610101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204c266a3008c3bd95ae4bc8228bf878595cabf76cc2ef3fed32936777fe37833a1a13ea016868b2352a8d6d1eb35d0aee784cef06ed50655b8d84c089324351df2b4ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401620101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020ab2c78d1249de8482cf26bfb1616ac04f7b8404eafcae3e0654f398943fd41571b4d7549862be0b06ed1408ddc3e7c01b07af24c203a18fe9744e214b14d2d652b4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401630101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002031aa0fc5e0242a9c9d91024b6b7e67544da72c4773537f881ee5caacd45a3c38c650ff5fa0ffd080b3e5f9752527b718e8c6b731467028e14b0b009d4e7406ee2b4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401640101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000200418c57609fc6ea3f24f569dc3afe163538a6aab940fe8c3d73c72cd781221380482c6f8ef2c19429da2f7a842bb811496aa86247c55f7ecb3337718b694d9472b4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401650101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204f36abaf10d6a8b3113103f3413475db0640c89a39f02a718e8bd2190fe87f1d6ffaf2b9fdbed67ebae4b36c97f9582814c99c90d0b5123f14da4861bf3e4f742b4ae75affff7f200100000002020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401660101ffffffff02b000062a01000000232102f6869601b2b9980b07fc047e309c1fc1433e08c5bf0498115c5c0e117ef59bfdac0000000000000000266a24aa21a9ed5896cd6a40cd126b09e317cbd179f39e2bcef2f9d423751d980258396416e671012000000000000000000000000000000000000000000000000000000000000000000000000002000000011cd16b94f20a8a3dda91027c888025f2ec1a07ddcb2786bdff5916e66c00406f0000000048473044022046d00465c4508cfd02fcb878b19d120e28be28e40658b1f15458828891ed1541022036aac054f36a42666dfb7b42a20506315a0b72232ce7704406e23c7a9515178701feffffff0200286bee0000000017a91481ddd4a9708ba8088cdcfeab9583ede8d83a298c8750bb9a3b0000000017a91484e16967722289584257803688aae36cd64480688765000000",
+ "00000020cc7c39992f2dae21e0ebd958f6ba77a6d0bcc568e044b9b61ca4d77536a4214e7b4ade79dd733ea72d97993aaac27f2263b91b1500467350ff35ea40c2850d392b4ae75affff7f200100000004020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401670101ffffffff0230d0062a01000000232102f58ba54b2d51c4e2a6096f9d266261b45f1026a86ba88c29ed8070dfe3f5ec6bac0000000000000000266a24aa21a9edb824d92cb231c2366f0726aedf8bfc2705239a40ae6b10a106534e8b5395a09d01200000000000000000000000000000000000000000000000000000000000000000000000000200000000010196bac2a0f6212b8e5710f8c7214dd32c393d38d20b7703cf0b7b25276bb6ab8001000000171600144f8a6c8d4c6c309b1e2b725b7496859e172ea367feffffff02781ef5050000000017a9149f00bafb542049fe32d532b0ea7494ebb7ae41398750daa4350000000017a9147794e6dc43de332ca7a095e582478c331446686d8702483045022100bd85ed3954f1151c2fde32c4021a32c96d7defa4a57c14b1a056be9b361a8e49022054947bf6fdb535c46cbee62efc1262cc0389a6eaa19afbcfa98fb1fb30c3ef230121031b2371df07fb88dddf590b246dc74defc265fdbfe258e4b168250859b806f5ce660000000200000001bf83574fb606f25c59200c844443201faf923ef5284fd4401f3104a323c601490000000049483045022100d1c4b09b488f6375ee4540a531a13b5549e88e2459bd88c84867e293c54862740220222e8af70c8d8b1139c2a7b616d9132bde94244edca7eee3c7a783b12839dadc01feffffff0250196bee0000000017a91490e5e33cfedf18d5cf911d6f853770c62e1f5d028700ca9a3b0000000017a91422311ee58518edf3a2289012461dc66bc8739d2687660000000200000000010196bac2a0f6212b8e5710f8c7214dd32c393d38d20b7703cf0b7b25276bb6ab800000000017160014b81faaafa52f7723f539f8d595147b1a112b38ecfeffffff0208bd9a3b0000000017a9146b2e611708a94d9c674dd08c7c4c1fbb97bcdba987005ed0b20000000017a914933a20f07bab1d8f341f391819466a271f0cfd648702483045022100dfa8b0052c7825e6abcea05d10fc82550a8d6538681ffc8188d48ba789e4d9b40220697371cdf527a6ecd1887f87da3c87dca3419e4a1aa2683e5c4e035199084d100121021cc37c2ec090f30ea0b49508ae8a7d65d9759903932666da56671c1faa445d5d53000000"
+ ],
+ "mocktime": 1525107225,
+ "stats": [
+ {
+ "avgfee": 0,
+ "avgfeerate": 0,
+ "avgtxsize": 0,
+ "blockhash": "1d7fe80f19d28b8e712af0399ac84006db753441f3033111b3a8d610afab364f",
+ "height": 101,
+ "ins": 0,
+ "maxfee": 0,
+ "maxfeerate": 0,
+ "maxtxsize": 0,
+ "medianfee": 0,
+ "medianfeerate": 0,
+ "mediantime": 1525107242,
+ "mediantxsize": 0,
+ "minfee": 0,
+ "minfeerate": 0,
+ "mintxsize": 0,
+ "outs": 2,
+ "subsidy": 5000000000,
+ "swtotal_size": 0,
+ "swtotal_weight": 0,
+ "swtxs": 0,
+ "time": 1525107243,
+ "total_out": 0,
+ "total_size": 0,
+ "total_weight": 0,
+ "totalfee": 0,
+ "txs": 1,
+ "utxo_increase": 2,
+ "utxo_size_inc": 173
+ },
+ {
+ "avgfee": 3760,
+ "avgfeerate": 20,
+ "avgtxsize": 187,
+ "blockhash": "4e21a43675d7a41cb6b944e068c5bcd0a677baf658d9ebe021ae2d2f99397ccc",
+ "height": 102,
+ "ins": 1,
+ "maxfee": 3760,
+ "maxfeerate": 20,
+ "maxtxsize": 187,
+ "medianfee": 3760,
+ "medianfeerate": 20,
+ "mediantime": 1525107242,
+ "mediantxsize": 187,
+ "minfee": 3760,
+ "minfeerate": 20,
+ "mintxsize": 187,
+ "outs": 4,
+ "subsidy": 5000000000,
+ "swtotal_size": 0,
+ "swtotal_weight": 0,
+ "swtxs": 0,
+ "time": 1525107243,
+ "total_out": 4999996240,
+ "total_size": 187,
+ "total_weight": 748,
+ "totalfee": 3760,
+ "txs": 2,
+ "utxo_increase": 3,
+ "utxo_size_inc": 234
+ },
+ {
+ "avgfee": 18960,
+ "avgfeerate": 109,
+ "avgtxsize": 228,
+ "blockhash": "22d9b8b9c2a37c81515f3fc84f7241f6c07dbcea85ef16b00bcc33ae400a030f",
+ "height": 103,
+ "ins": 3,
+ "maxfee": 49800,
+ "maxfeerate": 300,
+ "maxtxsize": 248,
+ "medianfee": 3760,
+ "medianfeerate": 20,
+ "mediantime": 1525107243,
+ "mediantxsize": 248,
+ "minfee": 3320,
+ "minfeerate": 20,
+ "mintxsize": 188,
+ "outs": 8,
+ "subsidy": 5000000000,
+ "swtotal_size": 496,
+ "swtotal_weight": 1324,
+ "swtxs": 2,
+ "time": 1525107243,
+ "total_out": 9999939360,
+ "total_size": 684,
+ "total_weight": 2076,
+ "totalfee": 56880,
+ "txs": 4,
+ "utxo_increase": 5,
+ "utxo_size_inc": 380
+ }
+ ]
+} \ No newline at end of file
diff --git a/test/functional/feature_help.py b/test/functional/feature_help.py
index fd4a72f628..d38275a9ca 100755
--- a/test/functional/feature_help.py
+++ b/test/functional/feature_help.py
@@ -36,6 +36,17 @@ class HelpTest(BitcoinTestFramework):
output = self.nodes[0].process.stdout.read()
assert b'version' in output
self.log.info("Version text received: {} (...)".format(output[0:60]))
+
+ # Test that arguments not in the help results in an error
+ self.log.info("Start bitcoind with -fakearg to make sure it does not start")
+ self.nodes[0].start(extra_args=['-fakearg'], stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+ # Node should exit immediately and output an error to stderr
+ ret_code = self.nodes[0].process.wait(timeout=1)
+ assert_equal(ret_code, 1)
+ output = self.nodes[0].process.stderr.read()
+ assert b'Error parsing command line arguments' in output
+ self.log.info("Error message received: {} (...)".format(output[0:60]))
+
# Clean up TestNode state
self.nodes[0].running = False
self.nodes[0].process = None
diff --git a/test/functional/feature_includeconf.py b/test/functional/feature_includeconf.py
index 9ccb89af43..9a7a0ca103 100755
--- a/test/functional/feature_includeconf.py
+++ b/test/functional/feature_includeconf.py
@@ -41,14 +41,9 @@ class IncludeConfTest(BitcoinTestFramework):
subversion = self.nodes[0].getnetworkinfo()["subversion"]
assert subversion.endswith("main; relative)/")
- self.log.info("-includeconf cannot be used as command-line arg. subversion should still end with 'main; relative)/'")
+ self.log.info("-includeconf cannot be used as command-line arg")
self.stop_node(0)
-
- self.start_node(0, extra_args=["-includeconf=relative2.conf"])
-
- subversion = self.nodes[0].getnetworkinfo()["subversion"]
- assert subversion.endswith("main; relative)/")
- self.stop_node(0, expected_stderr="warning: -includeconf cannot be used from commandline; ignoring -includeconf=relative2.conf")
+ self.nodes[0].assert_start_raises_init_error(extra_args=["-includeconf=relative2.conf"], expected_msg="Error parsing command line arguments: -includeconf cannot be used from commandline; -includeconf=relative2.conf")
self.log.info("-includeconf cannot be used recursively. subversion should end with 'main; relative)/'")
with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "a", encoding="utf8") as f:
@@ -59,8 +54,18 @@ class IncludeConfTest(BitcoinTestFramework):
assert subversion.endswith("main; relative)/")
self.stop_node(0, expected_stderr="warning: -includeconf cannot be used from included files; ignoring -includeconf=relative2.conf")
+ self.log.info("-includeconf cannot contain invalid arg")
+ with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "w", encoding="utf8") as f:
+ f.write("foo=bar\n")
+ self.nodes[0].assert_start_raises_init_error(expected_msg="Error reading configuration file: Invalid configuration value foo")
+
+ self.log.info("-includeconf cannot be invalid path")
+ os.remove(os.path.join(self.options.tmpdir, "node0", "relative.conf"))
+ self.nodes[0].assert_start_raises_init_error(expected_msg="Error reading configuration file: Failed to include configuration file relative.conf")
+
self.log.info("multiple -includeconf args can be used from the base config file. subversion should end with 'main; relative; relative2)/'")
with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "w", encoding="utf8") as f:
+ # Restore initial file contents
f.write("uacomment=relative\n")
with open(os.path.join(self.options.tmpdir, "node0", "bitcoin.conf"), "a", encoding='utf8') as f:
diff --git a/test/functional/p2p_invalid_tx.py b/test/functional/p2p_invalid_tx.py
index a12c1d6023..3fed872ccc 100755
--- a/test/functional/p2p_invalid_tx.py
+++ b/test/functional/p2p_invalid_tx.py
@@ -79,7 +79,7 @@ class InvalidTxRequestTest(BitcoinTestFramework):
self.reconnect_p2p(num_connections=2)
self.log.info('Test orphan transaction handling ... ')
- # Create a root transaction that we withold until all dependend transactions
+ # Create a root transaction that we withhold until all dependend transactions
# are sent out and in the orphan cache
SCRIPT_PUB_KEY_OP_TRUE = b'\x51\x75' * 15 + b'\x51'
tx_withhold = CTransaction()
@@ -137,6 +137,13 @@ class InvalidTxRequestTest(BitcoinTestFramework):
wait_until(lambda: 1 == len(node.getpeerinfo()), timeout=12) # p2ps[1] is no longer connected
assert_equal(expected_mempool, set(node.getrawmempool()))
+ # restart node with sending BIP61 messages disabled, check that it disconnects without sending the reject message
+ self.log.info('Test a transaction that is rejected, with BIP61 disabled')
+ self.restart_node(0, ['-enablebip61=0','-persistmempool=0'])
+ self.reconnect_p2p(num_connections=1)
+ node.p2p.send_txs_and_test([tx1], node, success=False, expect_disconnect=True)
+ # send_txs_and_test will have waited for disconnect, so we can safely check that no reject has been received
+ assert_equal(node.p2p.reject_code_received, None)
if __name__ == '__main__':
InvalidTxRequestTest().main()
diff --git a/test/functional/rpc_getblockstats.py b/test/functional/rpc_getblockstats.py
new file mode 100755
index 0000000000..060a2373b1
--- /dev/null
+++ b/test/functional/rpc_getblockstats.py
@@ -0,0 +1,180 @@
+#!/usr/bin/env python3
+# Copyright (c) 2017-2017 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#
+# Test getblockstats rpc call
+#
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ assert_raises_rpc_error,
+)
+import json
+import os
+import time
+
+TESTSDIR = os.path.dirname(os.path.realpath(__file__))
+
+class GetblockstatsTest(BitcoinTestFramework):
+
+ start_height = 101
+ max_stat_pos = 2
+ STATS_NEED_TXINDEX = [
+ 'avgfee',
+ 'avgfeerate',
+ 'maxfee',
+ 'maxfeerate',
+ 'medianfee',
+ 'medianfeerate',
+ 'minfee',
+ 'minfeerate',
+ 'totalfee',
+ 'utxo_size_inc',
+ ]
+
+ def add_options(self, parser):
+ parser.add_option('--gen-test-data', dest='gen_test_data',
+ default=False, action='store_true',
+ help='Generate test data')
+ parser.add_option('--test-data', dest='test_data',
+ default='data/rpc_getblockstats.json',
+ action='store', metavar='FILE',
+ help='Test data file')
+
+ def set_test_params(self):
+ self.num_nodes = 2
+ self.extra_args = [['-txindex'], ['-paytxfee=0.003']]
+ self.setup_clean_chain = True
+
+ def get_stats(self):
+ return [self.nodes[0].getblockstats(hash_or_height=self.start_height + i) for i in range(self.max_stat_pos+1)]
+
+ def generate_test_data(self, filename):
+ mocktime = time.time()
+ self.nodes[0].generate(101)
+
+ self.nodes[0].sendtoaddress(address=self.nodes[1].getnewaddress(), amount=10, subtractfeefromamount=True)
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ self.nodes[0].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=10, subtractfeefromamount=True)
+ self.nodes[0].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=10, subtractfeefromamount=False)
+ self.nodes[1].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=1, subtractfeefromamount=True)
+ self.sync_all()
+ self.nodes[0].generate(1)
+
+ self.expected_stats = self.get_stats()
+
+ blocks = []
+ tip = self.nodes[0].getbestblockhash()
+ blockhash = None
+ height = 0
+ while tip != blockhash:
+ blockhash = self.nodes[0].getblockhash(height)
+ blocks.append(self.nodes[0].getblock(blockhash, 0))
+ height += 1
+
+ to_dump = {
+ 'blocks': blocks,
+ 'mocktime': int(mocktime),
+ 'stats': self.expected_stats,
+ }
+ with open(filename, 'w') as f:
+ json.dump(to_dump, f, sort_keys=True, indent=2)
+
+ def load_test_data(self, filename):
+ with open(filename, 'r') as f:
+ d = json.load(f)
+ blocks = d['blocks']
+ mocktime = d['mocktime']
+ self.expected_stats = d['stats']
+
+ # Set the timestamps from the file so that the nodes can get out of Initial Block Download
+ self.nodes[0].setmocktime(mocktime)
+ self.nodes[1].setmocktime(mocktime)
+
+ for b in blocks:
+ self.nodes[0].submitblock(b)
+
+ def run_test(self):
+ test_data = os.path.join(TESTSDIR, self.options.test_data)
+ if self.options.gen_test_data:
+ self.generate_test_data(test_data)
+ else:
+ self.load_test_data(test_data)
+
+ self.sync_all()
+ stats = self.get_stats()
+ expected_stats_noindex = []
+ for stat_row in stats:
+ expected_stats_noindex.append({k: v for k, v in stat_row.items() if k not in self.STATS_NEED_TXINDEX})
+
+ # Make sure all valid statistics are included but nothing else is
+ expected_keys = self.expected_stats[0].keys()
+ assert_equal(set(stats[0].keys()), set(expected_keys))
+
+ assert_equal(stats[0]['height'], self.start_height)
+ assert_equal(stats[self.max_stat_pos]['height'], self.start_height + self.max_stat_pos)
+
+ for i in range(self.max_stat_pos+1):
+ self.log.info('Checking block %d\n' % (i))
+ assert_equal(stats[i], self.expected_stats[i])
+
+ # Check selecting block by hash too
+ blockhash = self.expected_stats[i]['blockhash']
+ stats_by_hash = self.nodes[0].getblockstats(hash_or_height=blockhash)
+ assert_equal(stats_by_hash, self.expected_stats[i])
+
+ # Check with the node that has no txindex
+ stats_no_txindex = self.nodes[1].getblockstats(hash_or_height=blockhash, stats=list(expected_stats_noindex[i].keys()))
+ assert_equal(stats_no_txindex, expected_stats_noindex[i])
+
+ # Make sure each stat can be queried on its own
+ for stat in expected_keys:
+ for i in range(self.max_stat_pos+1):
+ result = self.nodes[0].getblockstats(hash_or_height=self.start_height + i, stats=[stat])
+ assert_equal(list(result.keys()), [stat])
+ if result[stat] != self.expected_stats[i][stat]:
+ self.log.info('result[%s] (%d) failed, %r != %r' % (
+ stat, i, result[stat], self.expected_stats[i][stat]))
+ assert_equal(result[stat], self.expected_stats[i][stat])
+
+ # Make sure only the selected statistics are included (more than one)
+ some_stats = {'minfee', 'maxfee'}
+ stats = self.nodes[0].getblockstats(hash_or_height=1, stats=list(some_stats))
+ assert_equal(set(stats.keys()), some_stats)
+
+ # Test invalid parameters raise the proper json exceptions
+ tip = self.start_height + self.max_stat_pos
+ assert_raises_rpc_error(-8, 'Target block height %d after current tip %d' % (tip+1, tip),
+ self.nodes[0].getblockstats, hash_or_height=tip+1)
+ assert_raises_rpc_error(-8, 'Target block height %d is negative' % (-1),
+ self.nodes[0].getblockstats, hash_or_height=-1)
+
+ # Make sure not valid stats aren't allowed
+ inv_sel_stat = 'asdfghjkl'
+ inv_stats = [
+ [inv_sel_stat],
+ ['minfee' , inv_sel_stat],
+ [inv_sel_stat, 'minfee'],
+ ['minfee', inv_sel_stat, 'maxfee'],
+ ]
+ for inv_stat in inv_stats:
+ assert_raises_rpc_error(-8, 'Invalid selected statistic %s' % inv_sel_stat,
+ self.nodes[0].getblockstats, hash_or_height=1, stats=inv_stat)
+
+ # Make sure we aren't always returning inv_sel_stat as the culprit stat
+ assert_raises_rpc_error(-8, 'Invalid selected statistic aaa%s' % inv_sel_stat,
+ self.nodes[0].getblockstats, hash_or_height=1, stats=['minfee' , 'aaa%s' % inv_sel_stat])
+
+ assert_raises_rpc_error(-8, 'One or more of the selected stats requires -txindex enabled',
+ self.nodes[1].getblockstats, hash_or_height=self.start_height + self.max_stat_pos)
+
+ # Mainchain's genesis block shouldn't be found on regtest
+ assert_raises_rpc_error(-5, 'Block not found', self.nodes[0].getblockstats,
+ hash_or_height='000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f')
+
+if __name__ == '__main__':
+ GetblockstatsTest().main()
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index b842e6ef4e..75a8986793 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -130,9 +130,11 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self.options.bitcoind = os.getenv("BITCOIND", default=config["environment"]["BUILDDIR"] + '/src/bitcoind' + config["environment"]["EXEEXT"])
self.options.bitcoincli = os.getenv("BITCOINCLI", default=config["environment"]["BUILDDIR"] + '/src/bitcoin-cli' + config["environment"]["EXEEXT"])
- os.environ['PATH'] = config['environment']['BUILDDIR'] + os.pathsep + \
- config['environment']['BUILDDIR'] + os.path.sep + "qt" + os.pathsep + \
- os.environ['PATH']
+ os.environ['PATH'] = os.pathsep.join([
+ os.path.join(config['environment']['BUILDDIR'], 'src'),
+ os.path.join(config['environment']['BUILDDIR'], 'src', 'qt'),
+ os.environ['PATH']
+ ])
# Set up temp directory and start logging
if self.options.tmpdir:
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index dfa8c33728..65e4c0817e 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -135,6 +135,7 @@ BASE_SCRIPTS = [
'wallet_resendwallettransactions.py',
'wallet_fallbackfee.py',
'feature_minchainwork.py',
+ 'rpc_getblockstats.py',
'p2p_fingerprint.py',
'feature_uacomment.py',
'p2p_unrequested_blocks.py',
diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py
index 01d27dabe7..ba420ab2a6 100755
--- a/test/functional/wallet_dump.py
+++ b/test/functional/wallet_dump.py
@@ -36,10 +36,10 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
addr_keypath = comment.split(" addr=")[1]
addr = addr_keypath.split(" ")[0]
keypath = None
- if keytype == "inactivehdmaster=1":
+ if keytype == "inactivehdseed=1":
# ensure the old master is still available
assert(hd_master_addr_old == addr)
- elif keytype == "hdmaster=1":
+ elif keytype == "hdseed=1":
# ensure we have generated a new hd master key
assert(hd_master_addr_old != addr)
hd_master_addr_ret = addr
diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py
index 97a945721f..86abe0ca99 100755
--- a/test/functional/wallet_hd.py
+++ b/test/functional/wallet_hd.py
@@ -29,7 +29,8 @@ class WalletHDTest(BitcoinTestFramework):
connect_nodes_bi(self.nodes, 0, 1)
# Make sure we use hd, keep masterkeyid
- masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid']
+ masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
+ assert_equal(masterkeyid, self.nodes[1].getwalletinfo()['hdmasterkeyid'])
assert_equal(len(masterkeyid), 40)
# create an internal key
@@ -54,6 +55,7 @@ class WalletHDTest(BitcoinTestFramework):
hd_add = self.nodes[1].getnewaddress()
hd_info = self.nodes[1].getaddressinfo(hd_add)
assert_equal(hd_info["hdkeypath"], "m/0'/0'/"+str(i)+"'")
+ assert_equal(hd_info["hdseedid"], masterkeyid)
assert_equal(hd_info["hdmasterkeyid"], masterkeyid)
self.nodes[0].sendtoaddress(hd_add, 1)
self.nodes[0].generate(1)
@@ -83,6 +85,7 @@ class WalletHDTest(BitcoinTestFramework):
hd_add_2 = self.nodes[1].getnewaddress()
hd_info_2 = self.nodes[1].getaddressinfo(hd_add_2)
assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/"+str(i)+"'")
+ assert_equal(hd_info_2["hdseedid"], masterkeyid)
assert_equal(hd_info_2["hdmasterkeyid"], masterkeyid)
assert_equal(hd_add, hd_add_2)
connect_nodes_bi(self.nodes, 0, 1)
@@ -122,9 +125,9 @@ class WalletHDTest(BitcoinTestFramework):
assert_equal(keypath[0:7], "m/0'/1'")
# Generate a new HD seed on node 1 and make sure it is set
- orig_masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid']
+ orig_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
self.nodes[1].sethdseed()
- new_masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid']
+ new_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
assert orig_masterkeyid != new_masterkeyid
addr = self.nodes[1].getnewaddress()
assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], 'm/0\'/0\'/0\'') # Make sure the new address is the first from the keypool
@@ -134,16 +137,16 @@ class WalletHDTest(BitcoinTestFramework):
new_seed = self.nodes[0].dumpprivkey(self.nodes[0].getnewaddress())
orig_masterkeyid = new_masterkeyid
self.nodes[1].sethdseed(False, new_seed)
- new_masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid']
+ new_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
assert orig_masterkeyid != new_masterkeyid
addr = self.nodes[1].getnewaddress()
- assert_equal(orig_masterkeyid, self.nodes[1].getaddressinfo(addr)['hdmasterkeyid'])
+ assert_equal(orig_masterkeyid, self.nodes[1].getaddressinfo(addr)['hdseedid'])
assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], 'm/0\'/0\'/1\'') # Make sure the new address continues previous keypool
# Check that the next address is from the new seed
self.nodes[1].keypoolrefill(1)
next_addr = self.nodes[1].getnewaddress()
- assert_equal(new_masterkeyid, self.nodes[1].getaddressinfo(next_addr)['hdmasterkeyid'])
+ assert_equal(new_masterkeyid, self.nodes[1].getaddressinfo(next_addr)['hdseedid'])
assert_equal(self.nodes[1].getaddressinfo(next_addr)['hdkeypath'], 'm/0\'/0\'/0\'') # Make sure the new address is not from previous keypool
assert next_addr != addr
diff --git a/test/functional/wallet_keypool.py b/test/functional/wallet_keypool.py
index 505014e48f..1285515dfc 100755
--- a/test/functional/wallet_keypool.py
+++ b/test/functional/wallet_keypool.py
@@ -16,7 +16,8 @@ class KeyPoolTest(BitcoinTestFramework):
addr_before_encrypting = nodes[0].getnewaddress()
addr_before_encrypting_data = nodes[0].getaddressinfo(addr_before_encrypting)
wallet_info_old = nodes[0].getwalletinfo()
- assert(addr_before_encrypting_data['hdmasterkeyid'] == wallet_info_old['hdmasterkeyid'])
+ assert_equal(wallet_info_old['hdseedid'], wallet_info_old['hdmasterkeyid'])
+ assert(addr_before_encrypting_data['hdseedid'] == wallet_info_old['hdseedid'])
# Encrypt wallet and wait to terminate
nodes[0].node_encrypt_wallet('test')
@@ -26,8 +27,9 @@ class KeyPoolTest(BitcoinTestFramework):
addr = nodes[0].getnewaddress()
addr_data = nodes[0].getaddressinfo(addr)
wallet_info = nodes[0].getwalletinfo()
- assert(addr_before_encrypting_data['hdmasterkeyid'] != wallet_info['hdmasterkeyid'])
- assert(addr_data['hdmasterkeyid'] == wallet_info['hdmasterkeyid'])
+ assert_equal(wallet_info['hdseedid'], wallet_info['hdmasterkeyid'])
+ assert(addr_before_encrypting_data['hdseedid'] != wallet_info['hdseedid'])
+ assert(addr_data['hdseedid'] == wallet_info['hdseedid'])
assert_raises_rpc_error(-12, "Error: Keypool ran out, please call keypoolrefill first", nodes[0].getnewaddress)
# put six (plus 2) new keys in the keypool (100% external-, +100% internal-keys, 1 in min)
diff --git a/test/functional/wallet_listreceivedby.py b/test/functional/wallet_listreceivedby.py
index 7447211296..e9912f994e 100755
--- a/test/functional/wallet_listreceivedby.py
+++ b/test/functional/wallet_listreceivedby.py
@@ -6,10 +6,13 @@
from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import (assert_array_result,
- assert_equal,
- assert_raises_rpc_error,
- )
+from test_framework.util import (
+ assert_array_result,
+ assert_equal,
+ assert_raises_rpc_error,
+ sync_blocks,
+)
+
class ReceivedByTest(BitcoinTestFramework):
def set_test_params(self):
@@ -18,6 +21,7 @@ class ReceivedByTest(BitcoinTestFramework):
def run_test(self):
# Generate block to get out of IBD
self.nodes[0].generate(1)
+ sync_blocks(self.nodes)
self.log.info("listreceivedbyaddress Test")
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index 5671773528..53638615f6 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -211,5 +211,28 @@ class MultiWalletTest(BitcoinTestFramework):
# Fail to load if wallet file is a symlink
assert_raises_rpc_error(-4, "Wallet file verification failed: Invalid -wallet path 'w8_symlink'", self.nodes[0].loadwallet, 'w8_symlink')
+ self.log.info("Test dynamic wallet creation.")
+
+ # Fail to create a wallet if it already exists.
+ assert_raises_rpc_error(-4, "Wallet w2 already exists.", self.nodes[0].createwallet, 'w2')
+
+ # Successfully create a wallet with a new name
+ loadwallet_name = self.nodes[0].createwallet('w9')
+ assert_equal(loadwallet_name['name'], 'w9')
+ w9 = node.get_wallet_rpc('w9')
+ assert_equal(w9.getwalletinfo()['walletname'], 'w9')
+
+ assert 'w9' in self.nodes[0].listwallets()
+
+ # Successfully create a wallet using a full path
+ new_wallet_dir = os.path.join(self.options.tmpdir, 'new_walletdir')
+ new_wallet_name = os.path.join(new_wallet_dir, 'w10')
+ loadwallet_name = self.nodes[0].createwallet(new_wallet_name)
+ assert_equal(loadwallet_name['name'], new_wallet_name)
+ w10 = node.get_wallet_rpc(new_wallet_name)
+ assert_equal(w10.getwalletinfo()['walletname'], new_wallet_name)
+
+ assert new_wallet_name in self.nodes[0].listwallets()
+
if __name__ == '__main__':
MultiWalletTest().main()
diff --git a/test/lint/README.md b/test/lint/README.md
new file mode 100644
index 0000000000..15974a3598
--- /dev/null
+++ b/test/lint/README.md
@@ -0,0 +1,29 @@
+This folder contains lint scripts.
+
+check-doc.py
+============
+Check for missing documentation of command line options.
+
+commit-script-check.sh
+======================
+Verification of [scripted diffs](/doc/developer-notes.md#scripted-diffs).
+
+git-subtree-check.sh
+====================
+Run this script from the root of the repository to verify that a subtree matches the contents of
+the commit it claims to have been updated to.
+
+To use, make sure that you have fetched the upstream repository branch in which the subtree is
+maintained:
+* for `src/secp256k1`: https://github.com/bitcoin-core/secp256k1.git (branch master)
+* for `src/leveldb`: https://github.com/bitcoin-core/leveldb.git (branch bitcoin-fork)
+* for `src/univalue`: https://github.com/bitcoin-core/univalue.git (branch master)
+* for `src/crypto/ctaes`: https://github.com/bitcoin-core/ctaes.git (branch master)
+
+Usage: `git-subtree-check.sh DIR (COMMIT)`
+
+`COMMIT` may be omitted, in which case `HEAD` is used.
+
+lint-all.sh
+===========
+Calls other scripts with the `lint-` prefix.
diff --git a/contrib/devtools/check-doc.py b/test/lint/check-doc.py
index de5719eb29..de5719eb29 100755
--- a/contrib/devtools/check-doc.py
+++ b/test/lint/check-doc.py
diff --git a/contrib/devtools/check-rpc-mappings.py b/test/lint/check-rpc-mappings.py
index 7e96852c5c..7e96852c5c 100755
--- a/contrib/devtools/check-rpc-mappings.py
+++ b/test/lint/check-rpc-mappings.py
diff --git a/contrib/devtools/commit-script-check.sh b/test/lint/commit-script-check.sh
index 1c9dbc7f68..1c9dbc7f68 100755
--- a/contrib/devtools/commit-script-check.sh
+++ b/test/lint/commit-script-check.sh
diff --git a/contrib/devtools/git-subtree-check.sh b/test/lint/git-subtree-check.sh
index 184951715e..184951715e 100755
--- a/contrib/devtools/git-subtree-check.sh
+++ b/test/lint/git-subtree-check.sh
diff --git a/contrib/devtools/lint-all.sh b/test/lint/lint-all.sh
index b6d86959c6..b6d86959c6 100755
--- a/contrib/devtools/lint-all.sh
+++ b/test/lint/lint-all.sh
diff --git a/contrib/devtools/lint-include-guards.sh b/test/lint/lint-include-guards.sh
index 6a0dd556bb..6a0dd556bb 100755
--- a/contrib/devtools/lint-include-guards.sh
+++ b/test/lint/lint-include-guards.sh
diff --git a/test/lint/lint-includes.sh b/test/lint/lint-includes.sh
new file mode 100755
index 0000000000..7cab0ca4d1
--- /dev/null
+++ b/test/lint/lint-includes.sh
@@ -0,0 +1,100 @@
+#!/bin/bash
+#
+# Copyright (c) 2018 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#
+# Check for duplicate includes.
+# Guard against accidental introduction of new Boost dependencies.
+
+filter_suffix() {
+ git ls-files | grep -E "^src/.*\.${1}"'$' | grep -Ev "/(leveldb|secp256k1|univalue)/"
+}
+
+EXIT_CODE=0
+
+for HEADER_FILE in $(filter_suffix h); do
+ DUPLICATE_INCLUDES_IN_HEADER_FILE=$(grep -E "^#include " < "${HEADER_FILE}" | sort | uniq -d)
+ if [[ ${DUPLICATE_INCLUDES_IN_HEADER_FILE} != "" ]]; then
+ echo "Duplicate include(s) in ${HEADER_FILE}:"
+ echo "${DUPLICATE_INCLUDES_IN_HEADER_FILE}"
+ echo
+ EXIT_CODE=1
+ fi
+done
+
+for CPP_FILE in $(filter_suffix cpp); do
+ DUPLICATE_INCLUDES_IN_CPP_FILE=$(grep -E "^#include " < "${CPP_FILE}" | sort | uniq -d)
+ if [[ ${DUPLICATE_INCLUDES_IN_CPP_FILE} != "" ]]; then
+ echo "Duplicate include(s) in ${CPP_FILE}:"
+ echo "${DUPLICATE_INCLUDES_IN_CPP_FILE}"
+ echo
+ EXIT_CODE=1
+ fi
+done
+
+EXPECTED_BOOST_INCLUDES=(
+ boost/algorithm/string.hpp
+ boost/algorithm/string/case_conv.hpp
+ boost/algorithm/string/classification.hpp
+ boost/algorithm/string/join.hpp
+ boost/algorithm/string/predicate.hpp
+ boost/algorithm/string/replace.hpp
+ boost/algorithm/string/split.hpp
+ boost/assign/std/vector.hpp
+ boost/bind.hpp
+ boost/chrono/chrono.hpp
+ boost/date_time/posix_time/posix_time.hpp
+ boost/filesystem.hpp
+ boost/filesystem/detail/utf8_codecvt_facet.hpp
+ boost/filesystem/fstream.hpp
+ boost/interprocess/sync/file_lock.hpp
+ boost/multi_index/hashed_index.hpp
+ boost/multi_index/ordered_index.hpp
+ boost/multi_index/sequenced_index.hpp
+ boost/multi_index_container.hpp
+ boost/optional.hpp
+ boost/preprocessor/cat.hpp
+ boost/preprocessor/stringize.hpp
+ boost/program_options/detail/config_file.hpp
+ boost/scoped_array.hpp
+ boost/signals2/connection.hpp
+ boost/signals2/last_value.hpp
+ boost/signals2/signal.hpp
+ boost/test/unit_test.hpp
+ boost/thread.hpp
+ boost/thread/condition_variable.hpp
+ boost/thread/mutex.hpp
+ boost/thread/thread.hpp
+ boost/variant.hpp
+ boost/variant/apply_visitor.hpp
+ boost/variant/static_visitor.hpp
+)
+
+for BOOST_INCLUDE in $(git grep '^#include <boost/' -- "*.cpp" "*.h" | cut -f2 -d: | cut -f2 -d'<' | cut -f1 -d'>' | sort -u); do
+ IS_EXPECTED_INCLUDE=0
+ for EXPECTED_BOOST_INCLUDE in "${EXPECTED_BOOST_INCLUDES[@]}"; do
+ if [[ "${BOOST_INCLUDE}" == "${EXPECTED_BOOST_INCLUDE}" ]]; then
+ IS_EXPECTED_INCLUDE=1
+ break
+ fi
+ done
+ if [[ ${IS_EXPECTED_INCLUDE} == 0 ]]; then
+ EXIT_CODE=1
+ echo "A new Boost dependency in the form of \"${BOOST_INCLUDE}\" appears to have been introduced:"
+ git grep "${BOOST_INCLUDE}" -- "*.cpp" "*.h"
+ echo
+ fi
+done
+
+for EXPECTED_BOOST_INCLUDE in "${EXPECTED_BOOST_INCLUDES[@]}"; do
+ if ! git grep -q "^#include <${EXPECTED_BOOST_INCLUDE}>" -- "*.cpp" "*.h"; then
+ echo "Good job! The Boost dependency \"${EXPECTED_BOOST_INCLUDE}\" is no longer used."
+ echo "Please remove it from EXPECTED_BOOST_INCLUDES in $0"
+ echo "to make sure this dependency is not accidentally reintroduced."
+ echo
+ EXIT_CODE=1
+ fi
+done
+
+exit ${EXIT_CODE}
diff --git a/contrib/devtools/lint-logs.sh b/test/lint/lint-logs.sh
index 35be13ec19..35be13ec19 100755
--- a/contrib/devtools/lint-logs.sh
+++ b/test/lint/lint-logs.sh
diff --git a/contrib/devtools/lint-python-shebang.sh b/test/lint/lint-python-shebang.sh
index f5c5971c03..f5c5971c03 100755
--- a/contrib/devtools/lint-python-shebang.sh
+++ b/test/lint/lint-python-shebang.sh
diff --git a/contrib/devtools/lint-python.sh b/test/lint/lint-python.sh
index 7d3555b6d4..7d3555b6d4 100755
--- a/contrib/devtools/lint-python.sh
+++ b/test/lint/lint-python.sh
diff --git a/contrib/devtools/lint-shell.sh b/test/lint/lint-shell.sh
index 5f5fa9a925..5f5fa9a925 100755
--- a/contrib/devtools/lint-shell.sh
+++ b/test/lint/lint-shell.sh
diff --git a/contrib/devtools/lint-tests.sh b/test/lint/lint-tests.sh
index ffc0660551..ffc0660551 100755
--- a/contrib/devtools/lint-tests.sh
+++ b/test/lint/lint-tests.sh
diff --git a/contrib/devtools/lint-whitespace.sh b/test/lint/lint-whitespace.sh
index c5d43043d5..c5d43043d5 100755
--- a/contrib/devtools/lint-whitespace.sh
+++ b/test/lint/lint-whitespace.sh