diff options
100 files changed, 2364 insertions, 1221 deletions
diff --git a/.travis.yml b/.travis.yml index 3467103d10..f59c7fc7e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -88,13 +88,35 @@ jobs: script: - set -o errexit; source ./ci/extended_lint/06_script.sh + - stage: extended-lint + name: 'lint macOS 10.12 (compat)' + os: osx + # Use the earliest macOS that can build our lint dependencies: + # Xcode 8.3.3, macOS 10.12, JDK 1.8.0_112-b16 + # https://docs.travis-ci.com/user/reference/osx/#OS-X-Version + osx_image: xcode8.3 + # TODO: if you're updating osx_image, try using "rvm:" to supply the + # version of ruby required by homebrew. Despite this "rvm:" declaration, + # brew update installs ruby 2.3.7 as its first action. + language: ruby + rvm: + - 2.3.7 + env: + cache: false + install: + - set -o errexit; source ./ci/lint/04_install.sh + before_script: + - set -o errexit; source ./ci/lint/05_before_script.sh + script: + - set -o errexit; source ./ci/lint/06_script.sh + - stage: test - name: 'ARM [GOAL: install] [no unit or functional tests]' + name: 'ARM [GOAL: install] [unit tests, no functional tests]' env: >- FILE_ENV="./ci/test/00_setup_env_arm.sh" - stage: test - name: 'Win64 [GOAL: deploy] [no gui or functional tests]' + name: 'Win64 [GOAL: deploy] [unit tests, no gui, no functional tests]' env: >- FILE_ENV="./ci/test/00_setup_env_win64.sh" diff --git a/Makefile.am b/Makefile.am index 8b1e2a6b5b..9e54dc210d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,6 +2,10 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. +# Pattern rule to print variables, e.g. make print-top_srcdir +print-%: + @echo $* = $($*) + ACLOCAL_AMFLAGS = -I build-aux/m4 SUBDIRS = src if ENABLE_MAN @@ -39,7 +43,10 @@ OSX_INSTALLER_ICONS=$(top_srcdir)/src/qt/res/icons/bitcoin.icns OSX_PLIST=$(top_builddir)/share/qt/Info.plist #not installed OSX_QT_TRANSLATIONS = da,de,es,hu,ru,uk,zh_CN,zh_TW -DIST_DOCS = $(wildcard doc/*.md) $(wildcard doc/release-notes/*.md) +DIST_DOCS = \ + README.md \ + $(wildcard doc/*.md) \ + $(wildcard doc/release-notes/*.md) DIST_CONTRIB = $(top_srcdir)/contrib/bitcoin-cli.bash-completion \ $(top_srcdir)/contrib/bitcoin-tx.bash-completion \ $(top_srcdir)/contrib/bitcoind.bash-completion \ diff --git a/autogen.sh b/autogen.sh index 2c434e9ef0..3e922e7e64 100755 --- a/autogen.sh +++ b/autogen.sh @@ -5,9 +5,9 @@ export LC_ALL=C set -e -srcdir="$(dirname $0)" +srcdir="$(dirname "$0")" cd "$srcdir" -if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="$(command -v glibtoolize)"; then +if [ -z "${LIBTOOLIZE}" ] && GLIBTOOLIZE="$(command -v glibtoolize)"; then LIBTOOLIZE="${GLIBTOOLIZE}" export LIBTOOLIZE fi diff --git a/ci/lint/04_install.sh b/ci/lint/04_install.sh index 12c3bfce45..9f7e1b310d 100755 --- a/ci/lint/04_install.sh +++ b/ci/lint/04_install.sh @@ -6,9 +6,22 @@ export LC_ALL=C +if [ "$TRAVIS_OS_NAME" == "osx" ]; then + # update first to install required ruby dependency + travis_retry brew update + travis_retry brew reinstall git -- --with-pcre2 # for --perl-regexp + travis_retry brew install grep # gnu grep for --perl-regexp support + PATH="$(brew --prefix grep)/libexec/gnubin:$PATH" + travis_retry brew install shellcheck + travis_retry brew upgrade python + PATH="$(brew --prefix python)/bin:$PATH" + export PATH +else + SHELLCHECK_VERSION=v0.6.0 + travis_retry curl --silent "https://storage.googleapis.com/shellcheck/shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" | tar --xz -xf - --directory /tmp/ + PATH="/tmp/shellcheck-${SHELLCHECK_VERSION}:${PATH}" + export PATH +fi + travis_retry pip3 install codespell==1.15.0 travis_retry pip3 install flake8==3.7.8 - -SHELLCHECK_VERSION=v0.6.0 -curl -s "https://storage.googleapis.com/shellcheck/shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" | tar --xz -xf - --directory /tmp/ -export PATH="/tmp/shellcheck-${SHELLCHECK_VERSION}:${PATH}" diff --git a/ci/test/00_setup_env.sh b/ci/test/00_setup_env.sh index 94598835ac..8bc50da2c3 100755 --- a/ci/test/00_setup_env.sh +++ b/ci/test/00_setup_env.sh @@ -22,6 +22,8 @@ export MAKEJOBS=${MAKEJOBS:--j4} # A folder for the ci system to put temporary files (ccache, datadirs for tests, ...) export BASE_SCRATCH_DIR=${BASE_SCRATCH_DIR:-$BASE_ROOT_DIR/ci/scratch/} export HOST=${HOST:-x86_64-unknown-linux-gnu} +# Whether to prefer BusyBox over GNU utilities +export USE_BUSY_BOX=${USE_BUSY_BOX:-false} export RUN_UNIT_TESTS=${RUN_UNIT_TESTS:-true} export RUN_FUNCTIONAL_TESTS=${RUN_FUNCTIONAL_TESTS:-true} export RUN_FUZZ_TESTS=${RUN_FUZZ_TESTS:-false} diff --git a/ci/test/00_setup_env_arm.sh b/ci/test/00_setup_env_arm.sh index ac7ace8c3b..9335f0b337 100644 --- a/ci/test/00_setup_env_arm.sh +++ b/ci/test/00_setup_env_arm.sh @@ -7,8 +7,10 @@ export LC_ALL=C.UTF-8 export HOST=arm-linux-gnueabihf -export PACKAGES="python3 g++-arm-linux-gnueabihf" -export RUN_UNIT_TESTS=false +export QEMU_USER_CMD="qemu-arm -L /usr/arm-linux-gnueabihf/" +export PACKAGES="python3 g++-arm-linux-gnueabihf busybox qemu-user" +export USE_BUSY_BOX=true +export RUN_UNIT_TESTS=true export RUN_FUNCTIONAL_TESTS=false export GOAL="install" # -Wno-psabi is to disable ABI warnings: "note: parameter passing for argument of type ... changed in GCC 7.1" diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh index 54d7a9b814..409e87ce04 100755 --- a/ci/test/04_install.sh +++ b/ci/test/04_install.sh @@ -33,18 +33,29 @@ if [ -z "$RUN_CI_ON_HOST" ]; then DOCKER_ID=$(docker run $DOCKER_ADMIN -idt --mount type=bind,src=$BASE_BUILD_DIR,dst=$BASE_BUILD_DIR --mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR -w $BASE_BUILD_DIR --env-file /tmp/env $DOCKER_NAME_TAG) DOCKER_EXEC () { - docker exec $DOCKER_ID bash -c "cd $PWD && $*" + docker exec $DOCKER_ID bash -c "export PATH=$BASE_SCRATCH_DIR/bins/:\$PATH && cd $PWD && $*" } else echo "Running on host system without docker wrapper" DOCKER_EXEC () { - bash -c "cd $PWD && $*" + bash -c "export PATH=$BASE_SCRATCH_DIR/bins/:\$PATH && cd $PWD && $*" } fi DOCKER_EXEC free -m -h -DOCKER_EXEC echo "Number of CPUs \(nproc\): $(nproc)" +DOCKER_EXEC echo "Number of CPUs \(nproc\):" \$\(nproc\) ${CI_RETRY_EXE} DOCKER_EXEC apt-get update -${CI_RETRY_EXE} DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES $DOCKER_PACKAGES - +${CI_RETRY_EXE} DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -y $PACKAGES $DOCKER_PACKAGES + +if [ "$USE_BUSY_BOX" = "true" ]; then + echo "Setup to use BusyBox utils" + DOCKER_EXEC mkdir -p $BASE_SCRATCH_DIR/bins/ + # tar excluded for now because it requires passing in the exact archive type in ./depends (fixed in later BusyBox version) + # find excluded for now because it does not recognize the -delete option in ./depends (fixed in later BusyBox version) + # ar excluded for now because it does not recognize the -q option in ./depends (unknown if fixed) + # shellcheck disable=SC1010 + DOCKER_EXEC for util in \$\(busybox --list \| grep -v "^ar$" \| grep -v "^tar$" \| grep -v "^find$"\)\; do ln -s \$\(command -v busybox\) $BASE_SCRATCH_DIR/bins/\$util\; done + # Print BusyBox version + DOCKER_EXEC patch --help +fi diff --git a/ci/test/06_script_b.sh b/ci/test/06_script_b.sh index ea7beae85f..1a5217277a 100755 --- a/ci/test/06_script_b.sh +++ b/ci/test/06_script_b.sh @@ -8,8 +8,28 @@ export LC_ALL=C.UTF-8 cd "build/bitcoin-$HOST" || (echo "could not enter distdir build/bitcoin-$HOST"; exit 1) +if [ -n "$QEMU_USER_CMD" ]; then + BEGIN_FOLD wrap-qemu + echo "Prepare to run functional tests for HOST=$HOST" + # Generate all binaries, so that they can be wrapped + DOCKER_EXEC make $MAKEJOBS -C src/secp256k1 VERBOSE=1 + DOCKER_EXEC make $MAKEJOBS -C src/univalue VERBOSE=1 + for b_name in {"${BASE_OUTDIR}/bin"/*,src/secp256k1/*tests,src/univalue/{no_nul,test_json,unitester,object}}; do + # shellcheck disable=SC2044 + for b in $(find "${BASE_ROOT_DIR}" -executable -type f -name $(basename $b_name)); do + echo "Wrap $b ..." + DOCKER_EXEC mv "$b" "${b}_orig" + DOCKER_EXEC echo "\#\!/usr/bin/env bash" \> "$b" + DOCKER_EXEC echo "$QEMU_USER_CMD \\\"${b}_orig\\\" \\\"\\\$@\\\"" \>\> "$b" + DOCKER_EXEC chmod +x "$b" + done + done + END_FOLD +fi + if [ "$RUN_UNIT_TESTS" = "true" ]; then BEGIN_FOLD unit-tests + bash -c "while sleep 500; do echo .; done" & # Print dots in case the unit tests take a long time to run DOCKER_EXEC LD_LIBRARY_PATH=$BASE_BUILD_DIR/depends/$HOST/lib make $MAKEJOBS check VERBOSE=1 END_FOLD fi diff --git a/configure.ac b/configure.ac index a86a876d4f..715b65f091 100644 --- a/configure.ac +++ b/configure.ac @@ -76,6 +76,10 @@ fi AC_PROG_OBJCXX ]) +dnl Since libtool 1.5.2 (released 2004-01-25), on Linux libtool no longer +dnl sets RPATH for any directories in the dynamic linker search path. +dnl See more: https://wiki.debian.org/RpathIssue +LT_PREREQ([1.5.2]) dnl Libtool init checks. LT_INIT([pic-only]) @@ -1665,17 +1669,6 @@ AC_CONFIG_SUBDIRS([src/secp256k1]) AC_OUTPUT -dnl Taken from https://wiki.debian.org/RpathIssue -case $host in - *-*-linux-gnu) - AC_MSG_RESULT([Fixing libtool for -rpath problems.]) - sed < libtool > libtool-2 \ - 's/^hardcode_libdir_flag_spec.*$'/'hardcode_libdir_flag_spec=" -D__LIBTOOL_IS_A_FOOL__ "/' - mv libtool-2 libtool - chmod 755 libtool - ;; -esac - dnl Replace the BUILDDIR path with the correct Windows path if compiling on Native Windows case ${OS} in *Windows*) diff --git a/contrib/devtools/copyright_header.py b/contrib/devtools/copyright_header.py index 67e77bc63d..5307b04197 100755 --- a/contrib/devtools/copyright_header.py +++ b/contrib/devtools/copyright_header.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016-2018 The Bitcoin Core developers +# Copyright (c) 2016-2019 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -34,7 +34,7 @@ EXCLUDE_DIRS = [ "src/univalue/", ] -INCLUDE = ['*.h', '*.cpp', '*.cc', '*.c', '*.mm', '*.py'] +INCLUDE = ['*.h', '*.cpp', '*.cc', '*.c', '*.mm', '*.py', '*.sh', '*.bash-completion'] INCLUDE_COMPILED = re.compile('|'.join([fnmatch.translate(m) for m in INCLUDE])) def applies_to_file(filename): diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index c50750ed44..e0b9f74397 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-core-linux-0.19" +name: "bitcoin-core-linux-0.20" enable_cache: true distro: "ubuntu" suites: @@ -181,7 +181,7 @@ script: | rm -rf ${DISTNAME}/lib/pkgconfig find ${DISTNAME}/bin -type f -executable -print0 | xargs -0 -n1 -I{} ../contrib/devtools/split-debug.sh {} {} {}.dbg find ${DISTNAME}/lib -type f -print0 | xargs -0 -n1 -I{} ../contrib/devtools/split-debug.sh {} {} {}.dbg - cp ../doc/README.md ${DISTNAME}/ + cp ../README.md ${DISTNAME}/ find ${DISTNAME} -not -name "*.dbg" | sort | tar --mtime="$REFERENCE_DATETIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}.tar.gz find ${DISTNAME} -name "*.dbg" | sort | tar --mtime="$REFERENCE_DATETIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}-debug.tar.gz cd ../../ diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 8c51ce7159..a563bef778 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-core-osx-0.19" +name: "bitcoin-core-osx-0.20" enable_cache: true distro: "ubuntu" suites: diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index f227c6ad92..d600af84fb 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -1,5 +1,5 @@ --- -name: "bitcoin-core-win-0.19" +name: "bitcoin-core-win-0.20" enable_cache: true distro: "ubuntu" suites: @@ -22,7 +22,6 @@ packages: - "zip" - "ca-certificates" - "python3" -- "rename" remotes: - "url": "https://github.com/bitcoin/bitcoin.git" "dir": "bitcoin" @@ -73,18 +72,10 @@ script: | done } - function create_per-host_linker_wrapper { - # This is only needed for trusty, as the mingw linker leaks a few bytes of - # heap, causing non-determinism. See discussion in https://github.com/bitcoin/bitcoin/pull/6900 + function create_per-host_compiler_wrapper { + # -posix variant is required for c++11 threading. for i in $HOSTS; do mkdir -p ${WRAP_DIR}/${i} - for prog in collect2; do - echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}/${prog} - REAL=$(${i}-gcc -print-prog-name=${prog}) - echo "export MALLOC_PERTURB_=255" >> ${WRAP_DIR}/${i}/${prog} - echo "${REAL} \$@" >> $WRAP_DIR/${i}/${prog} - chmod +x ${WRAP_DIR}/${i}/${prog} - done for prog in gcc g++; do echo '#!/usr/bin/env bash' > ${WRAP_DIR}/${i}-${prog} echo "REAL=\`which -a ${i}-${prog}-posix | grep -v ${WRAP_DIR}/${i}-${prog} | head -1\`" >> ${WRAP_DIR}/${i}-${prog} @@ -101,7 +92,7 @@ script: | export PATH_orig=${PATH} create_global_faketime_wrappers "2000-01-01 12:00:00" create_per-host_faketime_wrappers "2000-01-01 12:00:00" - create_per-host_linker_wrapper "2000-01-01 12:00:00" + create_per-host_compiler_wrapper "2000-01-01 12:00:00" export PATH=${WRAP_DIR}:${PATH} cd bitcoin @@ -115,7 +106,7 @@ script: | export PATH=${PATH_orig} create_global_faketime_wrappers "${REFERENCE_DATETIME}" create_per-host_faketime_wrappers "${REFERENCE_DATETIME}" - create_per-host_linker_wrapper "${REFERENCE_DATETIME}" + create_per-host_compiler_wrapper "${REFERENCE_DATETIME}" export PATH=${WRAP_DIR}:${PATH} # Create the release tarball using (arbitrarily) the first host @@ -124,14 +115,11 @@ script: | make dist SOURCEDIST=`echo bitcoin-*.tar.gz` DISTNAME=`echo ${SOURCEDIST} | sed 's/.tar.*//'` - # Correct tar file order mkdir -p temp pushd temp tar -xf ../$SOURCEDIST find bitcoin-* | sort | tar --mtime="$REFERENCE_DATETIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ../$SOURCEDIST - mkdir -p $OUTDIR/src - cp ../$SOURCEDIST $OUTDIR/src popd # Workaround for tarball not building with the bare tag version (prep) @@ -157,24 +145,27 @@ script: | make ${MAKEOPTS} -C src check-security make deploy make install DESTDIR=${INSTALLPATH} - rename 's/-setup\.exe$/-setup-unsigned.exe/' *-setup.exe - cp -f bitcoin-*setup*.exe $OUTDIR/ + ( + SETUP_EXE="$(basename "$(echo ./*-setup.exe)")" + cp -f "$SETUP_EXE" "${OUTDIR}/${SETUP_EXE/%-setup.exe/-setup-unsigned.exe}" + ) cd installed mv ${DISTNAME}/bin/*.dll ${DISTNAME}/lib/ find . -name "lib*.la" -delete find . -name "lib*.a" -delete rm -rf ${DISTNAME}/lib/pkgconfig - find ${DISTNAME}/bin -type f -executable -exec ${i}-objcopy --only-keep-debug {} {}.dbg \; -exec ${i}-strip -s {} \; -exec ${i}-objcopy --add-gnu-debuglink={}.dbg {} \; - find ${DISTNAME}/lib -type f -exec ${i}-objcopy --only-keep-debug {} {}.dbg \; -exec ${i}-strip -s {} \; -exec ${i}-objcopy --add-gnu-debuglink={}.dbg {} \; - find ${DISTNAME} -not -name "*.dbg" -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${i}.zip - find ${DISTNAME} -name "*.dbg" -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${i}-debug.zip + find ${DISTNAME}/bin -type f -executable -print0 | xargs -0 -n1 -I{} ../contrib/devtools/split-debug.sh {} {} {}.dbg + find ${DISTNAME}/lib -type f -print0 | xargs -0 -n1 -I{} ../contrib/devtools/split-debug.sh {} {} {}.dbg + cp ../doc/README_windows.txt ${DISTNAME}/readme.txt + find ${DISTNAME} -not -name "*.dbg" -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${i//x86_64-w64-mingw32/win64}.zip + find ${DISTNAME} -name "*.dbg" -type f | sort | zip -X@ ${OUTDIR}/${DISTNAME}-${i//x86_64-w64-mingw32/win64}-debug.zip cd ../../ rm -rf distsrc-${i} done + mkdir -p $OUTDIR/src + mv $SOURCEDIST $OUTDIR/src cp -rf contrib/windeploy $BUILD_DIR cd $BUILD_DIR/windeploy mkdir unsigned cp $OUTDIR/bitcoin-*setup-unsigned.exe unsigned/ find . | sort | tar --mtime="$REFERENCE_DATETIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-win-unsigned.tar.gz - mv ${OUTDIR}/${DISTNAME}-x86_64-*-debug.zip ${OUTDIR}/${DISTNAME}-win64-debug.zip - mv ${OUTDIR}/${DISTNAME}-x86_64-*.zip ${OUTDIR}/${DISTNAME}-win64.zip diff --git a/contrib/init/bitcoind.conf b/contrib/init/bitcoind.conf index de4ea0ed52..dde1bd0c4d 100644 --- a/contrib/init/bitcoind.conf +++ b/contrib/init/bitcoind.conf @@ -16,7 +16,7 @@ expect fork respawn respawn limit 5 120 -kill timeout 60 +kill timeout 600 pre-start script # this will catch non-existent config files diff --git a/contrib/init/bitcoind.init b/contrib/init/bitcoind.init index 0c95baf3a1..19e1f76d09 100644 --- a/contrib/init/bitcoind.init +++ b/contrib/init/bitcoind.init @@ -39,7 +39,7 @@ start() { stop() { echo -n $"Stopping $prog: " - killproc $prog + killproc $prog -t600 RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f $lockfile diff --git a/contrib/init/bitcoind.openrcconf b/contrib/init/bitcoind.openrcconf index f70e25cb5f..c8a22a08d9 100644 --- a/contrib/init/bitcoind.openrcconf +++ b/contrib/init/bitcoind.openrcconf @@ -30,4 +30,4 @@ # Note that this will be mapped as argument to start-stop-daemon's # '--retry' option, which means you can specify a retry schedule # here. For more information see man 8 start-stop-daemon. -BITCOIND_SIGTERM_TIMEOUT=60 +BITCOIND_SIGTERM_TIMEOUT=600 diff --git a/contrib/init/bitcoind.service b/contrib/init/bitcoind.service index 34c3e7b3ab..8b308644b1 100644 --- a/contrib/init/bitcoind.service +++ b/contrib/init/bitcoind.service @@ -29,6 +29,7 @@ ExecStartPre=/bin/chgrp bitcoin /etc/bitcoin Type=forking PIDFile=/run/bitcoind/bitcoind.pid Restart=on-failure +TimeoutStopSec=600 # Directory creation and permissions #################################### diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py index 95754ab937..863b22f6b1 100755 --- a/contrib/linearize/linearize-data.py +++ b/contrib/linearize/linearize-data.py @@ -213,8 +213,11 @@ class BlockDataCopier: inMagic = inhdr[:4] if (inMagic != self.settings['netmagic']): - print("Invalid magic: " + inMagic.hex()) - return + # Seek backwards 7 bytes (skipping the first byte in the previous search) + # and continue searching from the new position if the magic bytes are not + # found. + self.inF.seek(-7, os.SEEK_CUR) + continue inLenLE = inhdr[4:] su = struct.unpack("<I", inLenLE) inLen = su[0] - 80 # length without header diff --git a/contrib/seeds/makeseeds.py b/contrib/seeds/makeseeds.py index 2f7697e0b1..ec589d4c02 100755 --- a/contrib/seeds/makeseeds.py +++ b/contrib/seeds/makeseeds.py @@ -123,7 +123,7 @@ def filtermultiport(ips): def lookup_asn(net, ip): ''' - Look up the asn for an IP (4 or 6) address by querying cymry.com, or None + Look up the asn for an IP (4 or 6) address by querying cymru.com, or None if it could not be found. ''' try: @@ -187,7 +187,7 @@ def main(): # Skip entries with invalid address. ips = [ip for ip in ips if ip is not None] print('%s Skip entries with invalid address' % (ip_stats(ips)), file=sys.stderr) - # Skip duplicattes (in case multiple seeds files were concatenated) + # Skip duplicates (in case multiple seeds files were concatenated) ips = dedup(ips) print('%s After removing duplicates' % (ip_stats(ips)), file=sys.stderr) # Skip entries from suspicious hosts. diff --git a/depends/Makefile b/depends/Makefile index b7e9a9213e..25ff135ea6 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -1,5 +1,9 @@ .NOTPARALLEL : +# Pattern rule to print variables, e.g. make print-top_srcdir +print-%: + @echo $* = $($*) + SOURCES_PATH ?= $(BASEDIR)/sources WORK_PATH = $(BASEDIR)/work BASE_CACHE ?= $(BASEDIR)/built diff --git a/depends/config.guess b/depends/config.guess index 2b79f6d837..7f9ebbe310 100755 --- a/depends/config.guess +++ b/depends/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2018 Free Software Foundation, Inc. +# Copyright 1992-2019 Free Software Foundation, Inc. -timestamp='2018-07-06' +timestamp='2019-09-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -50,7 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2018 Free Software Foundation, Inc. +Copyright 1992-2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -84,8 +84,6 @@ if test $# != 0; then exit 1 fi -trap 'exit 1' 1 2 15 - # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a @@ -96,34 +94,38 @@ trap 'exit 1' 1 2 15 # Portable tmp directory creation inspired by the Autoconf team. -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp 2>/dev/null) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in - ,,) echo "int x;" > "$dummy.c" ; - for c in cc gcc c89 c99 ; do - if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' +tmp= +# shellcheck disable=SC2172 +trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 + +set_cc_for_build() { + : "${TMPDIR=/tmp}" + # shellcheck disable=SC2039 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } + dummy=$tmp/dummy + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in + ,,) echo "int x;" > "$dummy.c" + for driver in cc gcc c89 c99 ; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD="$driver" + break + fi + done + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; + esac +} # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then +if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi @@ -138,7 +140,7 @@ Linux|GNU|GNU/*) # We could probably try harder. LIBC=gnu - eval "$set_cc_for_build" + set_cc_for_build cat <<-EOF > "$dummy.c" #include <features.h> #if defined(__UCLIBC__) @@ -199,7 +201,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval "$set_cc_for_build" + set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then @@ -260,6 +262,9 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:SolidBSD:*:*) echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; + *:OS108:*:*) + echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE" + exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; @@ -269,12 +274,15 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:Sortix:*:*) echo "$UNAME_MACHINE"-unknown-sortix exit ;; + *:Twizzler:*:*) + echo "$UNAME_MACHINE"-unknown-twizzler + exit ;; *:Redox:*:*) echo "$UNAME_MACHINE"-unknown-redox exit ;; mips:OSF1:*.*) - echo mips-dec-osf1 - exit ;; + echo mips-dec-osf1 + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -389,7 +397,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval "$set_cc_for_build" + set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. @@ -482,7 +490,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include <stdio.h> /* for printf() prototype */ @@ -579,7 +587,7 @@ EOF exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include <sys/systemcfg.h> @@ -660,7 +668,7 @@ EOF esac fi if [ "$HP_ARCH" = "" ]; then - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE @@ -700,7 +708,7 @@ EOF esac if [ "$HP_ARCH" = hppa2.0w ] then - eval "$set_cc_for_build" + set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -726,7 +734,7 @@ EOF echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) - eval "$set_cc_for_build" + set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include <unistd.h> int @@ -840,6 +848,17 @@ EOF *:BSD/OS:*:*) echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" exit ;; + arm:FreeBSD:*:*) + UNAME_PROCESSOR=`uname -p` + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi + else + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf + fi + exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case "$UNAME_PROCESSOR" in @@ -881,7 +900,7 @@ EOF echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin + echo x86_64-pc-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" @@ -922,7 +941,7 @@ EOF echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) - eval "$set_cc_for_build" + set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then @@ -971,23 +990,51 @@ EOF echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) - eval "$set_cc_for_build" + set_cc_for_build + IS_GLIBC=0 + test x"${LIBC}" = xgnu && IS_GLIBC=1 sed 's/^ //' << EOF > "$dummy.c" #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el + #undef mips + #undef mipsel + #undef mips64 + #undef mips64el + #if ${IS_GLIBC} && defined(_ABI64) + LIBCABI=gnuabi64 + #else + #if ${IS_GLIBC} && defined(_ABIN32) + LIBCABI=gnuabin32 + #else + LIBCABI=${LIBC} + #endif + #endif + + #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa64r6 + #else + #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa32r6 + #else + #if defined(__mips64) + CPU=mips64 + #else + CPU=mips + #endif + #endif + #endif + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el + MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} + MIPS_ENDIAN= #else - CPU= + MIPS_ENDIAN= #endif #endif EOF - eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" - test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`" + test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; mips64el:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" @@ -1100,7 +1147,7 @@ EOF *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then @@ -1284,38 +1331,39 @@ EOF echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval "$set_cc_for_build" - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc + UNAME_PROCESSOR=`uname -p` + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + if command -v xcode-select > /dev/null 2> /dev/null && \ + ! xcode-select --print-path > /dev/null 2> /dev/null ; then + # Avoid executing cc if there is no toolchain installed as + # cc will be a stub that puts up a graphical alert + # prompting the user to install developer tools. + CC_FOR_BUILD=no_compiler_found + else + set_cc_for_build fi - if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi - # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc - if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_PPC >/dev/null - then - UNAME_PROCESSOR=powerpc - fi + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc fi elif test "$UNAME_PROCESSOR" = i386 ; then - # Avoid executing cc on OS X 10.9, as it ships with a stub - # that puts up a graphical alert prompting to install - # developer tools. Any system running Mac OS X 10.7 or - # later (Darwin 11 and later) is required to have a 64-bit - # processor. This is not true of the ARM version of Darwin - # that Apple uses in portable devices. - UNAME_PROCESSOR=x86_64 + # uname -m returns i386 or x86_64 + UNAME_PROCESSOR=$UNAME_MACHINE fi echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; @@ -1358,6 +1406,7 @@ EOF # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. + # shellcheck disable=SC2154 if test "$cputype" = 386; then UNAME_MACHINE=i386 else @@ -1414,8 +1463,148 @@ EOF amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; + *:Unleashed:*:*) + echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE" + exit ;; esac +# No uname command or uname output not recognized. +set_cc_for_build +cat > "$dummy.c" <<EOF +#ifdef _SEQUENT_ +#include <sys/types.h> +#include <sys/utsname.h> +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#include <signal.h> +#if defined(_SIZE_T_) || defined(SIGLOST) +#include <sys/utsname.h> +#endif +#endif +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); +#endif + +#if defined (vax) +#if !defined (ultrix) +#include <sys/param.h> +#if defined (BSD) +#if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +#else +#if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#endif +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#else +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname un; + uname (&un); + printf ("vax-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname *un; + uname (&un); + printf ("mips-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("mips-dec-ultrix\n"); exit (0); +#endif +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. +test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } + echo "$0: unable to guess system type" >&2 case "$UNAME_MACHINE:$UNAME_SYSTEM" in diff --git a/depends/config.sub b/depends/config.sub index c95acc681d..a318a46868 100755 --- a/depends/config.sub +++ b/depends/config.sub @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2018 Free Software Foundation, Inc. +# Copyright 1992-2019 Free Software Foundation, Inc. -timestamp='2018-07-03' +timestamp='2019-06-30' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -67,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.sub ($timestamp) -Copyright 1992-2018 Free Software Foundation, Inc. +Copyright 1992-2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -89,7 +89,7 @@ while test $# -gt 0 ; do - ) # Use stdin as input. break ;; -* ) - echo "$me: invalid option $1$help" + echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) @@ -111,7 +111,8 @@ case $# in esac # Split fields of configuration type -IFS="-" read -r field1 field2 field3 field4 <<EOF +# shellcheck disable=SC2162 +IFS="-" read field1 field2 field3 field4 <<EOF $1 EOF @@ -149,29 +150,39 @@ case $1 in esac ;; *-*) - # Second component is usually, but not always the OS - case $field2 in - # Prevent following clause from handling this valid os - sun*os*) - basic_machine=$field1 - os=$field2 - ;; - # Manufacturers - dec* | mips* | sequent* | encore* | pc532* | sgi* | sony* \ - | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ - | unicom* | ibm* | next | hp | isi* | apollo | altos* \ - | convergent* | ncr* | news | 32* | 3600* | 3100* | hitachi* \ - | c[123]* | convex* | sun | crds | omron* | dg | ultra | tti* \ - | harris | dolphin | highlevel | gould | cbm | ns | masscomp \ - | apple | axis | knuth | cray | microblaze* \ - | sim | cisco | oki | wec | wrs | winbond) - basic_machine=$field1-$field2 + # A lone config we happen to match not fitting any pattern + case $field1-$field2 in + decstation-3100) + basic_machine=mips-dec os= ;; - *) - basic_machine=$field1 - os=$field2 - ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* \ + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ + | ultra | tti* | harris | dolphin | highlevel | gould \ + | cbm | ns | masscomp | apple | axis | knuth | cray \ + | microblaze* | sim | cisco \ + | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + os= + ;; + *) + basic_machine=$field1 + os=$field2 + ;; + esac + ;; esac ;; *) @@ -190,6 +201,14 @@ case $1 in basic_machine=m68010-adobe os=scout ;; + alliant) + basic_machine=fx80-alliant + os= + ;; + altos | altos3068) + basic_machine=m68k-altos + os= + ;; am29k) basic_machine=a29k-none os=bsd @@ -198,6 +217,10 @@ case $1 in basic_machine=580-amdahl os=sysv ;; + amiga) + basic_machine=m68k-unknown + os= + ;; amigaos | amigados) basic_machine=m68k-unknown os=amigaos @@ -234,13 +257,41 @@ case $1 in basic_machine=arm-unknown os=cegcc ;; + convex-c1) + basic_machine=c1-convex + os=bsd + ;; + convex-c2) + basic_machine=c2-convex + os=bsd + ;; + convex-c32) + basic_machine=c32-convex + os=bsd + ;; + convex-c34) + basic_machine=c34-convex + os=bsd + ;; + convex-c38) + basic_machine=c38-convex + os=bsd + ;; cray) basic_machine=j90-cray os=unicos ;; - craynv) - basic_machine=craynv-cray - os=unicosmp + crds | unos) + basic_machine=m68k-crds + os= + ;; + da30) + basic_machine=m68k-da30 + os= + ;; + decstation | pmax | pmin | dec3100 | decstatn) + basic_machine=mips-dec + os= ;; delta88) basic_machine=m88k-motorola @@ -286,13 +337,13 @@ case $1 in basic_machine=m88k-harris os=sysv3 ;; - hp300bsd) + hp300 | hp300hpux) basic_machine=m68k-hp - os=bsd + os=hpux ;; - hp300hpux) + hp300bsd) basic_machine=m68k-hp - os=hpux + os=bsd ;; hppaosf) basic_machine=hppa1.1-hp @@ -306,10 +357,6 @@ case $1 in basic_machine=i386-mach os=mach ;; - vsta) - basic_machine=i386-unknown - os=vsta - ;; isi68 | isi) basic_machine=m68k-isi os=sysv @@ -371,7 +418,7 @@ case $1 in os=sysv4 ;; netbsd386) - basic_machine=i386-unknown + basic_machine=i386-pc os=netbsd ;; netwinder) @@ -454,14 +501,26 @@ case $1 in basic_machine=mips-sei os=seiux ;; + sequent) + basic_machine=i386-sequent + os= + ;; sps7) basic_machine=m68k-bull os=sysv2 ;; + st2000) + basic_machine=m68k-tandem + os= + ;; stratus) basic_machine=i860-stratus os=sysv4 ;; + sun2) + basic_machine=m68000-sun + os= + ;; sun2os3) basic_machine=m68000-sun os=sunos3 @@ -470,6 +529,10 @@ case $1 in basic_machine=m68000-sun os=sunos4 ;; + sun3) + basic_machine=m68k-sun + os= + ;; sun3os3) basic_machine=m68k-sun os=sunos3 @@ -478,6 +541,10 @@ case $1 in basic_machine=m68k-sun os=sunos4 ;; + sun4) + basic_machine=sparc-sun + os= + ;; sun4os3) basic_machine=sparc-sun os=sunos3 @@ -490,6 +557,10 @@ case $1 in basic_machine=sparc-sun os=solaris2 ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + os= + ;; sv1) basic_machine=sv1-cray os=unicos @@ -534,6 +605,10 @@ case $1 in basic_machine=vax-dec os=vms ;; + vsta) + basic_machine=i386-pc + os=vsta + ;; vxworks960) basic_machine=i960-wrs os=vxworks @@ -562,417 +637,162 @@ case $1 in ;; esac -# Decode aliases for certain CPU-COMPANY combinations. +# Decode 1-component or ad-hoc basic machines case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv6m | armv[78][arm] \ - | avr | avr32 \ - | ba \ - | be32 | be64 \ - | bfin \ - | c4x | c8051 | clipper | csky \ - | d10v | d30v | dlx | dsp16xx \ - | e2k | epiphany \ - | fido | fr30 | frv | ft32 \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia16 | ia64 \ - | ip2k | iq2000 \ - | k1om \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa32r6 | mipsisa32r6el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64r6 | mipsisa64r6el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nfp \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 | or1k | or1knd | or32 \ - | pdp10 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pru \ - | pyramid \ - | riscv | riscv32 | riscv64 \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | visium \ - | wasm32 \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown - ;; - c54x) - basic_machine=tic54x-unknown - ;; - c55x) - basic_machine=tic55x-unknown - ;; - c6x) - basic_machine=tic6x-unknown - ;; - leon|leon[3-9]) - basic_machine=sparc-$basic_machine - ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) - basic_machine=$basic_machine-unknown - os=${os:-none} - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) + # Here we handle the default manufacturer of certain CPU types. It is in + # some cases the only manufacturer, in others, it is the most popular. + w89k) + cpu=hppa1.1 + vendor=winbond ;; - m9s12z | m68hcs12z | hcs12z | s12z) - basic_machine=s12z-unknown - os=${os:-none} + op50n) + cpu=hppa1.1 + vendor=oki ;; - ms1) - basic_machine=mt-unknown + op60c) + cpu=hppa1.1 + vendor=oki ;; - strongarm | thumb | xscale) - basic_machine=arm-unknown + ibm*) + cpu=i370 + vendor=ibm ;; - xgate) - basic_machine=$basic_machine-unknown - os=${os:-none} + orion105) + cpu=clipper + vendor=highlevel ;; - xscaleeb) - basic_machine=armeb-unknown + mac | mpw | mac-mpw) + cpu=m68k + vendor=apple ;; - - xscaleel) - basic_machine=armel-unknown + pmac | pmac-mpw) + cpu=powerpc + vendor=apple ;; - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | ba-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | c8051-* | clipper-* | craynv-* | csky-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | e2k-* | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ - | ip2k-* | iq2000-* \ - | k1om-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa32r6-* | mipsisa32r6el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64r6-* | mipsisa64r6el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nfp-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | or1k*-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pru-* \ - | pyramid-* \ - | riscv-* | riscv32-* | riscv64-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | visium-* \ - | wasm32-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att + cpu=m68000 + vendor=att ;; 3b*) - basic_machine=we32k-att - ;; - abacus) - basic_machine=abacus-unknown - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - asmjs) - basic_machine=asmjs-unknown - ;; - blackfin-*) - basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=linux + cpu=we32k + vendor=att ;; bluegene*) - basic_machine=powerpc-ibm + cpu=powerpc + vendor=ibm os=cnk ;; - c54x-*) - basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=${os:-unicos} - ;; - convex-c1) - basic_machine=c1-convex - os=bsd - ;; - convex-c2) - basic_machine=c2-convex - os=bsd - ;; - convex-c32) - basic_machine=c32-convex - os=bsd - ;; - convex-c34) - basic_machine=c34-convex - os=bsd - ;; - convex-c38) - basic_machine=c38-convex - os=bsd - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=${os:-elf} - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=${os:-elf} - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; decsystem10* | dec10*) - basic_machine=pdp10-dec + cpu=pdp10 + vendor=dec os=tops10 ;; decsystem20* | dec20*) - basic_machine=pdp10-dec + cpu=pdp10 + vendor=dec os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=${os:-bosx} + cpu=m68k + vendor=motorola ;; dpx2*) - basic_machine=m68k-bull + cpu=m68k + vendor=bull os=sysv3 ;; - e500v[12]) - basic_machine=powerpc-unknown - os=$os"spe" - ;; - e500v[12]-*) - basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=$os"spe" - ;; encore | umax | mmax) - basic_machine=ns32k-encore + cpu=ns32k + vendor=encore ;; elxsi) - basic_machine=elxsi-elxsi + cpu=elxsi + vendor=elxsi os=${os:-bsd} ;; fx2800) - basic_machine=i860-alliant + cpu=i860 + vendor=alliant ;; genix) - basic_machine=ns32k-ns + cpu=ns32k + vendor=ns ;; h3050r* | hiux*) - basic_machine=hppa1.1-hitachi + cpu=hppa1.1 + vendor=hitachi os=hiuxwe2 ;; - hp300-*) - basic_machine=m68k-hp - ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp + cpu=hppa1.0 + vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp + cpu=m68000 + vendor=hp ;; hp9k3[2-9][0-9]) - basic_machine=m68k-hp + cpu=m68k + vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp + cpu=hppa1.0 + vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp + cpu=hppa1.1 + vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm + cpu=hppa1.0 + vendor=hp ;; i*86v32) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc os=sysv32 ;; i*86v4*) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc os=sysv4 ;; i*86v) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc os=sysv ;; i*86sol2) - basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc os=solaris2 ;; j90 | j90-cray) - basic_machine=j90-cray + cpu=j90 + vendor=cray os=${os:-unicos} ;; iris | iris4d) - basic_machine=mips-sgi + cpu=mips + vendor=sgi case $os in irix*) ;; @@ -981,40 +801,27 @@ case $basic_machine in ;; esac ;; - leon-*|leon[3-9]-*) - basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` - ;; - m68knommu-*) - basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=linux - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; miniframe) - basic_machine=m68000-convergent + cpu=m68000 + vendor=convergent ;; *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari + cpu=m68k + vendor=atari os=mint ;; - mips3*-*) - basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown - ;; - ms1-*) - basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` - ;; news-3600 | risc-news) - basic_machine=mips-sony + cpu=mips + vendor=sony os=newsos ;; next | m*-next) - basic_machine=m68k-next + cpu=m68k + vendor=next case $os in - nextstep* ) + openstep*) + ;; + nextstep*) ;; ns2*) os=nextstep2 @@ -1025,260 +832,442 @@ case $basic_machine in esac ;; np1) - basic_machine=np1-gould + cpu=np1 + vendor=gould ;; - neo-tandem) - basic_machine=neo-tandem + op50n-* | op60c-*) + cpu=hppa1.1 + vendor=oki + os=proelf ;; - nse-tandem) - basic_machine=nse-tandem + pa-hitachi) + cpu=hppa1.1 + vendor=hitachi + os=hiuxwe2 ;; - nsr-tandem) - basic_machine=nsr-tandem + pbd) + cpu=sparc + vendor=tti ;; - nsv-tandem) - basic_machine=nsv-tandem + pbb) + cpu=m68k + vendor=tti ;; - nsx-tandem) - basic_machine=nsx-tandem + pc532) + cpu=ns32k + vendor=pc532 ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=proelf + pn) + cpu=pn + vendor=gould ;; - openrisc | openrisc-*) - basic_machine=or32-unknown + power) + cpu=power + vendor=ibm ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=hiuxwe2 + ps2) + cpu=i386 + vendor=ibm ;; - parisc-*) - basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` - os=linux + rm[46]00) + cpu=mips + vendor=siemens ;; - pbd) - basic_machine=sparc-tti + rtpc | rtpc-*) + cpu=romp + vendor=ibm ;; - pbb) - basic_machine=m68k-tti + sde) + cpu=mipsisa32 + vendor=sde + os=${os:-elf} ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 + simso-wrs) + cpu=sparclite + vendor=wrs + os=vxworks ;; - pc98) - basic_machine=i386-pc + tower | tower-32) + cpu=m68k + vendor=ncr ;; - pc98-*) - basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` + vpp*|vx|vx-*) + cpu=f301 + vendor=fujitsu ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc + w65) + cpu=w65 + vendor=wdc ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc + w89k-*) + cpu=hppa1.1 + vendor=winbond + os=proelf ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc + none) + cpu=none + vendor=none ;; - pentium4) - basic_machine=i786-pc + leon|leon[3-9]) + cpu=sparc + vendor=$basic_machine ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` + leon-*|leon[3-9]-*) + cpu=sparc + vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + + *-*) + # shellcheck disable=SC2162 + IFS="-" read cpu vendor <<EOF +$basic_machine +EOF ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + cpu=$basic_machine + vendor=pc ;; - pentium4-*) - basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` + # These rules are duplicated from below for sake of the special case above; + # i.e. things that normalized to x86 arches should also default to "pc" + pc98) + cpu=i386 + vendor=pc ;; - pn) - basic_machine=pn-gould + x64 | amd64) + cpu=x86_64 + vendor=pc + ;; + # Recognize the basic CPU types without company name. + *) + cpu=$basic_machine + vendor=unknown + ;; +esac + +unset -v basic_machine + +# Decode basic machines in the full and proper CPU-Company form. +case $cpu-$vendor in + # Here we handle the default manufacturer of certain CPU types in canonical form. It is in + # some cases the only manufacturer, in others, it is the most popular. + craynv-unknown) + vendor=cray + os=${os:-unicosmp} + ;; + c90-unknown | c90-cray) + vendor=cray + os=${os:-unicos} ;; - power) basic_machine=power-ibm + fx80-unknown) + vendor=alliant ;; - ppc | ppcbe) basic_machine=powerpc-unknown + romp-unknown) + vendor=ibm ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + mmix-unknown) + vendor=knuth ;; - ppcle | powerpclittle) - basic_machine=powerpcle-unknown + microblaze-unknown | microblazeel-unknown) + vendor=xilinx ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` + rs6000-unknown) + vendor=ibm ;; - ppc64) basic_machine=powerpc64-unknown + vax-unknown) + vendor=dec ;; - ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` + pdp11-unknown) + vendor=dec ;; - ppc64le | powerpc64little) - basic_machine=powerpc64le-unknown + we32k-unknown) + vendor=att ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` + cydra-unknown) + vendor=cydrome ;; - ps2) - basic_machine=i386-ibm + i370-ibm*) + vendor=ibm ;; - rm[46]00) - basic_machine=mips-siemens + orion-unknown) + vendor=highlevel ;; - rtpc | rtpc-*) - basic_machine=romp-ibm + xps-unknown | xps100-unknown) + cpu=xps100 + vendor=honeywell ;; - s390 | s390-*) - basic_machine=s390-ibm + + # Here we normalize CPU types with a missing or matching vendor + dpx20-unknown | dpx20-bull) + cpu=rs6000 + vendor=bull + os=${os:-bosx} ;; - s390x | s390x-*) - basic_machine=s390x-ibm + + # Here we normalize CPU types irrespective of the vendor + amd64-*) + cpu=x86_64 ;; - sb1) - basic_machine=mipsisa64sb1-unknown + blackfin-*) + cpu=bfin + os=linux ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown + c54x-*) + cpu=tic54x ;; - sde) - basic_machine=mipsisa32-sde - os=${os:-elf} + c55x-*) + cpu=tic55x ;; - sequent) - basic_machine=i386-sequent + c6x-*) + cpu=tic6x ;; - sh5el) - basic_machine=sh5le-unknown + e500v[12]-*) + cpu=powerpc + os=$os"spe" ;; - simso-wrs) - basic_machine=sparclite-wrs - os=vxworks + mips3*-*) + cpu=mips64 ;; - spur) - basic_machine=spur-unknown + ms1-*) + cpu=mt ;; - st2000) - basic_machine=m68k-tandem + m68knommu-*) + cpu=m68k + os=linux ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` + m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*) + cpu=s12z ;; - sun2) - basic_machine=m68000-sun + openrisc-*) + cpu=or32 ;; - sun3 | sun3-*) - basic_machine=m68k-sun + parisc-*) + cpu=hppa + os=linux ;; - sun4) - basic_machine=sparc-sun + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + cpu=i586 ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun + pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*) + cpu=i686 ;; - tile*) - basic_machine=$basic_machine-unknown - os=linux-gnu + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + cpu=i686 ;; - tx39) - basic_machine=mipstx39-unknown + pentium4-*) + cpu=i786 ;; - tx39el) - basic_machine=mipstx39el-unknown + pc98-*) + cpu=i386 ;; - tower | tower-32) - basic_machine=m68k-ncr + ppc-* | ppcbe-*) + cpu=powerpc ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu + ppcle-* | powerpclittle-*) + cpu=powerpcle ;; - w65*) - basic_machine=w65-wdc - os=none + ppc64-*) + cpu=powerpc64 ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=proelf + ppc64le-* | powerpc64little-*) + cpu=powerpc64le ;; - x64) - basic_machine=x86_64-pc + sb1-*) + cpu=mipsisa64sb1 ;; - xps | xps100) - basic_machine=xps100-honeywell + sb1el-*) + cpu=mipsisa64sb1el ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` + sh5e[lb]-*) + cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'` ;; - none) - basic_machine=none-none - os=${os:-none} + spur-*) + cpu=spur ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond + strongarm-* | thumb-*) + cpu=arm ;; - op50n) - basic_machine=hppa1.1-oki + tx39-*) + cpu=mipstx39 ;; - op60c) - basic_machine=hppa1.1-oki + tx39el-*) + cpu=mipstx39el ;; - romp) - basic_machine=romp-ibm + x64-*) + cpu=x86_64 ;; - mmix) - basic_machine=mmix-knuth + xscale-* | xscalee[bl]-*) + cpu=`echo "$cpu" | sed 's/^xscale/arm/'` ;; - rs6000) - basic_machine=rs6000-ibm + + # Recognize the canonical CPU Types that limit and/or modify the + # company names they are paired with. + cr16-*) + os=${os:-elf} ;; - vax) - basic_machine=vax-dec + crisv32-* | etraxfs*-*) + cpu=crisv32 + vendor=axis ;; - pdp11) - basic_machine=pdp11-dec + cris-* | etrax*-*) + cpu=cris + vendor=axis ;; - we32k) - basic_machine=we32k-att + crx-*) + os=${os:-elf} ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown + neo-tandem) + cpu=neo + vendor=tandem ;; - cydra) - basic_machine=cydra-cydrome + nse-tandem) + cpu=nse + vendor=tandem ;; - orion) - basic_machine=orion-highlevel + nsr-tandem) + cpu=nsr + vendor=tandem ;; - orion105) - basic_machine=clipper-highlevel + nsv-tandem) + cpu=nsv + vendor=tandem ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple + nsx-tandem) + cpu=nsx + vendor=tandem ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple + s390-*) + cpu=s390 + vendor=ibm ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. + s390x-*) + cpu=s390x + vendor=ibm ;; + tile*-*) + os=${os:-linux-gnu} + ;; + *) - echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 - exit 1 + # Recognize the canonical CPU types that are allowed with any + # company name. + case $cpu in + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | abacus \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ + | alphapca5[67] | alpha64pca5[67] \ + | am33_2.0 \ + | amdgcn \ + | arc | arceb \ + | arm | arm[lb]e | arme[lb] | armv* \ + | avr | avr32 \ + | asmjs \ + | ba \ + | be32 | be64 \ + | bfin | bpf | bs2000 \ + | c[123]* | c30 | [cjt]90 | c4x \ + | c8051 | clipper | craynv | csky | cydra \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | elxsi | epiphany \ + | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ + | h8300 | h8500 \ + | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i*86 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle \ + | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ + | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ + | m88110 | m88k | maxq | mb | mcore | mep | metag \ + | microblaze | microblazeel \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64eb | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mmix \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nfp \ + | nios | nios2 | nios2eb | nios2el \ + | none | np1 | ns16k | ns32k | nvptx \ + | open8 \ + | or1k* \ + | or32 \ + | orion \ + | picochip \ + | pdp10 | pdp11 | pj | pjl | pn | power \ + | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \ + | pru \ + | pyramid \ + | riscv | riscv32 | riscv64 \ + | rl78 | romp | rs6000 | rx \ + | score \ + | sh | shl \ + | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \ + | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \ + | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ + | spu \ + | tahoe \ + | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ + | tron \ + | ubicom32 \ + | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ + | vax \ + | visium \ + | w65 \ + | wasm32 | wasm64 \ + | we32k \ + | x86 | x86_64 | xc16x | xgate | xps100 \ + | xstormy16 | xtensa* \ + | ymp \ + | z8k | z80) + ;; + + *) + echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 + exit 1 + ;; + esac ;; esac # Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` +case $vendor in + digital*) + vendor=dec ;; - *-commodore*) - basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` + commodore*) + vendor=cbm ;; *) ;; @@ -1356,9 +1345,9 @@ case $os in | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ | aos* | aros* | cloudabi* | sortix* \ | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ - | clix* | riscos* | uniplus* | iris* | rtu* | xenix* \ + | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ | knetbsd* | mirbsd* | netbsd* \ - | bitrig* | openbsd* | solidbsd* | libertybsd* \ + | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \ | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \ | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ @@ -1376,12 +1365,13 @@ case $os in | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ | skyos* | haiku* | rdos* | toppers* | drops* | es* \ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ - | midnightbsd*) + | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ + | nsk* | powerunix) # Remember, each alternative MUST END IN *, to match a version number. ;; qnx*) - case $basic_machine in - x86-* | i*86-*) + case $cpu in + x86 | i*86) ;; *) os=nto-$os @@ -1460,9 +1450,6 @@ case $os in ns2) os=nextstep2 ;; - nsk*) - os=nsk - ;; # Preserve the version number of sinix5. sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` @@ -1507,7 +1494,7 @@ case $os in # Until real need of OS specific support for # particular features comes up, bare metal # configurations are quite functional. - case $basic_machine in + case $cpu in arm*) os=eabi ;; @@ -1541,7 +1528,7 @@ else # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. -case $basic_machine in +case $cpu-$vendor in score-*) os=elf ;; @@ -1722,9 +1709,8 @@ fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) +case $vendor in + unknown) case $os in riscix*) vendor=acorn @@ -1793,11 +1779,10 @@ case $basic_machine in vendor=stratus ;; esac - basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac -echo "$basic_machine-$os" +echo "$cpu-$vendor-$os" exit # Local variables: diff --git a/depends/packages/native_libdmg-hfsplus.mk b/depends/packages/native_libdmg-hfsplus.mk index a4ffb6046c..8493f1d979 100644 --- a/depends/packages/native_libdmg-hfsplus.mk +++ b/depends/packages/native_libdmg-hfsplus.mk @@ -1,16 +1,18 @@ package=native_libdmg-hfsplus -$(package)_version=0.1 -$(package)_download_path=https://github.com/theuni/libdmg-hfsplus/archive -$(package)_file_name=libdmg-hfsplus-v$($(package)_version).tar.gz -$(package)_sha256_hash=6569a02eb31c2827080d7d59001869ea14484c281efab0ae7f2b86af5c3120b3 +$(package)_version=7ac55ec64c96f7800d9818ce64c79670e7f02b67 +$(package)_download_path=https://github.com/planetbeing/libdmg-hfsplus/archive +$(package)_file_name=$($(package)_version).tar.gz +$(package)_sha256_hash=56fbdc48ec110966342f0ecddd6f8f89202f4143ed2a3336e42bbf88f940850c $(package)_build_subdir=build +$(package)_patches=remove-libcrypto-dependency.patch define $(package)_preprocess_cmds + patch -p1 < $($(package)_patch_dir)/remove-libcrypto-dependency.patch && \ mkdir build endef define $(package)_config_cmds - cmake -DCMAKE_INSTALL_PREFIX:PATH=$(build_prefix)/bin .. + cmake -DCMAKE_INSTALL_PREFIX:PATH=$(build_prefix) .. endef define $(package)_build_cmds diff --git a/depends/patches/native_libdmg-hfsplus/remove-libcrypto-dependency.patch b/depends/patches/native_libdmg-hfsplus/remove-libcrypto-dependency.patch new file mode 100644 index 0000000000..f346c8f2cf --- /dev/null +++ b/depends/patches/native_libdmg-hfsplus/remove-libcrypto-dependency.patch @@ -0,0 +1,45 @@ +From 3e5fd3fb56bc9ff03beb535979e33dcf83fe1f70 Mon Sep 17 00:00:00 2001 +From: Cory Fields <cory-nospam-@coryfields.com> +Date: Thu, 8 May 2014 12:39:42 -0400 +Subject: [PATCH] dmg: remove libcrypto dependency + +--- + dmg/CMakeLists.txt | 16 ---------------- + 1 file changed, 16 deletions(-) + +diff --git a/dmg/CMakeLists.txt b/dmg/CMakeLists.txt +index eec62d6..3969f64 100644 +--- a/dmg/CMakeLists.txt ++++ b/dmg/CMakeLists.txt +@@ -1,12 +1,5 @@ +-INCLUDE(FindOpenSSL) + INCLUDE(FindZLIB) + +-FIND_LIBRARY(CRYPTO_LIBRARIES crypto +- PATHS +- /usr/lib +- /usr/local/lib +- ) +- + IF(NOT ZLIB_FOUND) + message(FATAL_ERROR "zlib is required for dmg!") + ENDIF(NOT ZLIB_FOUND) +@@ -18,15 +11,6 @@ link_directories(${PROJECT_BINARY_DIR}/common ${PROJECT_BINARY_DIR}/hfs) + + add_library(dmg adc.c base64.c checksum.c dmgfile.c dmglib.c filevault.c io.c partition.c resources.c udif.c) + +-IF(OPENSSL_FOUND) +- add_definitions(-DHAVE_CRYPT) +- include_directories(${OPENSSL_INCLUDE_DIR}) +- target_link_libraries(dmg ${CRYPTO_LIBRARIES}) +- IF(WIN32) +- TARGET_LINK_LIBRARIES(dmg gdi32) +- ENDIF(WIN32) +-ENDIF(OPENSSL_FOUND) +- + target_link_libraries(dmg common hfs z) + + add_executable(dmg-bin dmg.c) +-- +2.22.0 + diff --git a/doc/benchmarking.md b/doc/benchmarking.md index 8e3d88ab7a..b1a06009b5 100644 --- a/doc/benchmarking.md +++ b/doc/benchmarking.md @@ -11,7 +11,7 @@ Running For benchmarks purposes you only need to compile `bitcoin_bench`. Beware of configuring without `--enable-debug` as this would impact benchmarking by unlatching log printers and lock analysis. - make -C src bench_bitcoin + make -C src bitcoin_bench After compiling bitcoin-core, the benchmarks can be run with: diff --git a/doc/bips.md b/doc/bips.md index 71ff5552ee..45562cec62 100644 --- a/doc/bips.md +++ b/doc/bips.md @@ -15,26 +15,26 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.19.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)). As of **v0.13.0**, this is only available for `NODE_BLOOM` (BIP 111) peers. * [`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)). Disabled by default since **v0.19.0**, can be enabled by the `-peerbloomfilters` option. * [`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)). Starting **v0.17.0**, whether to send reject messages can be configured with the `-enablebip61` option, and support is deprecated as of **v0.18.0**. +* [`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, and support is deprecated (disabled by default) as of **v0.18.0**. Support was removed in **v0.20.0** ([PR #15437](https://github.com/bitcoin/bitcoin/pull/15437)). * [`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*. +* [`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 *buried* since **v0.19.0** ([PR #16060](https://github.com/bitcoin/bitcoin/pull/16060)). * [`BIP 70`](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki) [`71`](https://github.com/bitcoin/bips/blob/master/bip-0071.mediawiki) [`72`](https://github.com/bitcoin/bips/blob/master/bip-0072.mediawiki): Payment Protocol support has been available in Bitcoin Core GUI since **v0.9.0** ([PR #5216](https://github.com/bitcoin/bitcoin/pull/5216)). Support can be optionally disabled at build time since **v0.18.0** ([PR 14451](https://github.com/bitcoin/bitcoin/pull/14451)), and is disabled by default at build time since **v0.19.0** ([PR #15584](https://github.com/bitcoin/bitcoin/pull/15584)). * [`BIP 90`](https://github.com/bitcoin/bips/blob/master/bip-0090.mediawiki): Trigger mechanism for activation of BIPs 34, 65, and 66 has been simplified to block height checks since **v0.14.0** ([PR #8391](https://github.com/bitcoin/bitcoin/pull/8391)). * [`BIP 111`](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki): `NODE_BLOOM` service bit added, and enforced for all peer versions as of **v0.13.0** ([PR #6579](https://github.com/bitcoin/bitcoin/pull/6579) and [PR #6641](https://github.com/bitcoin/bitcoin/pull/6641)). -* [`BIP 112`](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki): The CHECKSEQUENCEVERIFY opcode has been implemented since **v0.12.1** ([PR #7524](https://github.com/bitcoin/bitcoin/pull/7524)) and has been activated since *block 419328*. -* [`BIP 113`](https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki): Median time past lock-time calculations have been implemented since **v0.12.1** ([PR #6566](https://github.com/bitcoin/bitcoin/pull/6566)) and have been activated since *block 419328*. +* [`BIP 112`](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki): The CHECKSEQUENCEVERIFY opcode has been implemented since **v0.12.1** ([PR #7524](https://github.com/bitcoin/bitcoin/pull/7524)), and has been *buried* since **v0.19.0** ([PR #16060](https://github.com/bitcoin/bitcoin/pull/16060)). +* [`BIP 113`](https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki): Median time past lock-time calculations have been implemented since **v0.12.1** ([PR #6566](https://github.com/bitcoin/bitcoin/pull/6566)), and has been *buried* since **v0.19.0** ([PR #16060](https://github.com/bitcoin/bitcoin/pull/16060)). * [`BIP 125`](https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki): Opt-in full replace-by-fee signaling honoured in mempool and mining as of **v0.12.0** ([PR 6871](https://github.com/bitcoin/bitcoin/pull/6871)). Enabled by default in the wallet GUI as of **v0.18.1** ([PR #11605](https://github.com/bitcoin/bitcoin/pull/11605)) * [`BIP 130`](https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki): direct headers announcement is negotiated with peer versions `>=70012` as of **v0.12.0** ([PR 6494](https://github.com/bitcoin/bitcoin/pull/6494)). * [`BIP 133`](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki): feefilter messages are respected and sent for peer versions `>=70013` as of **v0.13.0** ([PR 7542](https://github.com/bitcoin/bitcoin/pull/7542)). -* [`BIP 141`](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki): Segregated Witness (Consensus Layer) as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)), and defined for mainnet as of **v0.13.1** ([PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)). -* [`BIP 143`](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki): Transaction Signature Verification for Version 0 Witness Program as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)) and defined for mainnet as of **v0.13.1** ([PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)). +* [`BIP 141`](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki): Segregated Witness (Consensus Layer) as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)), defined for mainnet as of **v0.13.1** ([PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)), and *buried* since **v0.19.0** ([PR #16060](https://github.com/bitcoin/bitcoin/pull/16060)). +* [`BIP 143`](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki): Transaction Signature Verification for Version 0 Witness Program as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)), defined for mainnet as of **v0.13.1** ([PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)), and *buried* since **v0.19.0** ([PR #16060](https://github.com/bitcoin/bitcoin/pull/16060)). * [`BIP 144`](https://github.com/bitcoin/bips/blob/master/bip-0144.mediawiki): Segregated Witness as of **0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)). * [`BIP 145`](https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki): getblocktemplate updates for Segregated Witness as of **v0.13.0** ([PR 8149](https://github.com/bitcoin/bitcoin/pull/8149)). -* [`BIP 147`](https://github.com/bitcoin/bips/blob/master/bip-0147.mediawiki): NULLDUMMY softfork as of **v0.13.1** ([PR 8636](https://github.com/bitcoin/bitcoin/pull/8636) and [PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)). +* [`BIP 147`](https://github.com/bitcoin/bips/blob/master/bip-0147.mediawiki): NULLDUMMY softfork as of **v0.13.1** ([PR 8636](https://github.com/bitcoin/bitcoin/pull/8636) and [PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)), *buried* since **v0.19.0** ([PR #16060](https://github.com/bitcoin/bitcoin/pull/16060)). * [`BIP 152`](https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki): Compact block transfer and related optimizations are used as of **v0.13.0** ([PR 8068](https://github.com/bitcoin/bitcoin/pull/8068)). - [`BIP 158`](https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki): Compact Block Filters for Light Clients can be indexed as of **v0.19.0** ([PR #14121](https://github.com/bitcoin/bitcoin/pull/14121)). -* [`BIP 159`](https://github.com/bitcoin/bips/blob/master/bip-0159.mediawiki): The NODE_NETWORK_LIMITED service bit is signalled as of **v0.16.0** ([PR 11740](https://github.com/bitcoin/bitcoin/pull/11740)), and such nodes are connected to as of **v0.17.0** ([PR 10387](https://github.com/bitcoin/bitcoin/pull/10387)). -* [`BIP 173`](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki): Bech32 addresses for native Segregated Witness outputs are supported as of **v0.16.0** ([PR 11167](https://github.com/bitcoin/bitcoin/pull/11167)). +* [`BIP 159`](https://github.com/bitcoin/bips/blob/master/bip-0159.mediawiki): The `NODE_NETWORK_LIMITED` service bit is signalled as of **v0.16.0** ([PR 11740](https://github.com/bitcoin/bitcoin/pull/11740)), and such nodes are connected to as of **v0.17.0** ([PR 10387](https://github.com/bitcoin/bitcoin/pull/10387)). +* [`BIP 173`](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki): Bech32 addresses for native Segregated Witness outputs are supported as of **v0.16.0** ([PR 11167](https://github.com/bitcoin/bitcoin/pull/11167)). Bech32 addresses are generated by default as of **v0.20.0** ([PR 16884](https://github.com/bitcoin/bitcoin/pull/16884)). * [`BIP 174`](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki): RPCs to operate on Partially Signed Bitcoin Transactions (PSBT) are present as of **v0.17.0** ([PR 13557](https://github.com/bitcoin/bitcoin/pull/13557)). * [`BIP 176`](https://github.com/bitcoin/bips/blob/master/bip-0176.mediawiki): Bits Denomination [QT only] is supported as of **v0.16.0** ([PR 12035](https://github.com/bitcoin/bitcoin/pull/12035)). diff --git a/doc/descriptors.md b/doc/descriptors.md index dbdac2c5b6..a98f43737e 100644 --- a/doc/descriptors.md +++ b/doc/descriptors.md @@ -23,6 +23,7 @@ Output descriptors currently support: - Pay-to-script-hash scripts (P2SH), through the `sh` function. - Pay-to-witness-script-hash scripts (P2WSH), through the `wsh` function. - Multisig scripts, through the `multi` function. +- Multisig scripts where the public keys are sorted lexicographically, through the `sortedmulti` function. - Any type of supported address through the `addr` function. - Raw hex scripts through the `raw` function. - Public keys (compressed and uncompressed) in hex notation, or BIP32 extended pubkeys with derivation paths. @@ -37,12 +38,14 @@ Output descriptors currently support: - `sh(wsh(pkh(02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13)))` describes an (overly complicated) P2SH-P2WSH-P2PKH output with the specified public key. - `multi(1,022f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4,025cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc)` describes a bare *1-of-2* multisig output with keys in the specified order. - `sh(multi(2,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01,03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe))` describes a P2SH *2-of-2* multisig output with keys in the specified order. +- `sh(sortedmulti(2,03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe,022f01e5e15cca351daff3843fb70f3c2f0a1bdd05e5af888a67784ef3e10a2a01))` describes a P2SH *2-of-2* multisig output with keys sorted lexicographically in the resulting redeemScript. - `wsh(multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a))` describes a P2WSH *2-of-3* multisig output with keys in the specified order. - `sh(wsh(multi(1,03f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8,03499fdf9e895e719cfd64e67f07d38e3226aa7b63678949e6e49b241a60e823e4,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e)))` describes a P2SH-P2WSH *1-of-3* multisig output with keys in the specified order. - `pk(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8)` describes a P2PK output with the public key of the specified xpub. - `pkh(xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw/1'/2)` describes a P2PKH output with child key *1'/2* of the specified xpub. - `pkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*)` describes a set of P2PKH outputs, but additionally specifies that the specified xpub is a child of a master with fingerprint `d34db33f`, and derived using path `44'/0'/0'`. - `wsh(multi(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*))` describes a set of *1-of-2* P2WSH multisig outputs where the first multisig key is the *1/0/`i`* child of the first specified xpub and the second multisig key is the *0/0/`i`* child of the second specified xpub, and `i` is any number in a configurable range (`0-1000` by default). +- `wsh(sortedmulti(1,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*))` describes a set of *1-of-2* P2WSH multisig outputs where one multisig key is the *1/0/`i`* child of the first specified xpub and the other multisig key is the *0/0/`i`* child of the second specified xpub, and `i` is any number in a configurable range (`0-1000` by default). The order of public keys in the resulting witnessScripts is determined by the lexicographic order of the public keys at that index. ## Reference @@ -56,6 +59,7 @@ Descriptors consist of several types of expressions. The top level expression is - `wpkh(KEY)` (not inside `wsh`): P2WPKH output for the given compressed pubkey. - `combo(KEY)` (top level only): an alias for the collection of `pk(KEY)` and `pkh(KEY)`. If the key is compressed, it also includes `wpkh(KEY)` and `sh(wpkh(KEY))`. - `multi(k,KEY_1,KEY_2,...,KEY_n)` (anywhere): k-of-n multisig script. +- `sortedmulti(k,KEY_1,KEY_2,...,KEY_n)` (anywhere): k-of-n multisig script with keys sorted lexicographically in the resulting script. - `addr(ADDR)` (top level only): the script which ADDR expands to. - `raw(HEX)` (top level only): the script whose hex encoding is HEX. @@ -101,11 +105,12 @@ not contain "p2" for brevity. Several pieces of software use multi-signature (multisig) scripts based on Bitcoin's OP_CHECKMULTISIG opcode. To support these, we introduce the -`multi(k,key_1,key_2,...,key_n)` function. It represents a *k-of-n* +`multi(k,key_1,key_2,...,key_n)` and `sortedmulti(k,key_1,key_2,...,key_n)` +functions. They represent a *k-of-n* multisig policy, where any *k* out of the *n* provided `KEY` expressions must sign. -Key order is significant. A `multi()` expression describes a multisig script +Key order is significant for `multi()`. A `multi()` expression describes a multisig script with keys in the specified order, and in a search for TXOs, it will not match outputs with multisig scriptPubKeys that have the same keys in a different order. Also, to prevent a combinatorial explosion of the search space, if more @@ -114,6 +119,10 @@ or `*'`, the `multi()` expression only matches multisig scripts with the `i`th child key from each wildcard path in lockstep, rather than scripts with any combination of child keys from each wildcard path. +Key order does not matter for `sortedmulti()`. `sortedmulti()` behaves in the same way +as `multi()` does but the keys are reordered in the resulting script such that they +are lexicographically ordered as described in BIP67. + ### BIP32 derived keys and chains Most modern wallet software and hardware uses keys that are derived using diff --git a/doc/developer-notes.md b/doc/developer-notes.md index f4a5e2d330..9cf4b4b075 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -87,7 +87,6 @@ code. - `++i` is preferred over `i++`. - `nullptr` is preferred over `NULL` or `(void*)0`. - `static_assert` is preferred over `assert` where possible. Generally; compile-time checking is preferred over run-time checking. - - `enum class` is preferred over `enum` where possible. Scoped enumerations avoid two potential pitfalls/problems with traditional C++ enumerations: implicit conversions to int, and name clashes due to enumerators being exported to the surrounding scope. Block style example: ```c++ @@ -563,6 +562,34 @@ class A - *Rationale*: Easier to understand what is happening, thus easier to spot mistakes, even for those that are not language lawyers. +- Prefer `enum class` (scoped enumerations) over `enum` (traditional enumerations) where possible. + + - *Rationale*: Scoped enumerations avoid two potential pitfalls/problems with traditional C++ enumerations: implicit conversions to `int`, and name clashes due to enumerators being exported to the surrounding scope. + +- `switch` statement on an enumeration example: + +```cpp +enum class Tabs { + INFO, + CONSOLE, + GRAPH, + PEERS +}; + +int GetInt(Tabs tab) +{ + switch (tab) { + case Tabs::INFO: return 0; + case Tabs::CONSOLE: return 1; + case Tabs::GRAPH: return 2; + case Tabs::PEERS: return 3; + } // no default case, so the compiler can warn about missing cases + assert(false); +} +``` + +*Rationale*: The comment documents skipping `default:` label, and it complies with `clang-format` rules. The assertion prevents firing of `-Wreturn-type` warning on some compilers. + Strings and formatting ------------------------ diff --git a/doc/files.md b/doc/files.md index 85c27f3fd0..c2296b45fa 100644 --- a/doc/files.md +++ b/doc/files.md @@ -1,37 +1,102 @@ -Filename | Description ---------------------|---------------------------------------------------------------------------------------------------------------------------- -banlist.dat | stores the IPs/Subnets of banned nodes -bitcoin.conf | contains configuration settings for bitcoind or bitcoin-qt -bitcoind.pid | stores the process id of bitcoind while running -blocks/blk000??.dat | block data (custom, 128 MiB per file); since 0.8.0 -blocks/rev000??.dat | block undo data (custom); since 0.8.0 (format changed since pre-0.8) -blocks/index/* | block index (LevelDB); since 0.8.0 -chainstate/* | blockchain state database (LevelDB); since 0.8.0 -database/* | BDB database environment; only used for wallet since 0.8.0; moved to wallets/ directory on new installs since 0.16.0 -db.log | wallet database log file; moved to wallets/ directory on new installs since 0.16.0 -debug.log | contains debug information and general logging generated by bitcoind or bitcoin-qt -fee_estimates.dat | stores statistics used to estimate minimum transaction fees and priorities required for confirmation; since 0.10.0 -indexes/txindex/* | optional transaction index database (LevelDB); since 0.17.0 -mempool.dat | dump of the mempool's transactions; since 0.14.0 -peers.dat | peer IP address database (custom format); since 0.7.0 -wallet.dat | personal wallet (BDB) with keys and transactions; moved to wallets/ directory on new installs since 0.16.0 -wallets/database/* | BDB database environment; used for wallets since 0.16.0 -wallets/db.log | wallet database log file; since 0.16.0 -wallets/wallet.dat | personal wallet (BDB) with keys and transactions; since 0.16.0 -.cookie | session RPC authentication cookie (written at start when cookie authentication is used, deleted on shutdown): since 0.12.0 -onion_private_key | cached Tor hidden service private key for `-listenonion`: since 0.12.0 -guisettings.ini.bak | backup of former GUI settings after `-resetguisettings` is used - -Only used in pre-0.8.0 ---------------------- -* blktree/*; block chain index (LevelDB); since pre-0.8, replaced by blocks/index/* in 0.8.0 -* coins/*; unspent transaction output database (LevelDB); since pre-0.8, replaced by chainstate/* in 0.8.0 - -Only used before 0.8.0 ---------------------- -* blkindex.dat: block chain index database (BDB); replaced by {chainstate/*,blocks/index/*,blocks/rev000??.dat} in 0.8.0 -* blk000?.dat: block data (custom, 2 GiB per file); replaced by blocks/blk000??.dat in 0.8.0 - -Only used before 0.7.0 ---------------------- -* addr.dat: peer IP address database (BDB); replaced by peers.dat in 0.7.0 +# Bitcoin Core file system + +**Contents** + +- [Data directory location](#data-directory-location) + +- [Data directory layout](#data-directory-layout) + +- [Multi-wallet environment](#multi-wallet-environment) + +- [GUI settings](#gui-settings) + +- [Legacy subdirectories and files](#legacy-subdirectories-and-files) + +- [Notes](#notes) + +## Data directory location + +The data directory is the default location where the Bitcoin Core files are stored. + +1. The default data directory paths for supported platforms are: + +Platform | Data directory path +---------|-------------------- +Linux | `$HOME/.bitcoin/` +macOS | `$HOME/Library/Application Support/Bitcoin/` +Windows | `%APPDATA%\Bitcoin\` <sup>[\[1\]](#note1)</sup> + +2. The non-default data directory path can be specified by `-datadir` option. + +3. All content of the data directory, except for `bitcoin.conf` file, is chain-specific. This means the actual data directory paths for non-mainnet cases differ: + +Chain option | Data directory path +--------------------|-------------------- +no option (mainnet) | *path_to_datadir*`/` +`-testnet` | *path_to_datadir*`/testnet3/` +`-regtest` | *path_to_datadir*`/regtest/` + +## Data directory layout + +Subdirectory | File(s) | Description +-------------------|-----------------------|------------ +`blocks/` | | Blocks directory; can be specified by `-blocksdir` option (except for `blocks/index/`) +`blocks/index/` | LevelDB database | Block index; `-blocksdir` option does not affect this path +`blocks/` | `blkNNNNN.dat`<sup>[\[2\]](#note2)</sup> | Actual Bitcoin blocks (in network format, dumped in raw on disk, 128 MiB per file) +`blocks/` | `revNNNNN.dat`<sup>[\[2\]](#note2)</sup> | Block undo data (custom format) +`chainstate/` | LevelDB database | Blockchain state (a compact representation of all currently unspent transaction outputs and some metadata about the transactions they are from) +`indexes/txindex/` | LevelDB database | Transaction index; *optional*, used if `-txindex=1` +`indexes/blockfilter/basic/db/` | LevelDB database | Blockfilter index LevelDB database for the basic filtertype; *optional*, used if `-blockfilterindex=basic` +`indexes/blockfilter/basic/` | `fltrNNNNN.dat`<sup>[\[2\]](#note2)</sup> | Blockfilter index filters for the basic filtertype; *optional*, used if `-blockfilterindex=basic` +`wallets/` | | [Contains wallets](#multi-wallet-environment); can be specified by `-walletdir` option; if `wallets/` subdirectory does not exist, a wallet resides in the data directory +`./` | `banlist.dat` | Stores the IPs/subnets of banned nodes +`./` | `bitcoin.conf` | Contains [configuration settings](bitcoin-conf.md) for `bitcoind` or `bitcoin-qt`; can be specified by `-conf` option +`./` | `bitcoind.pid` | Stores the process ID (PID) of `bitcoind` or `bitcoin-qt` while running; created at start and deleted on shutdown; can be specified by `-pid` option +`./` | `debug.log` | Contains debug information and general logging generated by `bitcoind` or `bitcoin-qt`; can be specified by `-debuglogfile` option +`./` | `fee_estimates.dat` | Stores statistics used to estimate minimum transaction fees and priorities required for confirmation +`./` | `guisettings.ini.bak` | Backup of former [GUI settings](#gui-settings) after `-resetguisettings` option is used +`./` | `mempool.dat` | Dump of the mempool's transactions +`./` | `onion_private_key` | Cached Tor hidden service private key for `-listenonion` option +`./` | `peers.dat` | Peer IP address database (custom format) +`./` | `.cookie` | Session RPC authentication cookie; if used, created at start and deleted on shutdown; can be specified by `-rpccookiefile` option +`./` | `.lock` | Data directory lock file + +## Multi-wallet environment + +Wallets are Berkeley DB (BDB) databases: + +Subdirectory | File(s) | Description +-------------|-------------------|------------ +`database/` | BDB logging files | Part of BDB environment; created at start and deleted on shutdown; a user *must keep it as safe* as personal wallet `wallet.dat` +`./` | `db.log` | BDB error file +`./` | `wallet.dat` | Personal wallet (BDB) with keys and transactions +`./` | `.walletlock` | Wallet lock file + +1. Each user-defined wallet named "wallet_name" resides in `wallets/wallet_name/` subdirectory. + +2. The default (unnamed) wallet resides in `wallets/` subdirectory; if the latter does not exist, the wallet resides in the data directory. + +3. A wallet database path can be specified by `-wallet` option. + +## GUI settings + +`bitcoin-qt` uses [`QSettings`](https://doc.qt.io/qt-5/qsettings.html) class; this implies platform-specific [locations where application settings are stored](https://doc.qt.io/qt-5/qsettings.html#locations-where-application-settings-are-stored). + +## Legacy subdirectories and files + +These subdirectories and files are no longer used by the Bitcoin Core: + +Path | Description | Repository notes +---------------|-------------|----------------- +`blktree/` | Blockchain index; replaced by `blocks/index/` in [0.8.0](https://github.com/bitcoin/bitcoin/blob/master/doc/release-notes/release-notes-0.8.0.md#improvements) | [PR #2231](https://github.com/bitcoin/bitcoin/pull/2231), [`8fdc94cc`](https://github.com/bitcoin/bitcoin/commit/8fdc94cc8f0341e96b1edb3a5b56811c0b20bd15) +`coins/` | Unspent transaction output database; replaced by `chainstate/` in 0.8.0 | [PR #2231](https://github.com/bitcoin/bitcoin/pull/2231), [`8fdc94cc`](https://github.com/bitcoin/bitcoin/commit/8fdc94cc8f0341e96b1edb3a5b56811c0b20bd15) +`blkindex.dat` | Blockchain index BDB database; replaced by {`chainstate/`, `blocks/index/`, `blocks/revNNNNN.dat`<sup>[\[2\]](#note2)</sup>} in 0.8.0 | [PR #1677](https://github.com/bitcoin/bitcoin/pull/1677) +`blk000?.dat` | Block data (custom format, 2 GiB per file); replaced by `blocks/blkNNNNN.dat`<sup>[\[2\]](#note2)</sup> in 0.8.0 | [PR #1677](https://github.com/bitcoin/bitcoin/pull/1677) +`addr.dat` | Peer IP address BDB database; replaced by `peers.dat` in [0.7.0](https://github.com/bitcoin/bitcoin/blob/master/doc/release-notes/release-notes-0.7.0.md) | [PR #1198](https://github.com/bitcoin/bitcoin/pull/1198), [`928d3a01`](https://github.com/bitcoin/bitcoin/commit/928d3a011cc66c7f907c4d053f674ea77dc611cc) + +## Notes + +<a name="note1">1</a>. The `/` (slash, U+002F) is used as the platform-independent path component separator in this paper. + +<a name="note2">2</a>. `NNNNN` matches `[0-9]{5}` regex. + diff --git a/doc/man/bitcoin-qt.1 b/doc/man/bitcoin-qt.1 index 1e8443b1d3..1957fb736e 100644 --- a/doc/man/bitcoin-qt.1 +++ b/doc/man/bitcoin-qt.1 @@ -179,10 +179,6 @@ Allow DNS lookups for \fB\-addnode\fR, \fB\-seednode\fR and \fB\-connect\fR (def Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless \fB\-connect\fR used) .HP -\fB\-enablebip61\fR -.IP -Send reject messages per BIP61 (default: 0) -.HP \fB\-externalip=\fR<ip> .IP Specify your own public address diff --git a/doc/man/bitcoind.1 b/doc/man/bitcoind.1 index 2a79b6cb46..b0aff99ca2 100644 --- a/doc/man/bitcoind.1 +++ b/doc/man/bitcoind.1 @@ -179,10 +179,6 @@ Allow DNS lookups for \fB\-addnode\fR, \fB\-seednode\fR and \fB\-connect\fR (def Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless \fB\-connect\fR used) .HP -\fB\-enablebip61\fR -.IP -Send reject messages per BIP61 (default: 0) -.HP \fB\-externalip=\fR<ip> .IP Specify your own public address diff --git a/doc/release-notes-15437.md b/doc/release-notes-15437.md new file mode 100644 index 0000000000..031e90ccd2 --- /dev/null +++ b/doc/release-notes-15437.md @@ -0,0 +1,34 @@ +P2P and network changes +----------------------- + +#### Removal of reject network messages from Bitcoin Core (BIP61) + +The command line option to enable BIP61 (`-enablebip61`) has been removed. + +This feature has been disabled by default since Bitcoin Core version 0.18.0. +Nodes on the network can not generally be trusted to send valid ("reject") +messages, so this should only ever be used when connected to a trusted node. +Please use the recommended alternatives if you rely on this deprecated feature: + +* Testing or debugging of implementations of the Bitcoin P2P network protocol + should be done by inspecting the log messages that are produced by a recent + version of Bitcoin Core. Bitcoin Core logs debug messages + (`-debug=<category>`) to a stream (`-printtoconsole`) or to a file + (`-debuglogfile=<debug.log>`). + +* Testing the validity of a block can be achieved by specific RPCs: + - `submitblock` + - `getblocktemplate` with `'mode'` set to `'proposal'` for blocks with + potentially invalid POW + +* Testing the validity of a transaction can be achieved by specific RPCs: + - `sendrawtransaction` + - `testmempoolaccept` + +* Wallets should not use the absence of "reject" messages to indicate a + transaction has propagated the network, nor should wallets use "reject" + messages to set transaction fees. Wallets should rather use fee estimation + to determine transaction fees and set replace-by-fee if desired. Thus, they + could wait until the transaction has confirmed (taking into account the fee + target they set (compare the RPC `estimatesmartfee`)) or listen for the + transaction announcement by other network peers to check for propagation. diff --git a/doc/release-notes-16524.md b/doc/release-notes-16524.md deleted file mode 100644 index 11c2f60c38..0000000000 --- a/doc/release-notes-16524.md +++ /dev/null @@ -1,8 +0,0 @@ - -Low-level changes -================= - -Tests ---- - -- `-fallbackfee` was 0 (disabled) by default for the main chain, but 20000 by default for the test chains. Now it is 0 by default for all chains. Testnet and regtest users will have to add fallbackfee=20000 to their configuration if they weren't setting it and they want it to keep working like before. (#16524) diff --git a/doc/release-notes-16884.md b/doc/release-notes-16884.md deleted file mode 100644 index e721080397..0000000000 --- a/doc/release-notes-16884.md +++ /dev/null @@ -1,2 +0,0 @@ -The wallet now by default uses bech32 addresses when using RPC, and creates native segwit -change outputs. diff --git a/doc/release-notes-17056.md b/doc/release-notes-17056.md new file mode 100644 index 0000000000..23d5a8c8cd --- /dev/null +++ b/doc/release-notes-17056.md @@ -0,0 +1,4 @@ +Low-level RPC Changes +=== + +- A new descriptor type `sortedmulti(...)` has been added to support multisig scripts where the public keys are sorted lexicographically in the resulting script. diff --git a/doc/release-notes.md b/doc/release-notes.md index db5aa0d8a7..ea82962e75 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -63,6 +63,39 @@ distribution provides binaries for the RISC-V platform. Notable changes =============== +New RPCs +-------- + +New settings +------------ + +Updated settings +---------------- + +Updated RPCs +------------ + +Note: some low-level RPC changes mainly useful for testing are described in the +Low-level Changes section below. + +GUI changes +----------- + +Wallet +------ + +- The wallet now by default uses bech32 addresses when using RPC, and creates native segwit change outputs. + +Low-level changes +================= + +Tests +----- + +- `-fallbackfee` was 0 (disabled) by default for the main chain, but 0.0002 by default for the test chains. Now it is 0 + by default for all chains. Testnet and regtest users will have to add `fallbackfee=0.0002` to their configuration if + they weren't setting it and they want it to keep working like before. (#16524) + Credits ======= diff --git a/doc/release-process.md b/doc/release-process.md index 551bde78a3..2c3c4e3869 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -14,19 +14,9 @@ Release Process * Update [bips.md](bips.md) to account for changes since the last release (don't forget to bump the version number on the first line). * Update version in `configure.ac` (don't forget to set `CLIENT_VERSION_RC` to `0`). * Write release notes (see "Write the release notes" below). -* Update `src/chainparams.cpp` nMinimumChainWork with information from the getblockchaininfo rpc. -* Update `src/chainparams.cpp` defaultAssumeValid with information from the getblockhash rpc. - - The selected value must not be orphaned so it may be useful to set the value two blocks back from the tip. - - Testnet should be set some tens of thousands back from the tip due to reorgs there. - - This update should be reviewed with a reindex-chainstate with assumevalid=0 to catch any defect - that causes rejection of blocks in the past history. ### Before every major release -* Update hardcoded [seeds](/contrib/seeds/README.md), see [this pull request](https://github.com/bitcoin/bitcoin/pull/7415) for an example. -* Update [`src/chainparams.cpp`](/src/chainparams.cpp) m_assumed_blockchain_size and m_assumed_chain_state_size with the current size plus some overhead (see [this](#how-to-calculate-m_assumed_blockchain_size-and-m_assumed_chain_state_size) for information on how to calculate them). -* Update `src/chainparams.cpp` chainTxData with statistics about the transaction count and rate. Use the output of the RPC `getchaintxstats`, see - [this pull request](https://github.com/bitcoin/bitcoin/pull/17002) for an example. Reviewers can verify the results by running `getchaintxstats <window_block_count> <window_last_block_hash>` with the `window_block_count` and `window_last_block_hash` from your output. * On both the master branch and the new release branch: - update `CLIENT_VERSION_MINOR` in [`configure.ac`](../configure.ac) - update `CLIENT_VERSION_MINOR`, `PACKAGE_VERSION`, and `PACKAGE_STRING` in [`build_msvc/bitcoin_config.h`](/build_msvc/bitcoin_config.h) @@ -36,6 +26,16 @@ Release Process #### Before branch-off +* Update hardcoded [seeds](/contrib/seeds/README.md), see [this pull request](https://github.com/bitcoin/bitcoin/pull/7415) for an example. +* Update [`src/chainparams.cpp`](/src/chainparams.cpp) m_assumed_blockchain_size and m_assumed_chain_state_size with the current size plus some overhead (see [this](#how-to-calculate-m_assumed_blockchain_size-and-m_assumed_chain_state_size) for information on how to calculate them). +* Update `src/chainparams.cpp` chainTxData with statistics about the transaction count and rate. Use the output of the RPC `getchaintxstats`, see + [this pull request](https://github.com/bitcoin/bitcoin/pull/17002) for an example. Reviewers can verify the results by running `getchaintxstats <window_block_count> <window_last_block_hash>` with the `window_block_count` and `window_last_block_hash` from your output. +* Update `src/chainparams.cpp` nMinimumChainWork with information from the getblockchaininfo rpc. +* Update `src/chainparams.cpp` defaultAssumeValid with information from the getblockhash rpc. + - The selected value must not be orphaned so it may be useful to set the value two blocks back from the tip. + - Testnet should be set some tens of thousands back from the tip due to reorgs there. + - This update should be reviewed with a reindex-chainstate with assumevalid=0 to catch any defect + that causes rejection of blocks in the past history. - Clear the release notes and move them to the wiki (see "Write the release notes" below). #### After branch-off (on master) diff --git a/src/.clang-format b/src/.clang-format index 38e19edf2c..aae039dd77 100644 --- a/src/.clang-format +++ b/src/.clang-format @@ -5,6 +5,7 @@ AlignEscapedNewlinesLeft: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: false diff --git a/src/Makefile.am b/src/Makefile.am index d25f7ebe87..eec84122ae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -208,7 +208,9 @@ BITCOIN_CORE_H = \ util/bytevectorhash.h \ util/error.h \ util/fees.h \ + util/spanparsing.h \ util/system.h \ + util/macros.h \ util/memory.h \ util/moneystr.h \ util/rbf.h \ @@ -504,6 +506,7 @@ libbitcoin_util_a_SOURCES = \ util/moneystr.cpp \ util/rbf.cpp \ util/threadnames.cpp \ + util/spanparsing.cpp \ util/strencodings.cpp \ util/string.cpp \ util/time.cpp \ diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index a8d3154107..9ab7f02e22 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -353,9 +353,9 @@ QT_QM=$(QT_TS:.ts=.qm) SECONDARY: $(QT_QM) -$(srcdir)/qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_zmq_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) $(libbitcoin_util_a_SOURCES) +$(srcdir)/qt/bitcoinstrings.cpp: FORCE @test -n $(XGETTEXT) || echo "xgettext is required for updating translations" - $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" $(PYTHON) ../share/qt/extract_strings_qt.py $^ + $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" $(PYTHON) ../share/qt/extract_strings_qt.py $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_zmq_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) $(libbitcoin_util_a_SOURCES) translate: $(srcdir)/qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_BASE_CPP) qt/bitcoin.cpp $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM) @test -n $(LUPDATE) || echo "lupdate is required for updating translations" diff --git a/src/Makefile.test.include b/src/Makefile.test.include index d3fe138133..b8957e52bd 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -17,12 +17,13 @@ FUZZ_TARGETS = \ test/fuzz/bloomfilter_deserialize \ test/fuzz/coins_deserialize \ test/fuzz/diskblockindex_deserialize \ + test/fuzz/eval_script \ test/fuzz/inv_deserialize \ test/fuzz/messageheader_deserialize \ test/fuzz/netaddr_deserialize \ test/fuzz/script_flags \ test/fuzz/service_deserialize \ - test/fuzz/transaction_deserialize \ + test/fuzz/transaction \ test/fuzz/txoutcompressor_deserialize \ test/fuzz/txundo_deserialize @@ -59,7 +60,8 @@ FUZZ_SUITE = \ test/setup_common.h \ test/setup_common.cpp \ test/fuzz/fuzz.cpp \ - test/fuzz/fuzz.h + test/fuzz/fuzz.h \ + test/fuzz/FuzzedDataProvider.h FUZZ_SUITE_LD_COMMON = \ $(LIBBITCOIN_SERVER) \ @@ -202,12 +204,6 @@ test_fuzz_block_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_block_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_fuzz_block_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) -test_fuzz_transaction_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp -test_fuzz_transaction_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTRANSACTION_DESERIALIZE=1 -test_fuzz_transaction_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -test_fuzz_transaction_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -test_fuzz_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) - test_fuzz_blocklocator_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_blocklocator_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DBLOCKLOCATOR_DESERIALIZE=1 test_fuzz_blocklocator_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) @@ -304,6 +300,12 @@ test_fuzz_diskblockindex_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_diskblockindex_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_fuzz_diskblockindex_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) +test_fuzz_eval_script_SOURCES = $(FUZZ_SUITE) test/fuzz/eval_script.cpp +test_fuzz_eval_script_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_eval_script_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_eval_script_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +test_fuzz_eval_script_LDADD = $(FUZZ_SUITE_LD_COMMON) + test_fuzz_txoutcompressor_deserialize_SOURCES = $(FUZZ_SUITE) test/fuzz/deserialize.cpp test_fuzz_txoutcompressor_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DTXOUTCOMPRESSOR_DESERIALIZE=1 test_fuzz_txoutcompressor_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) @@ -321,6 +323,13 @@ test_fuzz_blocktransactionsrequest_deserialize_CPPFLAGS = $(AM_CPPFLAGS) $(BITCO test_fuzz_blocktransactionsrequest_deserialize_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_fuzz_blocktransactionsrequest_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_fuzz_blocktransactionsrequest_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMON) + +test_fuzz_transaction_SOURCES = $(FUZZ_SUITE) test/fuzz/transaction.cpp +test_fuzz_transaction_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) +test_fuzz_transaction_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +test_fuzz_transaction_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +test_fuzz_transaction_LDADD = $(FUZZ_SUITE_LD_COMMON) + endif # ENABLE_FUZZ nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES) diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 615b955f6e..17989a4214 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -45,7 +45,7 @@ static bool AppInit(int argc, char* argv[]) bool fRet = false; - util::ThreadRename("init"); + util::ThreadSetInternalName("init"); // // Parameters diff --git a/src/compat/stdin.cpp b/src/compat/stdin.cpp index 4f2ba1e9c4..98d406cca8 100644 --- a/src/compat/stdin.cpp +++ b/src/compat/stdin.cpp @@ -14,7 +14,7 @@ #else #include <termios.h> // for SetStdinEcho() #include <unistd.h> // for SetStdinEcho(), isatty() -#include <sys/poll.h> // for StdinReady() +#include <poll.h> // for StdinReady() #endif #include <compat/stdin.h> diff --git a/src/init.cpp b/src/init.cpp index 8c0d599435..035725b090 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -407,7 +407,6 @@ void SetupServerArgs() gArgs.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); gArgs.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); gArgs.AddArg("-dnsseed", "Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); - gArgs.AddArg("-enablebip61", strprintf("Send reject messages per BIP61 (default: %u)", DEFAULT_ENABLE_BIP61), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); gArgs.AddArg("-externalip=<ip>", "Specify your own public address", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); gArgs.AddArg("-forcednsseed", strprintf("Always query for peer addresses via DNS lookup (default: %u)", DEFAULT_FORCEDNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); gArgs.AddArg("-listen", "Accept connections from outside (default: 1 if no -proxy or -connect)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); @@ -1320,7 +1319,7 @@ bool AppInitMain(InitInterfaces& interfaces) assert(!g_connman); g_connman = std::unique_ptr<CConnman>(new CConnman(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max()))); - peerLogic.reset(new PeerLogicValidation(g_connman.get(), g_banman.get(), scheduler, gArgs.GetBoolArg("-enablebip61", DEFAULT_ENABLE_BIP61))); + peerLogic.reset(new PeerLogicValidation(g_connman.get(), g_banman.get(), scheduler)); RegisterValidationInterface(peerLogic.get()); // sanitize comments per BIP-0014, format user agent and check total size diff --git a/src/net_processing.cpp b/src/net_processing.cpp index e345af604c..b6839dcf21 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -193,12 +193,6 @@ namespace { } // namespace namespace { -struct CBlockReject { - unsigned char chRejectCode; - std::string strRejectReason; - uint256 hashBlock; -}; - /** * Maintain validation-specific state about nodes, protected by cs_main, instead * by CNode's own locks. This simplifies asynchronous operation, where @@ -216,8 +210,6 @@ struct CNodeState { bool fShouldBan; //! String name of this peer (debugging/logging purposes). const std::string name; - //! List of asynchronously-determined block rejections to notify this peer about. - std::vector<CBlockReject> rejects; //! The best known block we know this peer has announced. const CBlockIndex *pindexBestKnownBlock; //! The hash of the last unknown block this peer has announced. @@ -1093,8 +1085,9 @@ static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Para (GetBlockProofEquivalentTime(*pindexBestHeader, *pindex, *pindexBestHeader, consensusParams) < STALE_RELAY_AGE_LIMIT); } -PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, BanMan* banman, CScheduler &scheduler, bool enable_bip61) - : connman(connmanIn), m_banman(banman), m_stale_tip_check_time(0), m_enable_bip61(enable_bip61) { +PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, BanMan* banman, CScheduler& scheduler) + : connman(connmanIn), m_banman(banman), m_stale_tip_check_time(0) +{ // Initialize global variables that cannot be constructed at startup. recentRejects.reset(new CRollingBloomFilter(120000, 0.000001)); @@ -1244,8 +1237,6 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta if (state.IsInvalid()) { // Don't send reject message with code 0 or an internal reject code. if (it != mapBlockSource.end() && State(it->second.first) && state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) { - CBlockReject reject = {(unsigned char)state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), hash}; - State(it->second.first)->rejects.push_back(reject); MaybePunishNode(/*nodeid=*/ it->second.first, state, /*via_compact_block=*/ !it->second.second); } } @@ -1859,7 +1850,7 @@ void static ProcessOrphanTx(CConnman* connman, std::set<uint256>& orphan_work_se } } -bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc, bool enable_bip61) +bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc) { LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->GetId()); if (gArgs.IsArgSet("-dropmessagestest") && GetRand(gArgs.GetArg("-dropmessagestest", 0)) == 0) @@ -1883,38 +1874,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } } - if (strCommand == NetMsgType::REJECT) - { - if (LogAcceptCategory(BCLog::NET)) { - try { - std::string strMsg; unsigned char ccode; std::string strReason; - vRecv >> LIMITED_STRING(strMsg, CMessageHeader::COMMAND_SIZE) >> ccode >> LIMITED_STRING(strReason, MAX_REJECT_MESSAGE_LENGTH); - - std::ostringstream ss; - ss << strMsg << " code " << itostr(ccode) << ": " << strReason; - - if (strMsg == NetMsgType::BLOCK || strMsg == NetMsgType::TX) - { - uint256 hash; - vRecv >> hash; - ss << ": hash " << hash.ToString(); - } - LogPrint(BCLog::NET, "Reject %s\n", SanitizeString(ss.str())); - } catch (const std::ios_base::failure&) { - // Avoid feedback loops by preventing reject messages from triggering a new reject message. - LogPrint(BCLog::NET, "Unparseable reject message received\n"); - } - } - return true; - } - if (strCommand == NetMsgType::VERSION) { // Each connection can only send one version message if (pfrom->nVersion != 0) { - if (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; @@ -1942,10 +1905,6 @@ 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)); - if (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; } @@ -1953,10 +1912,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (nVersion < MIN_PEER_PROTO_VERSION) { // disconnect from peers older than this proto version LogPrint(BCLog::NET, "peer=%d using obsolete version %i; disconnecting\n", pfrom->GetId(), nVersion); - if (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; } @@ -2628,10 +2583,6 @@ 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 (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)); - } MaybePunishNode(pfrom->GetId(), state, /*via_compact_block*/ false); } return true; @@ -2811,7 +2762,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } // cs_main if (fProcessBLOCKTXN) - return ProcessMessage(pfrom, NetMsgType::BLOCKTXN, blockTxnMsg, nTimeReceived, chainparams, connman, interruptMsgProc, enable_bip61); + return ProcessMessage(pfrom, NetMsgType::BLOCKTXN, blockTxnMsg, nTimeReceived, chainparams, connman, interruptMsgProc); if (fRevertToHeaderProcessing) { // Headers received from HB compact block peers are permitted to be @@ -3238,18 +3189,11 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr return true; } -bool PeerLogicValidation::SendRejectsAndCheckIfBanned(CNode* pnode, bool enable_bip61) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +bool PeerLogicValidation::CheckIfBanned(CNode* pnode) { AssertLockHeld(cs_main); CNodeState &state = *State(pnode->GetId()); - if (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(); - if (state.fShouldBan) { state.fShouldBan = false; if (pnode->HasPermission(PF_NOBAN)) @@ -3358,7 +3302,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter bool fRet = false; try { - fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime, chainparams, connman, interruptMsgProc, m_enable_bip61); + fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime, chainparams, connman, interruptMsgProc); if (interruptMsgProc) return false; if (!pfrom->vRecvGetData.empty()) @@ -3366,9 +3310,6 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter } catch (const std::ios_base::failure& e) { - if (m_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 LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught, normally caused by a message being shorter than its stated length\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); @@ -3399,7 +3340,7 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter } LOCK(cs_main); - SendRejectsAndCheckIfBanned(pfrom, m_enable_bip61); + CheckIfBanned(pfrom); return fMoreWork; } @@ -3598,11 +3539,12 @@ bool PeerLogicValidation::SendMessages(CNode* pto) } } - TRY_LOCK(cs_main, lockMain); // Acquire cs_main for IsInitialBlockDownload() and CNodeState() + TRY_LOCK(cs_main, lockMain); if (!lockMain) return true; - if (SendRejectsAndCheckIfBanned(pto, m_enable_bip61)) return true; + if (CheckIfBanned(pto)) return true; + CNodeState &state = *State(pto->GetId()); // Address refresh broadcast @@ -3847,10 +3789,10 @@ bool PeerLogicValidation::SendMessages(CNode* pto) if (fSendTrickle && pto->m_tx_relay->fSendMempool) { auto vtxinfo = mempool.infoAll(); pto->m_tx_relay->fSendMempool = false; - CAmount filterrate = 0; + CFeeRate filterrate; { LOCK(pto->m_tx_relay->cs_feeFilter); - filterrate = pto->m_tx_relay->minFeeFilter; + filterrate = CFeeRate(pto->m_tx_relay->minFeeFilter); } LOCK(pto->m_tx_relay->cs_filter); @@ -3859,9 +3801,9 @@ bool PeerLogicValidation::SendMessages(CNode* pto) const uint256& hash = txinfo.tx->GetHash(); CInv inv(MSG_TX, hash); pto->m_tx_relay->setInventoryTxToSend.erase(hash); - if (filterrate) { - if (txinfo.feeRate.GetFeePerK() < filterrate) - continue; + // Don't send transactions that peers will not put into their mempool + if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) { + continue; } if (pto->m_tx_relay->pfilter) { if (!pto->m_tx_relay->pfilter->IsRelevantAndUpdate(*txinfo.tx)) continue; @@ -3884,10 +3826,10 @@ bool PeerLogicValidation::SendMessages(CNode* pto) for (std::set<uint256>::iterator it = pto->m_tx_relay->setInventoryTxToSend.begin(); it != pto->m_tx_relay->setInventoryTxToSend.end(); it++) { vInvTx.push_back(it); } - CAmount filterrate = 0; + CFeeRate filterrate; { LOCK(pto->m_tx_relay->cs_feeFilter); - filterrate = pto->m_tx_relay->minFeeFilter; + filterrate = CFeeRate(pto->m_tx_relay->minFeeFilter); } // Topologically and fee-rate sort the inventory we send for privacy and priority reasons. // A heap is used so that not all items need sorting if only a few are being sent. @@ -3914,7 +3856,8 @@ bool PeerLogicValidation::SendMessages(CNode* pto) if (!txinfo.tx) { continue; } - if (filterrate && txinfo.feeRate.GetFeePerK() < filterrate) { + // Peer told you to not send transactions at that feerate? Don't bother sending it. + if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) { continue; } if (pto->m_tx_relay->pfilter && !pto->m_tx_relay->pfilter->IsRelevantAndUpdate(*txinfo.tx)) continue; diff --git a/src/net_processing.h b/src/net_processing.h index 1d26164b18..e8bc3580dd 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -17,8 +17,6 @@ extern CCriticalSection cs_main; static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100; /** Default number of orphan+recently-replaced txn to keep around for block reconstruction */ static const unsigned int DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN = 100; -/** Default for BIP61 (sending reject messages) */ -static constexpr bool DEFAULT_ENABLE_BIP61{false}; static const bool DEFAULT_PEERBLOOMFILTERS = false; class PeerLogicValidation final : public CValidationInterface, public NetEventsInterface { @@ -26,9 +24,10 @@ private: CConnman* const connman; BanMan* const m_banman; - bool SendRejectsAndCheckIfBanned(CNode* pnode, bool enable_bip61) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + bool CheckIfBanned(CNode* pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + public: - PeerLogicValidation(CConnman* connman, BanMan* banman, CScheduler &scheduler, bool enable_bip61); + PeerLogicValidation(CConnman* connman, BanMan* banman, CScheduler& scheduler); /** * Overridden from CValidationInterface. @@ -75,9 +74,6 @@ public: private: int64_t m_stale_tip_check_time; //!< Next time to check for stale tip - - /** Enable BIP61 (sending reject messages) */ - const bool m_enable_bip61; }; struct CNodeStateStats { diff --git a/src/policy/feerate.h b/src/policy/feerate.h index 85d7d22b4f..d081f2ce8e 100644 --- a/src/policy/feerate.h +++ b/src/policy/feerate.h @@ -25,7 +25,7 @@ public: /** Fee rate of 0 satoshis per kB */ CFeeRate() : nSatoshisPerK(0) { } template<typename I> - CFeeRate(const I _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { + explicit CFeeRate(const I _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { // We've previously had bugs creep in from silent double->int conversion... static_assert(std::is_integral<I>::value, "CFeeRate should be used without floats"); } diff --git a/src/protocol.cpp b/src/protocol.cpp index bdf236c2c7..e49e5523ac 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -34,7 +34,6 @@ const char *NOTFOUND="notfound"; const char *FILTERLOAD="filterload"; const char *FILTERADD="filteradd"; const char *FILTERCLEAR="filterclear"; -const char *REJECT="reject"; const char *SENDHEADERS="sendheaders"; const char *FEEFILTER="feefilter"; const char *SENDCMPCT="sendcmpct"; @@ -66,7 +65,6 @@ const static std::string allNetMessageTypes[] = { NetMsgType::FILTERLOAD, NetMsgType::FILTERADD, NetMsgType::FILTERCLEAR, - NetMsgType::REJECT, NetMsgType::SENDHEADERS, NetMsgType::FEEFILTER, NetMsgType::SENDCMPCT, diff --git a/src/protocol.h b/src/protocol.h index 91d043947b..e6b25ffa25 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -193,13 +193,6 @@ extern const char *FILTERADD; */ extern const char *FILTERCLEAR; /** - * The reject message informs the receiving node that one of its previous - * messages has been rejected. - * @since protocol version 70002 as described by BIP61. - * @see https://bitcoin.org/en/developer-reference#reject - */ -extern const char *REJECT; -/** * Indicates that a node prefers to receive new block announcements via a * "headers" message rather than an "inv". * @since protocol version 70012 as described by BIP130. diff --git a/src/psbt.h b/src/psbt.h index 6d77db0c6f..802a7c5ba7 100644 --- a/src/psbt.h +++ b/src/psbt.h @@ -126,6 +126,9 @@ struct PSBTInput template <typename Stream> inline void Unserialize(Stream& s) { + // Used for duplicate key detection + std::set<std::vector<unsigned char>> key_lookup; + // Read loop bool found_sep = false; while(!s.empty()) { @@ -147,7 +150,7 @@ struct PSBTInput switch(type) { case PSBT_IN_NON_WITNESS_UTXO: { - if (non_witness_utxo) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, input non-witness utxo already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Non-witness utxo key is more than one byte type"); @@ -158,7 +161,7 @@ struct PSBTInput break; } case PSBT_IN_WITNESS_UTXO: - if (!witness_utxo.IsNull()) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, input witness utxo already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Witness utxo key is more than one byte type"); @@ -189,7 +192,7 @@ struct PSBTInput break; } case PSBT_IN_SIGHASH: - if (sighash_type > 0) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, input sighash type already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Sighash type key is more than one byte type"); @@ -198,7 +201,7 @@ struct PSBTInput break; case PSBT_IN_REDEEMSCRIPT: { - if (!redeem_script.empty()) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, input redeemScript already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Input redeemScript key is more than one byte type"); @@ -208,7 +211,7 @@ struct PSBTInput } case PSBT_IN_WITNESSSCRIPT: { - if (!witness_script.empty()) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, input witnessScript already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Input witnessScript key is more than one byte type"); @@ -223,7 +226,7 @@ struct PSBTInput } case PSBT_IN_SCRIPTSIG: { - if (!final_script_sig.empty()) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, input final scriptSig already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Final scriptSig key is more than one byte type"); @@ -233,7 +236,7 @@ struct PSBTInput } case PSBT_IN_SCRIPTWITNESS: { - if (!final_script_witness.IsNull()) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, input final scriptWitness already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Final scriptWitness key is more than one byte type"); @@ -309,6 +312,9 @@ struct PSBTOutput template <typename Stream> inline void Unserialize(Stream& s) { + // Used for duplicate key detection + std::set<std::vector<unsigned char>> key_lookup; + // Read loop bool found_sep = false; while(!s.empty()) { @@ -330,7 +336,7 @@ struct PSBTOutput switch(type) { case PSBT_OUT_REDEEMSCRIPT: { - if (!redeem_script.empty()) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, output redeemScript already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Output redeemScript key is more than one byte type"); @@ -340,7 +346,7 @@ struct PSBTOutput } case PSBT_OUT_WITNESSSCRIPT: { - if (!witness_script.empty()) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, output witnessScript already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Output witnessScript key is more than one byte type"); @@ -448,6 +454,9 @@ struct PartiallySignedTransaction throw std::ios_base::failure("Invalid PSBT magic bytes"); } + // Used for duplicate key detection + std::set<std::vector<unsigned char>> key_lookup; + // Read global data bool found_sep = false; while(!s.empty()) { @@ -469,7 +478,7 @@ struct PartiallySignedTransaction switch(type) { case PSBT_GLOBAL_UNSIGNED_TX: { - if (tx) { + if (!key_lookup.emplace(key).second) { throw std::ios_base::failure("Duplicate Key, unsigned tx already provided"); } else if (key.size() != 1) { throw std::ios_base::failure("Global unsigned tx key is more than one byte type"); diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index ec6075c8fb..86f4dc91a1 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -416,7 +416,7 @@ int GuiMain(int argc, char* argv[]) std::tie(argc, argv) = winArgs.get(); #endif SetupEnvironment(); - util::ThreadRename("main"); + util::ThreadSetInternalName("main"); std::unique_ptr<interfaces::Node> node = interfaces::MakeNode(); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 7671fde705..2878a8eb14 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -493,6 +493,7 @@ void BitcoinGUI::createMenuBar() window_menu->addSeparator(); for (RPCConsole::TabTypes tab_type : rpcConsole->tabs()) { QAction* tab_action = window_menu->addAction(rpcConsole->tabTitle(tab_type)); + tab_action->setShortcut(rpcConsole->tabShortcut(tab_type)); connect(tab_action, &QAction::triggered, [this, tab_type] { rpcConsole->setTabFocus(tab_type); showDebugWindow(); @@ -747,9 +748,9 @@ void BitcoinGUI::createTrayIconMenu() trayIconMenu->addAction(signMessageAction); trayIconMenu->addAction(verifyMessageAction); trayIconMenu->addSeparator(); - trayIconMenu->addAction(openRPCConsoleAction); } trayIconMenu->addAction(optionsAction); + trayIconMenu->addAction(openRPCConsoleAction); #ifndef Q_OS_MAC // This is built-in on macOS trayIconMenu->addSeparator(); trayIconMenu->addAction(quitAction); diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 00d83d23dd..806cc3c41e 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -82,7 +82,7 @@ static QString ipcServerName() // the main GUI window is up and ready to ask the user // to send payment. -static QList<QString> savedPaymentRequests; +static QSet<QString> savedPaymentRequests; // // Sending to the server is done synchronously, at startup. @@ -107,7 +107,8 @@ void PaymentServer::ipcParseCommandLine(interfaces::Node& node, int argc, char* // will start a mainnet instance and throw a "wrong network" error. if (arg.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI { - savedPaymentRequests.append(arg); + if (savedPaymentRequests.contains(arg)) continue; + savedPaymentRequests.insert(arg); SendCoinsRecipient r; if (GUIUtil::parseBitcoinURI(arg, &r) && !r.address.isEmpty()) @@ -127,7 +128,8 @@ void PaymentServer::ipcParseCommandLine(interfaces::Node& node, int argc, char* #ifdef ENABLE_BIP70 else if (QFile::exists(arg)) // Filename { - savedPaymentRequests.append(arg); + if (savedPaymentRequests.contains(arg)) continue; + savedPaymentRequests.insert(arg); PaymentRequestPlus request; if (readPaymentRequestFromFile(arg, request)) @@ -280,7 +282,7 @@ void PaymentServer::handleURIOrFile(const QString& s) { if (saveURIs) { - savedPaymentRequests.append(s); + savedPaymentRequests.insert(s); return; } diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index eccc34e12f..4f6629bfe1 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -1276,6 +1276,16 @@ QString RPCConsole::tabTitle(TabTypes tab_type) const return ui->tabWidget->tabText(tab_type); } +QKeySequence RPCConsole::tabShortcut(TabTypes tab_type) const +{ + switch (tab_type) { + case TAB_INFO: return QKeySequence(Qt::CTRL + Qt::Key_I); + case TAB_CONSOLE: return QKeySequence(Qt::CTRL + Qt::Key_T); + case TAB_GRAPH: return QKeySequence(Qt::CTRL + Qt::Key_N); + case TAB_PEERS: return QKeySequence(Qt::CTRL + Qt::Key_P); + } +} + void RPCConsole::updateAlerts(const QString& warnings) { this->ui->label_alerts->setVisible(!warnings.isEmpty()); diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 3f7a74ba03..6b0f07baf1 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -68,6 +68,7 @@ public: std::vector<TabTypes> tabs() const { return {TAB_INFO, TAB_CONSOLE, TAB_GRAPH, TAB_PEERS}; } QString tabTitle(TabTypes tab_type) const; + QKeySequence tabShortcut(TabTypes tab_type) const; protected: virtual bool eventFilter(QObject* obj, QEvent *event); diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 9de90759fa..08ba030d65 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -93,10 +93,14 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const interface if (fAllFromMe && fAllToMe) { // Payment to self - CAmount nChange = wtx.change; + std::string address; + for (auto it = wtx.txout_address.begin(); it != wtx.txout_address.end(); ++it) { + if (it != wtx.txout_address.begin()) address += ", "; + address += EncodeDestination(*it); + } - parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "", - -(nDebit - nChange), nCredit - nChange)); + CAmount nChange = wtx.change; + parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, address, -(nDebit - nChange), nCredit - nChange)); parts.last().involvesWatchAddress = involvesWatchAddress; // maybe pass to TransactionRecord as constructor argument } else if (fAllFromMe) diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 8d0cb54151..fed55577ca 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -394,6 +394,7 @@ QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, b case TransactionRecord::SendToOther: return QString::fromStdString(wtx->address) + watchAddress; case TransactionRecord::SendToSelf: + return lookupAddress(wtx->address, tooltip) + watchAddress; default: return tr("(n/a)") + watchAddress; } diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index b782ebbd1f..ed1bd4cda9 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -11,6 +11,7 @@ #include <span.h> #include <util/bip32.h> +#include <util/spanparsing.h> #include <util/system.h> #include <util/strencodings.h> @@ -593,15 +594,23 @@ public: ComboDescriptor(std::unique_ptr<PubkeyProvider> prov) : DescriptorImpl(Singleton(std::move(prov)), {}, "combo") {} }; -/** A parsed multi(...) descriptor. */ +/** A parsed multi(...) or sortedmulti(...) descriptor */ class MultisigDescriptor final : public DescriptorImpl { const int m_threshold; + const bool m_sorted; protected: std::string ToStringExtra() const override { return strprintf("%i", m_threshold); } - std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider&) const override { return Singleton(GetScriptForMultisig(m_threshold, keys)); } + std::vector<CScript> MakeScripts(const std::vector<CPubKey>& keys, const CScript*, FlatSigningProvider&) const override { + if (m_sorted) { + std::vector<CPubKey> sorted_keys(keys); + std::sort(sorted_keys.begin(), sorted_keys.end()); + return Singleton(GetScriptForMultisig(m_threshold, sorted_keys)); + } + return Singleton(GetScriptForMultisig(m_threshold, keys)); + } public: - MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers) : DescriptorImpl(std::move(providers), {}, "multi"), m_threshold(threshold) {} + MultisigDescriptor(int threshold, std::vector<std::unique_ptr<PubkeyProvider>> providers, bool sorted = false) : DescriptorImpl(std::move(providers), {}, sorted ? "sortedmulti" : "multi"), m_threshold(threshold), m_sorted(sorted) {} }; /** A parsed sh(...) descriptor. */ @@ -632,63 +641,6 @@ enum class ParseScriptContext { P2WSH, }; -/** Parse a constant. If successful, sp is updated to skip the constant and return true. */ -bool Const(const std::string& str, Span<const char>& sp) -{ - if ((size_t)sp.size() >= str.size() && std::equal(str.begin(), str.end(), sp.begin())) { - sp = sp.subspan(str.size()); - return true; - } - return false; -} - -/** Parse a function call. If successful, sp is updated to be the function's argument(s). */ -bool Func(const std::string& str, Span<const char>& sp) -{ - if ((size_t)sp.size() >= str.size() + 2 && sp[str.size()] == '(' && sp[sp.size() - 1] == ')' && std::equal(str.begin(), str.end(), sp.begin())) { - sp = sp.subspan(str.size() + 1, sp.size() - str.size() - 2); - return true; - } - return false; -} - -/** Return the expression that sp begins with, and update sp to skip it. */ -Span<const char> Expr(Span<const char>& sp) -{ - int level = 0; - auto it = sp.begin(); - while (it != sp.end()) { - if (*it == '(') { - ++level; - } else if (level && *it == ')') { - --level; - } else if (level == 0 && (*it == ')' || *it == ',')) { - break; - } - ++it; - } - Span<const char> ret = sp.first(it - sp.begin()); - sp = sp.subspan(it - sp.begin()); - return ret; -} - -/** Split a string on every instance of sep, returning a vector. */ -std::vector<Span<const char>> Split(const Span<const char>& sp, char sep) -{ - std::vector<Span<const char>> ret; - auto it = sp.begin(); - auto start = it; - while (it != sp.end()) { - if (*it == sep) { - ret.emplace_back(start, it); - start = it + 1; - } - ++it; - } - ret.emplace_back(start, it); - return ret; -} - /** Parse a key path, being passed a split list of elements (the first element is ignored). */ NODISCARD bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& out, std::string& error) { @@ -715,6 +667,8 @@ NODISCARD bool ParseKeyPath(const std::vector<Span<const char>>& split, KeyPath& /** Parse a public key that excludes origin information. */ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error) { + using namespace spanparsing; + auto split = Split(sp, '/'); std::string str(split[0].begin(), split[0].end()); if (str.size() == 0) { @@ -774,6 +728,8 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(const Span<const char>& sp, boo /** Parse a public key including origin information (if enabled). */ std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool permit_uncompressed, FlatSigningProvider& out, std::string& error) { + using namespace spanparsing; + auto origin_split = Split(sp, ']'); if (origin_split.size() > 2) { error = "Multiple ']' characters found for a single pubkey"; @@ -808,7 +764,10 @@ std::unique_ptr<PubkeyProvider> ParsePubkey(const Span<const char>& sp, bool per /** Parse a script in a particular context. */ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error) { + using namespace spanparsing; + auto expr = Expr(sp); + bool sorted_multi = false; if (Func("pk", expr)) { auto pubkey = ParsePubkey(expr, ctx != ParseScriptContext::P2WSH, out, error); if (!pubkey) return nullptr; @@ -827,7 +786,7 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon error = "Cannot have combo in non-top level"; return nullptr; } - if (Func("multi", expr)) { + if ((sorted_multi = Func("sortedmulti", expr)) || Func("multi", expr)) { auto threshold = Expr(expr); uint32_t thres; std::vector<std::unique_ptr<PubkeyProvider>> providers; @@ -869,7 +828,7 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon return nullptr; } } - return MakeUnique<MultisigDescriptor>(thres, std::move(providers)); + return MakeUnique<MultisigDescriptor>(thres, std::move(providers), sorted_multi); } if (ctx != ParseScriptContext::P2WSH && Func("wpkh", expr)) { auto pubkey = ParsePubkey(expr, false, out, error); @@ -1003,6 +962,8 @@ std::unique_ptr<DescriptorImpl> InferScript(const CScript& script, ParseScriptCo /** Check a descriptor checksum, and update desc to be the checksum-less part. */ bool CheckChecksum(Span<const char>& sp, bool require_checksum, std::string& error, std::string* out_checksum = nullptr) { + using namespace spanparsing; + auto check_split = Split(sp, '#'); if (check_split.size() > 2) { error = "Multiple '#' symbols"; diff --git a/src/script/descriptor.h b/src/script/descriptor.h index 0195ca0939..5a1b55259a 100644 --- a/src/script/descriptor.h +++ b/src/script/descriptor.h @@ -11,22 +11,24 @@ #include <vector> -// Descriptors are strings that describe a set of scriptPubKeys, together with -// all information necessary to solve them. By combining all information into -// one, they avoid the need to separately import keys and scripts. -// -// Descriptors may be ranged, which occurs when the public keys inside are -// specified in the form of HD chains (xpubs). -// -// Descriptors always represent public information - public keys and scripts - -// but in cases where private keys need to be conveyed along with a descriptor, -// they can be included inside by changing public keys to private keys (WIF -// format), and changing xpubs by xprvs. -// -// Reference documentation about the descriptor language can be found in -// doc/descriptors.md. - -/** Interface for parsed descriptor objects. */ + +/** \brief Interface for parsed descriptor objects. + * + * Descriptors are strings that describe a set of scriptPubKeys, together with + * all information necessary to solve them. By combining all information into + * one, they avoid the need to separately import keys and scripts. + * + * Descriptors may be ranged, which occurs when the public keys inside are + * specified in the form of HD chains (xpubs). + * + * Descriptors always represent public information - public keys and scripts - + * but in cases where private keys need to be conveyed along with a descriptor, + * they can be included inside by changing public keys to private keys (WIF + * format), and changing xpubs by xprvs. + * + * Reference documentation about the descriptor language can be found in + * doc/descriptors.md. + */ struct Descriptor { virtual ~Descriptor() = default; @@ -45,51 +47,51 @@ struct Descriptor { /** Expand a descriptor at a specified position. * - * pos: the position at which to expand the descriptor. If IsRange() is false, this is ignored. - * provider: the provider to query for private keys in case of hardened derivation. - * output_scripts: the expanded scriptPubKeys will be put here. - * out: scripts and public keys necessary for solving the expanded scriptPubKeys will be put here (may be equal to provider). - * cache: vector which will be overwritten with cache data necessary to evaluate the descriptor at this point without access to private keys. + * @param[in] pos: The position at which to expand the descriptor. If IsRange() is false, this is ignored. + * @param[in] provider: The provider to query for private keys in case of hardened derivation. + * @param[out] output_scripts: The expanded scriptPubKeys. + * @param[out] out: Scripts and public keys necessary for solving the expanded scriptPubKeys (may be equal to `provider`). + * @param[out] cache: Cache data necessary to evaluate the descriptor at this point without access to private keys. */ virtual bool Expand(int pos, const SigningProvider& provider, std::vector<CScript>& output_scripts, FlatSigningProvider& out, std::vector<unsigned char>* cache = nullptr) const = 0; /** Expand a descriptor at a specified position using cached expansion data. * - * pos: the position at which to expand the descriptor. If IsRange() is false, this is ignored. - * cache: vector from which cached expansion data will be read. - * output_scripts: the expanded scriptPubKeys will be put here. - * out: scripts and public keys necessary for solving the expanded scriptPubKeys will be put here (may be equal to provider). + * @param[in] pos: The position at which to expand the descriptor. If IsRange() is false, this is ignored. + * @param[in] cache: Cached expansion data. + * @param[out] output_scripts: The expanded scriptPubKeys. + * @param[out] out: Scripts and public keys necessary for solving the expanded scriptPubKeys (may be equal to `provider`). */ virtual bool ExpandFromCache(int pos, const std::vector<unsigned char>& cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const = 0; /** Expand the private key for a descriptor at a specified position, if possible. * - * pos: the position at which to expand the descriptor. If IsRange() is false, this is ignored. - * provider: the provider to query for the private keys. - * out: any private keys available for the specified pos will be placed here. + * @param[in] pos: The position at which to expand the descriptor. If IsRange() is false, this is ignored. + * @param[in] provider: The provider to query for the private keys. + * @param[out] out: Any private keys available for the specified `pos`. */ virtual void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const = 0; }; -/** Parse a descriptor string. Included private keys are put in out. +/** Parse a `descriptor` string. Included private keys are put in `out`. * - * If the descriptor has a checksum, it must be valid. If require_checksum + * If the descriptor has a checksum, it must be valid. If `require_checksum` * is set, the checksum is mandatory - otherwise it is optional. * * If a parse error occurs, or the checksum is missing/invalid, or anything - * else is wrong, nullptr is returned. + * else is wrong, `nullptr` is returned. */ std::unique_ptr<Descriptor> Parse(const std::string& descriptor, FlatSigningProvider& out, std::string& error, bool require_checksum = false); -/** Get the checksum for a descriptor. +/** Get the checksum for a `descriptor`. * - * If it already has one, and it is correct, return the checksum in the input. - * If it already has one that is wrong, return "". - * If it does not already have one, return the checksum that would need to be added. + * - If it already has one, and it is correct, return the checksum in the input. + * - If it already has one that is wrong, return "". + * - If it does not already have one, return the checksum that would need to be added. */ std::string GetDescriptorChecksum(const std::string& descriptor); -/** Find a descriptor for the specified script, using information from provider where possible. +/** Find a descriptor for the specified `script`, using information from `provider` where possible. * * A non-ranged descriptor which only generates the specified script will be returned in all * circumstances. @@ -98,9 +100,9 @@ std::string GetDescriptorChecksum(const std::string& descriptor); * descriptor. * * - If all information for solving `script` is present in `provider`, a descriptor will be returned - * which is `IsSolvable()` and encapsulates said information. + * which is IsSolvable() and encapsulates said information. * - Failing that, if `script` corresponds to a known address type, an "addr()" descriptor will be - * returned (which is not `IsSolvable()`). + * returned (which is not IsSolvable()). * - Failing that, a "raw()" descriptor is returned. */ std::unique_ptr<Descriptor> InferDescriptor(const CScript& script, const SigningProvider& provider); diff --git a/src/sync.h b/src/sync.h index bdbdde1a2a..8ff6173142 100644 --- a/src/sync.h +++ b/src/sync.h @@ -7,6 +7,7 @@ #define BITCOIN_SYNC_H #include <threadsafety.h> +#include <util/macros.h> #include <condition_variable> #include <thread> @@ -176,9 +177,6 @@ public: template<typename MutexArg> using DebugLock = UniqueLock<typename std::remove_reference<typename std::remove_pointer<MutexArg>::type>::type>; -#define PASTE(x, y) x ## y -#define PASTE2(x, y) PASTE(x, y) - #define LOCK(cs) DebugLock<decltype(cs)> PASTE2(criticalblock, __COUNTER__)(cs, #cs, __FILE__, __LINE__) #define LOCK2(cs1, cs2) \ DebugLock<decltype(cs1)> criticalblock1(cs1, #cs1, __FILE__, __LINE__); \ diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index b0a613372f..1928324b27 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -78,7 +78,7 @@ BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup) BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) { auto connman = MakeUnique<CConnman>(0x1337, 0x1337); - auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, scheduler, false); + auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, scheduler); // Mock an outbound peer CAddress addr1(ip(0xa0b0c001), NODE_NONE); @@ -148,7 +148,7 @@ static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidat BOOST_AUTO_TEST_CASE(stale_tip_peer_management) { auto connman = MakeUnique<CConnmanTest>(0x1337, 0x1337); - auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, scheduler, false); + auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), nullptr, scheduler); const Consensus::Params& consensusParams = Params().GetConsensus(); constexpr int max_outbound_full_relay = 8; @@ -221,7 +221,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) { auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto connman = MakeUnique<CConnman>(0x1337, 0x1337); - auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler, false); + auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler); banman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); @@ -276,7 +276,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) { auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto connman = MakeUnique<CConnman>(0x1337, 0x1337); - auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler, false); + auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler); banman->ClearBanned(); gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number @@ -323,7 +323,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) { auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME); auto connman = MakeUnique<CConnman>(0x1337, 0x1337); - auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler, false); + auto peerLogic = MakeUnique<PeerLogicValidation>(connman.get(), banman.get(), scheduler); banman->ClearBanned(); int64_t nStartTime = GetTime(); diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp index 50ac0bd7b8..55726a4a8f 100644 --- a/src/test/descriptor_tests.cpp +++ b/src/test/descriptor_tests.cpp @@ -252,7 +252,10 @@ BOOST_AUTO_TEST_CASE(descriptor_test) // Multisig constructions Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}); + Check("sortedmulti(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "sortedmulti(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}); + Check("sortedmulti(1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sortedmulti(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}}); Check("sh(multi(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,[00000000/111'/222]xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}}, {{0x8000006FUL,222},{0}}); + Check("sortedmulti(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/*,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0/0/*)", "sortedmulti(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*)", RANGE, {{"5221025d5fc65ebb8d44a5274b53bac21ff8307fec2334a32df05553459f8b1f7fe1b62102fbd47cc8034098f0e6a94c6aeee8528abf0a2153a5d8e46d325b7284c046784652ae"}, {"52210264fd4d1f5dea8ded94c61e9641309349b62f27fbffe807291f664e286bfbe6472103f4ece6dfccfa37b211eb3d0af4d0c61dba9ef698622dc17eecdf764beeb005a652ae"}, {"5221022ccabda84c30bad578b13c89eb3b9544ce149787e5b538175b1d1ba259cbb83321024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c52ae"}}, {{0}, {1}, {2}, {0, 0, 0}, {0, 0, 1}, {0, 0, 2}}); Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}}, {{0xFFFFFFFFUL,0}, {1,2,0}, {1,2,1}, {1,2,2}, {10, 20, 30, 40, 0x80000000UL}, {10, 20, 30, 40, 0x80000001UL}, {10, 20, 30, 40, 0x80000002UL}}); Check("sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", SIGNABLE, {{"a9147fc63e13dc25e8a95a3cee3d9a714ac3afd96f1e87"}}); CheckUnparsable("sh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9))","sh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232))", "P2SH script is too large, 547 bytes is larger than 520 bytes"); // P2SH does not fit 16 compressed pubkeys in a redeemscript diff --git a/src/test/fs_tests.cpp b/src/test/fs_tests.cpp index 6d5a6641f0..b504a3cbb1 100644 --- a/src/test/fs_tests.cpp +++ b/src/test/fs_tests.cpp @@ -15,7 +15,7 @@ BOOST_AUTO_TEST_CASE(fsbridge_fstream) fs::path tmpfolder = GetDataDir(); // tmpfile1 should be the same as tmpfile2 fs::path tmpfile1 = tmpfolder / "fs_tests_₿_🏃"; - fs::path tmpfile2 = tmpfolder / L"fs_tests_₿_🏃"; + fs::path tmpfile2 = tmpfolder / "fs_tests_₿_🏃"; { fsbridge::ofstream file(tmpfile1); file << "bitcoin"; diff --git a/src/test/fuzz/FuzzedDataProvider.h b/src/test/fuzz/FuzzedDataProvider.h new file mode 100644 index 0000000000..1b5b4bb012 --- /dev/null +++ b/src/test/fuzz/FuzzedDataProvider.h @@ -0,0 +1,245 @@ +//===- FuzzedDataProvider.h - Utility header for fuzz targets ---*- C++ -* ===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// A single header library providing an utility class to break up an array of +// bytes. Whenever run on the same input, provides the same output, as long as +// its methods are called in the same order, with the same arguments. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_ +#define LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_ + +#include <limits.h> +#include <stddef.h> +#include <stdint.h> + +#include <algorithm> +#include <cstring> +#include <initializer_list> +#include <string> +#include <type_traits> +#include <utility> +#include <vector> + +class FuzzedDataProvider { +public: + // |data| is an array of length |size| that the FuzzedDataProvider wraps to + // provide more granular access. |data| must outlive the FuzzedDataProvider. + FuzzedDataProvider(const uint8_t *data, size_t size) + : data_ptr_(data), remaining_bytes_(size) {} + ~FuzzedDataProvider() = default; + + // Returns a std::vector containing |num_bytes| of input data. If fewer than + // |num_bytes| of data remain, returns a shorter std::vector containing all + // of the data that's left. Can be used with any byte sized type, such as + // char, unsigned char, uint8_t, etc. + template <typename T> std::vector<T> ConsumeBytes(size_t num_bytes) { + num_bytes = std::min(num_bytes, remaining_bytes_); + return ConsumeBytes<T>(num_bytes, num_bytes); + } + + // Similar to |ConsumeBytes|, but also appends the terminator value at the end + // of the resulting vector. Useful, when a mutable null-terminated C-string is + // needed, for example. But that is a rare case. Better avoid it, if possible, + // and prefer using |ConsumeBytes| or |ConsumeBytesAsString| methods. + template <typename T> + std::vector<T> ConsumeBytesWithTerminator(size_t num_bytes, + T terminator = 0) { + num_bytes = std::min(num_bytes, remaining_bytes_); + std::vector<T> result = ConsumeBytes<T>(num_bytes + 1, num_bytes); + result.back() = terminator; + return result; + } + + // Returns a std::string containing |num_bytes| of input data. Using this and + // |.c_str()| on the resulting string is the best way to get an immutable + // null-terminated C string. If fewer than |num_bytes| of data remain, returns + // a shorter std::string containing all of the data that's left. + std::string ConsumeBytesAsString(size_t num_bytes) { + static_assert(sizeof(std::string::value_type) == sizeof(uint8_t), + "ConsumeBytesAsString cannot convert the data to a string."); + + num_bytes = std::min(num_bytes, remaining_bytes_); + std::string result( + reinterpret_cast<const std::string::value_type *>(data_ptr_), + num_bytes); + Advance(num_bytes); + return result; + } + + // Returns a number in the range [min, max] by consuming bytes from the + // input data. The value might not be uniformly distributed in the given + // range. If there's no input data left, always returns |min|. |min| must + // be less than or equal to |max|. + template <typename T> T ConsumeIntegralInRange(T min, T max) { + static_assert(std::is_integral<T>::value, "An integral type is required."); + static_assert(sizeof(T) <= sizeof(uint64_t), "Unsupported integral type."); + + if (min > max) + abort(); + + // Use the biggest type possible to hold the range and the result. + uint64_t range = static_cast<uint64_t>(max) - min; + uint64_t result = 0; + size_t offset = 0; + + while (offset < sizeof(T) * CHAR_BIT && (range >> offset) > 0 && + remaining_bytes_ != 0) { + // Pull bytes off the end of the seed data. Experimentally, this seems to + // allow the fuzzer to more easily explore the input space. This makes + // sense, since it works by modifying inputs that caused new code to run, + // and this data is often used to encode length of data read by + // |ConsumeBytes|. Separating out read lengths makes it easier modify the + // contents of the data that is actually read. + --remaining_bytes_; + result = (result << CHAR_BIT) | data_ptr_[remaining_bytes_]; + offset += CHAR_BIT; + } + + // Avoid division by 0, in case |range + 1| results in overflow. + if (range != std::numeric_limits<decltype(range)>::max()) + result = result % (range + 1); + + return static_cast<T>(min + result); + } + + // Returns a std::string of length from 0 to |max_length|. When it runs out of + // input data, returns what remains of the input. Designed to be more stable + // with respect to a fuzzer inserting characters than just picking a random + // length and then consuming that many bytes with |ConsumeBytes|. + std::string ConsumeRandomLengthString(size_t max_length) { + // Reads bytes from the start of |data_ptr_|. Maps "\\" to "\", and maps "\" + // followed by anything else to the end of the string. As a result of this + // logic, a fuzzer can insert characters into the string, and the string + // will be lengthened to include those new characters, resulting in a more + // stable fuzzer than picking the length of a string independently from + // picking its contents. + std::string result; + + // Reserve the anticipated capaticity to prevent several reallocations. + result.reserve(std::min(max_length, remaining_bytes_)); + for (size_t i = 0; i < max_length && remaining_bytes_ != 0; ++i) { + char next = ConvertUnsignedToSigned<char>(data_ptr_[0]); + Advance(1); + if (next == '\\' && remaining_bytes_ != 0) { + next = ConvertUnsignedToSigned<char>(data_ptr_[0]); + Advance(1); + if (next != '\\') + break; + } + result += next; + } + + result.shrink_to_fit(); + return result; + } + + // Returns a std::vector containing all remaining bytes of the input data. + template <typename T> std::vector<T> ConsumeRemainingBytes() { + return ConsumeBytes<T>(remaining_bytes_); + } + + // Prefer using |ConsumeRemainingBytes| unless you actually need a std::string + // object. + // Returns a std::vector containing all remaining bytes of the input data. + std::string ConsumeRemainingBytesAsString() { + return ConsumeBytesAsString(remaining_bytes_); + } + + // Returns a number in the range [Type's min, Type's max]. The value might + // not be uniformly distributed in the given range. If there's no input data + // left, always returns |min|. + template <typename T> T ConsumeIntegral() { + return ConsumeIntegralInRange(std::numeric_limits<T>::min(), + std::numeric_limits<T>::max()); + } + + // Reads one byte and returns a bool, or false when no data remains. + bool ConsumeBool() { return 1 & ConsumeIntegral<uint8_t>(); } + + // Returns a copy of a value selected from a fixed-size |array|. + template <typename T, size_t size> + T PickValueInArray(const T (&array)[size]) { + static_assert(size > 0, "The array must be non empty."); + return array[ConsumeIntegralInRange<size_t>(0, size - 1)]; + } + + template <typename T> + T PickValueInArray(std::initializer_list<const T> list) { + // static_assert(list.size() > 0, "The array must be non empty."); + return *(list.begin() + ConsumeIntegralInRange<size_t>(0, list.size() - 1)); + } + + // Return an enum value. The enum must start at 0 and be contiguous. It must + // also contain |kMaxValue| aliased to its largest (inclusive) value. Such as: + // enum class Foo { SomeValue, OtherValue, kMaxValue = OtherValue }; + template <typename T> T ConsumeEnum() { + static_assert(std::is_enum<T>::value, "|T| must be an enum type."); + return static_cast<T>(ConsumeIntegralInRange<uint32_t>( + 0, static_cast<uint32_t>(T::kMaxValue))); + } + + // Reports the remaining bytes available for fuzzed input. + size_t remaining_bytes() { return remaining_bytes_; } + +private: + FuzzedDataProvider(const FuzzedDataProvider &) = delete; + FuzzedDataProvider &operator=(const FuzzedDataProvider &) = delete; + + void Advance(size_t num_bytes) { + if (num_bytes > remaining_bytes_) + abort(); + + data_ptr_ += num_bytes; + remaining_bytes_ -= num_bytes; + } + + template <typename T> + std::vector<T> ConsumeBytes(size_t size, size_t num_bytes_to_consume) { + static_assert(sizeof(T) == sizeof(uint8_t), "Incompatible data type."); + + // The point of using the size-based constructor below is to increase the + // odds of having a vector object with capacity being equal to the length. + // That part is always implementation specific, but at least both libc++ and + // libstdc++ allocate the requested number of bytes in that constructor, + // which seems to be a natural choice for other implementations as well. + // To increase the odds even more, we also call |shrink_to_fit| below. + std::vector<T> result(size); + std::memcpy(result.data(), data_ptr_, num_bytes_to_consume); + Advance(num_bytes_to_consume); + + // Even though |shrink_to_fit| is also implementation specific, we expect it + // to provide an additional assurance in case vector's constructor allocated + // a buffer which is larger than the actual amount of data we put inside it. + result.shrink_to_fit(); + return result; + } + + template <typename TS, typename TU> TS ConvertUnsignedToSigned(TU value) { + static_assert(sizeof(TS) == sizeof(TU), "Incompatible data types."); + static_assert(!std::numeric_limits<TU>::is_signed, + "Source type must be unsigned."); + + // TODO(Dor1s): change to `if constexpr` once C++17 becomes mainstream. + if (std::numeric_limits<TS>::is_modulo) + return static_cast<TS>(value); + + // Avoid using implementation-defined unsigned to signer conversions. + // To learn more, see https://stackoverflow.com/questions/13150449. + if (value <= std::numeric_limits<TS>::max()) + return static_cast<TS>(value); + else { + constexpr auto TS_min = std::numeric_limits<TS>::min(); + return TS_min + static_cast<char>(value - TS_min); + } + } + + const uint8_t *data_ptr_; + size_t remaining_bytes_; +}; + +#endif // LLVM_FUZZER_FUZZED_DATA_PROVIDER_H_ diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp index 9364ac4a32..3a6876ad39 100644 --- a/src/test/fuzz/deserialize.cpp +++ b/src/test/fuzz/deserialize.cpp @@ -23,7 +23,7 @@ #include <test/fuzz/fuzz.h> -void test_one_input(std::vector<uint8_t> buffer) +void test_one_input(const std::vector<uint8_t>& buffer) { CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); try { @@ -40,11 +40,6 @@ void test_one_input(std::vector<uint8_t> buffer) CBlock block; ds >> block; } catch (const std::ios_base::failure& e) {return;} -#elif TRANSACTION_DESERIALIZE - try - { - CTransaction tx(deserialize, ds); - } catch (const std::ios_base::failure& e) {return;} #elif BLOCKLOCATOR_DESERIALIZE try { diff --git a/src/test/fuzz/eval_script.cpp b/src/test/fuzz/eval_script.cpp new file mode 100644 index 0000000000..9444cd489e --- /dev/null +++ b/src/test/fuzz/eval_script.cpp @@ -0,0 +1,30 @@ +// Copyright (c) 2009-2019 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 <script/interpreter.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> + +#include <limits> + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + const unsigned int flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>(); + const std::vector<uint8_t> script_bytes = [&] { + if (fuzzed_data_provider.remaining_bytes() != 0) { + return fuzzed_data_provider.ConsumeRemainingBytes<uint8_t>(); + } else { + // Avoid UBSan warning: + // test/fuzz/FuzzedDataProvider.h:212:17: runtime error: null pointer passed as argument 1, which is declared to never be null + // /usr/include/string.h:43:28: note: nonnull attribute specified here + return std::vector<uint8_t>(); + } + }(); + const CScript script(script_bytes.begin(), script_bytes.end()); + for (const auto sig_version : {SigVersion::BASE, SigVersion::WITNESS_V0}) { + std::vector<std::vector<unsigned char>> stack; + (void)EvalScript(stack, script, flags, BaseSignatureChecker(), sig_version, nullptr); + } +} diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp index 0709da5563..cfa160dde2 100644 --- a/src/test/fuzz/fuzz.cpp +++ b/src/test/fuzz/fuzz.cpp @@ -30,7 +30,8 @@ static void initialize() // This function is used by libFuzzer extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - test_one_input(std::vector<uint8_t>(data, data + size)); + const std::vector<uint8_t> input(data, data + size); + test_one_input(input); return 0; } diff --git a/src/test/fuzz/fuzz.h b/src/test/fuzz/fuzz.h index 4e009d9b54..573bd572db 100644 --- a/src/test/fuzz/fuzz.h +++ b/src/test/fuzz/fuzz.h @@ -9,6 +9,6 @@ #include <vector> -void test_one_input(std::vector<uint8_t> buffer); +void test_one_input(const std::vector<uint8_t>& buffer); #endif // BITCOIN_TEST_FUZZ_FUZZ_H diff --git a/src/test/fuzz/script_flags.cpp b/src/test/fuzz/script_flags.cpp index 9b90d66755..0bf5cd5c72 100644 --- a/src/test/fuzz/script_flags.cpp +++ b/src/test/fuzz/script_flags.cpp @@ -11,7 +11,7 @@ /** Flags that are not forbidden by an assert */ static bool IsValidFlagCombination(unsigned flags); -void test_one_input(std::vector<uint8_t> buffer) +void test_one_input(const std::vector<uint8_t>& buffer) { CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); try { diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp new file mode 100644 index 0000000000..96d7947b07 --- /dev/null +++ b/src/test/fuzz/transaction.cpp @@ -0,0 +1,81 @@ +// Copyright (c) 2019 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 <coins.h> +#include <consensus/tx_check.h> +#include <consensus/tx_verify.h> +#include <consensus/validation.h> +#include <core_io.h> +#include <core_memusage.h> +#include <policy/policy.h> +#include <policy/settings.h> +#include <primitives/transaction.h> +#include <streams.h> +#include <test/fuzz/fuzz.h> +#include <util/rbf.h> +#include <validation.h> +#include <version.h> + +#include <cassert> + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); + try { + int nVersion; + ds >> nVersion; + ds.SetVersion(nVersion); + } catch (const std::ios_base::failure& e) { + return; + } + bool valid = true; + const CTransaction tx = [&] { + try { + return CTransaction(deserialize, ds); + } catch (const std::ios_base::failure& e) { + valid = false; + return CTransaction(); + } + }(); + if (!valid) { + return; + } + + CValidationState state_with_dupe_check; + const bool valid_with_dupe_check = CheckTransaction(tx, state_with_dupe_check, /* fCheckDuplicateInputs= */ true); + CValidationState state_without_dupe_check; + const bool valid_without_dupe_check = CheckTransaction(tx, state_without_dupe_check, /* fCheckDuplicateInputs= */ false); + if (valid_with_dupe_check) { + assert(valid_without_dupe_check); + } + + const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE}; + std::string reason; + const bool is_standard_with_permit_bare_multisig = IsStandardTx(tx, /* permit_bare_multisig= */ true, dust_relay_fee, reason); + const bool is_standard_without_permit_bare_multisig = IsStandardTx(tx, /* permit_bare_multisig= */ false, dust_relay_fee, reason); + if (is_standard_without_permit_bare_multisig) { + assert(is_standard_with_permit_bare_multisig); + } + + (void)tx.GetHash(); + (void)tx.GetTotalSize(); + try { + (void)tx.GetValueOut(); + } catch (const std::runtime_error&) { + } + (void)tx.GetWitnessHash(); + (void)tx.HasWitness(); + (void)tx.IsCoinBase(); + (void)tx.IsNull(); + (void)tx.ToString(); + + (void)EncodeHexTx(tx); + (void)GetLegacySigOpCount(tx); + (void)GetTransactionWeight(tx); + (void)GetVirtualTransactionSize(tx); + (void)IsFinalTx(tx, /* nBlockHeight= */ 1024, /* nBlockTime= */ 1024); + (void)IsStandardTx(tx, reason); + (void)RecursiveDynamicUsage(tx); + (void)SignalsOptInRBF(tx); +} diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index d0cd4b0a03..31a66b6fa9 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -12,6 +12,7 @@ #include <util/strencodings.h> #include <util/string.h> #include <util/time.h> +#include <util/spanparsing.h> #include <stdint.h> #include <thread> @@ -1572,4 +1573,127 @@ BOOST_AUTO_TEST_CASE(test_Capitalize) BOOST_CHECK_EQUAL(Capitalize("\x00\xfe\xff"), "\x00\xfe\xff"); } +static std::string SpanToStr(Span<const char>& span) +{ + return std::string(span.begin(), span.end()); +} + +BOOST_AUTO_TEST_CASE(test_spanparsing) +{ + using namespace spanparsing; + std::string input; + Span<const char> sp; + bool success; + + // Const(...): parse a constant, update span to skip it if successful + input = "MilkToastHoney"; + sp = MakeSpan(input); + success = Const("", sp); // empty + BOOST_CHECK(success); + BOOST_CHECK_EQUAL(SpanToStr(sp), "MilkToastHoney"); + + success = Const("Milk", sp); + BOOST_CHECK(success); + BOOST_CHECK_EQUAL(SpanToStr(sp), "ToastHoney"); + + success = Const("Bread", sp); + BOOST_CHECK(!success); + + success = Const("Toast", sp); + BOOST_CHECK(success); + BOOST_CHECK_EQUAL(SpanToStr(sp), "Honey"); + + success = Const("Honeybadger", sp); + BOOST_CHECK(!success); + + success = Const("Honey", sp); + BOOST_CHECK(success); + BOOST_CHECK_EQUAL(SpanToStr(sp), ""); + + // Func(...): parse a function call, update span to argument if successful + input = "Foo(Bar(xy,z()))"; + sp = MakeSpan(input); + + success = Func("FooBar", sp); + BOOST_CHECK(!success); + + success = Func("Foo(", sp); + BOOST_CHECK(!success); + + success = Func("Foo", sp); + BOOST_CHECK(success); + BOOST_CHECK_EQUAL(SpanToStr(sp), "Bar(xy,z())"); + + success = Func("Bar", sp); + BOOST_CHECK(success); + BOOST_CHECK_EQUAL(SpanToStr(sp), "xy,z()"); + + success = Func("xy", sp); + BOOST_CHECK(!success); + + // Expr(...): return expression that span begins with, update span to skip it + Span<const char> result; + + input = "(n*(n-1))/2"; + sp = MakeSpan(input); + result = Expr(sp); + BOOST_CHECK_EQUAL(SpanToStr(result), "(n*(n-1))/2"); + BOOST_CHECK_EQUAL(SpanToStr(sp), ""); + + input = "foo,bar"; + sp = MakeSpan(input); + result = Expr(sp); + BOOST_CHECK_EQUAL(SpanToStr(result), "foo"); + BOOST_CHECK_EQUAL(SpanToStr(sp), ",bar"); + + input = "(aaaaa,bbbbb()),c"; + sp = MakeSpan(input); + result = Expr(sp); + BOOST_CHECK_EQUAL(SpanToStr(result), "(aaaaa,bbbbb())"); + BOOST_CHECK_EQUAL(SpanToStr(sp), ",c"); + + input = "xyz)foo"; + sp = MakeSpan(input); + result = Expr(sp); + BOOST_CHECK_EQUAL(SpanToStr(result), "xyz"); + BOOST_CHECK_EQUAL(SpanToStr(sp), ")foo"); + + input = "((a),(b),(c)),xxx"; + sp = MakeSpan(input); + result = Expr(sp); + BOOST_CHECK_EQUAL(SpanToStr(result), "((a),(b),(c))"); + BOOST_CHECK_EQUAL(SpanToStr(sp), ",xxx"); + + // Split(...): split a string on every instance of sep, return vector + std::vector<Span<const char>> results; + + input = "xxx"; + results = Split(MakeSpan(input), 'x'); + BOOST_CHECK_EQUAL(results.size(), 4); + BOOST_CHECK_EQUAL(SpanToStr(results[0]), ""); + BOOST_CHECK_EQUAL(SpanToStr(results[1]), ""); + BOOST_CHECK_EQUAL(SpanToStr(results[2]), ""); + BOOST_CHECK_EQUAL(SpanToStr(results[3]), ""); + + input = "one#two#three"; + results = Split(MakeSpan(input), '-'); + BOOST_CHECK_EQUAL(results.size(), 1); + BOOST_CHECK_EQUAL(SpanToStr(results[0]), "one#two#three"); + + input = "one#two#three"; + results = Split(MakeSpan(input), '#'); + BOOST_CHECK_EQUAL(results.size(), 3); + BOOST_CHECK_EQUAL(SpanToStr(results[0]), "one"); + BOOST_CHECK_EQUAL(SpanToStr(results[1]), "two"); + BOOST_CHECK_EQUAL(SpanToStr(results[2]), "three"); + + input = "*foo*bar*"; + results = Split(MakeSpan(input), '*'); + BOOST_CHECK_EQUAL(results.size(), 4); + BOOST_CHECK_EQUAL(SpanToStr(results[0]), ""); + BOOST_CHECK_EQUAL(SpanToStr(results[1]), "foo"); + BOOST_CHECK_EQUAL(SpanToStr(results[2]), "bar"); + BOOST_CHECK_EQUAL(SpanToStr(results[3]), ""); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/txdb.cpp b/src/txdb.cpp index 18be07e6db..536bfee901 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -145,7 +145,7 @@ size_t CCoinsViewDB::EstimateSize() const return db.EstimateSize(DB_COIN, (char)(DB_COIN+1)); } -CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(gArgs.IsArgSet("-blocksdir") ? GetDataDir() / "blocks" / "index" : GetBlocksDir() / "index", nCacheSize, fMemory, fWipe) { +CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) { } bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) { diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 835b8d63bd..e4c1fd4bc6 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -773,7 +773,7 @@ void CTxMemPool::queryHashes(std::vector<uint256>& vtxid) const } static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it) { - return TxMempoolInfo{it->GetSharedTx(), it->GetTime(), CFeeRate(it->GetFee(), it->GetTxSize()), it->GetModifiedFee() - it->GetFee()}; + return TxMempoolInfo{it->GetSharedTx(), it->GetTime(), it->GetFee(), it->GetTxSize(), it->GetModifiedFee() - it->GetFee()}; } std::vector<TxMempoolInfo> CTxMemPool::infoAll() const diff --git a/src/txmempool.h b/src/txmempool.h index f2fc1c8310..229a923a28 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -334,8 +334,11 @@ struct TxMempoolInfo /** Time the transaction entered the mempool. */ std::chrono::seconds m_time; - /** Feerate of the transaction. */ - CFeeRate feeRate; + /** Fee of the transaction. */ + CAmount fee; + + /** Virtual size of the transaction. */ + size_t vsize; /** The fee delta. */ int64_t nFeeDelta; diff --git a/src/util/macros.h b/src/util/macros.h new file mode 100644 index 0000000000..36ea87c0fe --- /dev/null +++ b/src/util/macros.h @@ -0,0 +1,11 @@ +// Copyright (c) 2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UTIL_MACROS_H +#define BITCOIN_UTIL_MACROS_H + +#define PASTE(x, y) x ## y +#define PASTE2(x, y) PASTE(x, y) + +#endif // BITCOIN_UTIL_MACROS_H diff --git a/src/util/spanparsing.cpp b/src/util/spanparsing.cpp new file mode 100644 index 0000000000..0c8575399a --- /dev/null +++ b/src/util/spanparsing.cpp @@ -0,0 +1,67 @@ +// 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. + +#include <util/spanparsing.h> + +#include <span.h> + +#include <string> +#include <vector> + +namespace spanparsing { + +bool Const(const std::string& str, Span<const char>& sp) +{ + if ((size_t)sp.size() >= str.size() && std::equal(str.begin(), str.end(), sp.begin())) { + sp = sp.subspan(str.size()); + return true; + } + return false; +} + +bool Func(const std::string& str, Span<const char>& sp) +{ + if ((size_t)sp.size() >= str.size() + 2 && sp[str.size()] == '(' && sp[sp.size() - 1] == ')' && std::equal(str.begin(), str.end(), sp.begin())) { + sp = sp.subspan(str.size() + 1, sp.size() - str.size() - 2); + return true; + } + return false; +} + +Span<const char> Expr(Span<const char>& sp) +{ + int level = 0; + auto it = sp.begin(); + while (it != sp.end()) { + if (*it == '(') { + ++level; + } else if (level && *it == ')') { + --level; + } else if (level == 0 && (*it == ')' || *it == ',')) { + break; + } + ++it; + } + Span<const char> ret = sp.first(it - sp.begin()); + sp = sp.subspan(it - sp.begin()); + return ret; +} + +std::vector<Span<const char>> Split(const Span<const char>& sp, char sep) +{ + std::vector<Span<const char>> ret; + auto it = sp.begin(); + auto start = it; + while (it != sp.end()) { + if (*it == sep) { + ret.emplace_back(start, it); + start = it + 1; + } + ++it; + } + ret.emplace_back(start, it); + return ret; +} + +} // namespace spanparsing diff --git a/src/util/spanparsing.h b/src/util/spanparsing.h new file mode 100644 index 0000000000..63f54758bd --- /dev/null +++ b/src/util/spanparsing.h @@ -0,0 +1,50 @@ +// 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. + +#ifndef BITCOIN_UTIL_SPANPARSING_H +#define BITCOIN_UTIL_SPANPARSING_H + +#include <span.h> + +#include <string> +#include <vector> + +namespace spanparsing { + +/** Parse a constant. + * + * If sp's initial part matches str, sp is updated to skip that part, and true is returned. + * Otherwise sp is unmodified and false is returned. + */ +bool Const(const std::string& str, Span<const char>& sp); + +/** Parse a function call. + * + * If sp's initial part matches str + "(", and sp ends with ")", sp is updated to be the + * section between the braces, and true is returned. Otherwise sp is unmodified and false + * is returned. + */ +bool Func(const std::string& str, Span<const char>& sp); + +/** Extract the expression that sp begins with. + * + * This function will return the initial part of sp, up to (but not including) the first + * comma or closing brace, skipping ones that are surrounded by braces. So for example, + * for "foo(bar(1),2),3" the initial part "foo(bar(1),2)" will be returned. sp will be + * updated to skip the initial part that is returned. + */ +Span<const char> Expr(Span<const char>& sp); + +/** Split a string on every instance of sep, returning a vector. + * + * If sep does not occur in sp, a singleton with the entirety of sp is returned. + * + * Note that this function does not care about braces, so splitting + * "foo(bar(1),2),3) on ',' will return {"foo(bar(1)", "2)", "3)"}. + */ +std::vector<Span<const char>> Split(const Span<const char>& sp, char sep); + +} // namespace spanparsing + +#endif // BITCOIN_UTIL_SPANPARSING_H diff --git a/src/util/system.cpp b/src/util/system.cpp index 8098cde093..f22256615f 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -1153,12 +1153,12 @@ void SetupEnvironment() } #endif // On most POSIX systems (e.g. Linux, but not BSD) the environment's locale - // may be invalid, in which case the "C" locale is used as fallback. + // may be invalid, in which case the "C.UTF-8" locale is used as fallback. #if !defined(WIN32) && !defined(MAC_OSX) && !defined(__FreeBSD__) && !defined(__OpenBSD__) try { std::locale(""); // Raises a runtime error if current locale is invalid } catch (const std::runtime_error&) { - setenv("LC_ALL", "C", 1); + setenv("LC_ALL", "C.UTF-8", 1); } #elif defined(WIN32) // Set the default input/output charset is utf-8 diff --git a/src/util/threadnames.cpp b/src/util/threadnames.cpp index c25e9ed661..168f9325d0 100644 --- a/src/util/threadnames.cpp +++ b/src/util/threadnames.cpp @@ -60,3 +60,8 @@ void util::ThreadRename(std::string&& name) SetThreadName(("b-" + name).c_str()); SetInternalName(std::move(name)); } + +void util::ThreadSetInternalName(std::string&& name) +{ + SetInternalName(std::move(name)); +} diff --git a/src/util/threadnames.h b/src/util/threadnames.h index aaf07b9bf8..69a1b55bfe 100644 --- a/src/util/threadnames.h +++ b/src/util/threadnames.h @@ -10,8 +10,13 @@ namespace util { //! Rename a thread both in terms of an internal (in-memory) name as well //! as its system thread name. +//! @note Do not call this for the main thread, as this will interfere with +//! UNIX utilities such as top and killall. Use ThreadSetInternalName instead. void ThreadRename(std::string&&); +//! Set the internal (in-memory) name of the current thread only. +void ThreadSetInternalName(std::string&&); + //! Get the thread's internal (in-memory) name; used e.g. for identification in //! logging. const std::string& ThreadGetInternalName(); diff --git a/src/validation.h b/src/validation.h index 96d249b6d3..fbbe3757e0 100644 --- a/src/validation.h +++ b/src/validation.h @@ -102,8 +102,6 @@ static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024; static const unsigned int DATABASE_WRITE_INTERVAL = 60 * 60; /** Time to wait (in seconds) between flushing chainstate to disk. */ static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60; -/** Maximum length of reject messages. */ -static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; /** Block download timeout base, expressed in millionths of the block interval (i.e. 10 min) */ static const int64_t BLOCK_DOWNLOAD_TIMEOUT_BASE = 1000000; /** Additional block download timeout per parallel downloading peer (i.e. 5 min) */ diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 96fa50d42e..dc437e5cd8 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1190,7 +1190,7 @@ static UniValue listreceivedbyaddress(const JSONRPCRequest& request) RPCResult{ "[\n" " {\n" - " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n" + " \"involvesWatchonly\" : true, (bool) Only returns true if imported addresses were involved in transaction.\n" " \"address\" : \"receivingaddress\", (string) The receiving address\n" " \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n" " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n" @@ -1240,7 +1240,7 @@ static UniValue listreceivedbylabel(const JSONRPCRequest& request) RPCResult{ "[\n" " {\n" - " \"involvesWatchonly\" : true, (bool) Only returned if imported addresses were involved in transaction\n" + " \"involvesWatchonly\" : true, (bool) Only returns true if imported addresses were involved in transaction.\n" " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this label\n" " \"confirmations\" : n, (numeric) The number of confirmations of the most recent transaction included\n" " \"label\" : \"label\" (string) The label of the receiving address. The default label is \"\".\n" @@ -1359,6 +1359,27 @@ static void ListTransactions(interfaces::Chain::Lock& locked_chain, CWallet* con } } +static const std::string TransactionDescriptionString() +{ + return " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Negative confirmations means the\n" + " transaction conflicted that many blocks ago.\n" + " \"generated\": xxx, (bool) Only present if transaction only input is a coinbase one.\n" + " \"trusted\": xxx, (bool) Only present if we consider transaction to be trusted and so safe to spend from.\n" + " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction.\n" + " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it.\n" + " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n" + " \"txid\": \"transactionid\", (string) The transaction id.\n" + " \"walletconflicts\": [ (array) Conflicting transaction ids.\n" + " \"txid\", (string) The transaction id.\n" + " ...\n" + " ],\n" + " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n" + " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT).\n" + " \"comment\": \"...\", (string) If a comment is associated with the transaction, only present if not empty.\n" + " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n" + " may be unknown for unconfirmed transactions not in the mempool\n"; +} + UniValue listtransactions(const JSONRPCRequest& request) { std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); @@ -1381,6 +1402,7 @@ UniValue listtransactions(const JSONRPCRequest& request) RPCResult{ "[\n" " {\n" + " \"involvesWatchonly\": xxx, (bool) Only returns true if imported addresses were involved in transaction.\n" " \"address\":\"address\", (string) The bitcoin address of the transaction.\n" " \"category\": (string) The transaction category.\n" " \"send\" Transactions sent.\n" @@ -1394,19 +1416,8 @@ UniValue listtransactions(const JSONRPCRequest& request) " \"vout\": n, (numeric) the vout value\n" " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n" " 'send' category of transactions.\n" - " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Negative confirmations indicate the\n" - " transaction conflicts with the block chain\n" - " \"trusted\": xxx, (bool) Whether we consider the outputs of this unconfirmed transaction safe to spend.\n" - " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction.\n" - " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it.\n" - " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n" - " \"txid\": \"transactionid\", (string) The transaction id.\n" - " \"time\": xxx, (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n" - " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT).\n" - " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n" - " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n" - " may be unknown for unconfirmed transactions not in the mempool\n" - " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n" + + TransactionDescriptionString() + + " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n" " 'send' category of transactions.\n" " }\n" "]\n" @@ -1515,6 +1526,7 @@ static UniValue listsinceblock(const JSONRPCRequest& request) RPCResult{ "{\n" " \"transactions\": [\n" + " \"involvesWatchonly\": xxx, (bool) Only returns true if imported addresses were involved in transaction.\n" " \"address\":\"address\", (string) The bitcoin address of the transaction.\n" " \"category\": (string) The transaction category.\n" " \"send\" Transactions sent.\n" @@ -1526,17 +1538,8 @@ static UniValue listsinceblock(const JSONRPCRequest& request) " for all other categories\n" " \"vout\" : n, (numeric) the vout value\n" " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the 'send' category of transactions.\n" - " \"confirmations\": n, (numeric) The number of confirmations for the transaction.\n" - " When it's < 0, it means the transaction conflicted that many blocks ago.\n" - " \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction.\n" - " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it.\n" - " \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n" - " \"txid\": \"transactionid\", (string) The transaction id.\n" - " \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n" - " \"timereceived\": xxx, (numeric) The time received in seconds since epoch (Jan 1 1970 GMT).\n" - " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n" - " may be unknown for unconfirmed transactions not in the mempool\n" - " \"abandoned\": xxx, (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the 'send' category of transactions.\n" + + TransactionDescriptionString() + + " \"abandoned\": xxx, (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the 'send' category of transactions.\n" " \"comment\": \"...\", (string) If a comment is associated with the transaction.\n" " \"label\" : \"label\" (string) A comment for the address/transaction, if any\n" " \"to\": \"...\", (string) If a comment to is associated with the transaction.\n" @@ -1655,40 +1658,33 @@ static UniValue gettransaction(const JSONRPCRequest& request) }, RPCResult{ "{\n" - " \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n" - " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n" + " \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n" + " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n" " 'send' category of transactions.\n" - " \"confirmations\" : n, (numeric) The number of confirmations\n" - " \"blockhash\" : \"hash\", (string) The block hash\n" - " \"blockindex\" : xx, (numeric) The index of the transaction in the block that includes it\n" - " \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n" - " \"txid\" : \"transactionid\", (string) The transaction id.\n" - " \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n" - " \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n" - " \"bip125-replaceable\": \"yes|no|unknown\", (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n" - " may be unknown for unconfirmed transactions not in the mempool\n" - " \"details\" : [\n" - " {\n" - " \"address\" : \"address\", (string) The bitcoin address involved in the transaction\n" - " \"category\" : (string) The transaction category.\n" - " \"send\" Transactions sent.\n" - " \"receive\" Non-coinbase transactions received.\n" - " \"generate\" Coinbase transactions received with more than 100 confirmations.\n" - " \"immature\" Coinbase transactions received with 100 or fewer confirmations.\n" - " \"orphan\" Orphaned coinbase transactions received.\n" - " \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + "\n" - " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n" - " \"vout\" : n, (numeric) the vout value\n" - " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n" + + TransactionDescriptionString() + + " \"details\" : [\n" + " {\n" + " \"involvesWatchonly\": xxx, (bool) Only returns true if imported addresses were involved in transaction.\n" + " \"address\" : \"address\", (string) The bitcoin address involved in the transaction\n" + " \"category\" : (string) The transaction category.\n" + " \"send\" Transactions sent.\n" + " \"receive\" Non-coinbase transactions received.\n" + " \"generate\" Coinbase transactions received with more than 100 confirmations.\n" + " \"immature\" Coinbase transactions received with 100 or fewer confirmations.\n" + " \"orphan\" Orphaned coinbase transactions received.\n" + " \"amount\" : x.xxx, (numeric) The amount in " + CURRENCY_UNIT + "\n" + " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n" + " \"vout\" : n, (numeric) the vout value\n" + " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n" " 'send' category of transactions.\n" - " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n" + " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n" " 'send' category of transactions.\n" - " }\n" - " ,...\n" - " ],\n" - " \"hex\" : \"data\" (string) Raw data for transaction\n" - " \"decoded\" : transaction (json object) Optional, the decoded transaction (only present when `verbose` is passed), equivalent to the\n" - " RPC decoderawtransaction method, or the RPC getrawtransaction method when `verbose` is passed.\n" + " }\n" + " ,...\n" + " ],\n" + " \"hex\" : \"data\" (string) Raw data for transaction\n" + " \"decoded\" : transaction (json object) Optional, the decoded transaction (only present when `verbose` is passed), equivalent to the\n" + " RPC decoderawtransaction method, or the RPC getrawtransaction method when `verbose` is passed.\n" "}\n" }, RPCExamples{ @@ -2327,7 +2323,7 @@ static UniValue settxfee(const JSONRPCRequest& request) CAmount nAmount = AmountFromValue(request.params[0]); CFeeRate tx_fee_rate(nAmount, 1000); - if (tx_fee_rate == 0) { + if (tx_fee_rate == CFeeRate(0)) { // automatic selection } else if (tx_fee_rate < pwallet->chain().relayMinFee()) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("txfee cannot be less than min relay tx fee (%s)", pwallet->chain().relayMinFee().ToString())); @@ -3386,7 +3382,7 @@ static UniValue bumpfee(const JSONRPCRequest& request) } } else if (options.exists("fee_rate")) { CFeeRate fee_rate(AmountFromValue(options["fee_rate"])); - if (fee_rate <= 0) { + if (fee_rate <= CFeeRate(0)) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid fee_rate %s (must be greater than 0)", fee_rate.ToString())); } coin_control.m_feerate = fee_rate; diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index fc3be2b6ab..73523ca36d 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -338,6 +338,84 @@ BOOST_AUTO_TEST_CASE(LoadReceiveRequests) BOOST_CHECK_EQUAL(values[1], "val_rr1"); } +// Test some watch-only wallet methods by the procedure of loading (LoadWatchOnly), +// checking (HaveWatchOnly), getting (GetWatchPubKey) and removing (RemoveWatchOnly) a +// given PubKey, resp. its corresponding P2PK Script. Results of the the impact on +// the address -> PubKey map is dependent on whether the PubKey is a point on the curve +static void TestWatchOnlyPubKey(CWallet& wallet, const CPubKey& add_pubkey) +{ + CScript p2pk = GetScriptForRawPubKey(add_pubkey); + CKeyID add_address = add_pubkey.GetID(); + CPubKey found_pubkey; + LOCK(wallet.cs_wallet); + + // all Scripts (i.e. also all PubKeys) are added to the general watch-only set + BOOST_CHECK(!wallet.HaveWatchOnly(p2pk)); + wallet.LoadWatchOnly(p2pk); + BOOST_CHECK(wallet.HaveWatchOnly(p2pk)); + + // only PubKeys on the curve shall be added to the watch-only address -> PubKey map + bool is_pubkey_fully_valid = add_pubkey.IsFullyValid(); + if (is_pubkey_fully_valid) { + BOOST_CHECK(wallet.GetWatchPubKey(add_address, found_pubkey)); + BOOST_CHECK(found_pubkey == add_pubkey); + } else { + BOOST_CHECK(!wallet.GetWatchPubKey(add_address, found_pubkey)); + BOOST_CHECK(found_pubkey == CPubKey()); // passed key is unchanged + } + + wallet.RemoveWatchOnly(p2pk); + BOOST_CHECK(!wallet.HaveWatchOnly(p2pk)); + + if (is_pubkey_fully_valid) { + BOOST_CHECK(!wallet.GetWatchPubKey(add_address, found_pubkey)); + BOOST_CHECK(found_pubkey == add_pubkey); // passed key is unchanged + } +} + +// Cryptographically invalidate a PubKey whilst keeping length and first byte +static void PollutePubKey(CPubKey& pubkey) +{ + std::vector<unsigned char> pubkey_raw(pubkey.begin(), pubkey.end()); + std::fill(pubkey_raw.begin()+1, pubkey_raw.end(), 0); + pubkey = CPubKey(pubkey_raw); + assert(!pubkey.IsFullyValid()); + assert(pubkey.IsValid()); +} + +// Test watch-only wallet logic for PubKeys +BOOST_AUTO_TEST_CASE(WatchOnlyPubKeys) +{ + CKey key; + CPubKey pubkey; + + BOOST_CHECK(!m_wallet.HaveWatchOnly()); + + // uncompressed valid PubKey + key.MakeNewKey(false); + pubkey = key.GetPubKey(); + assert(!pubkey.IsCompressed()); + TestWatchOnlyPubKey(m_wallet, pubkey); + + // uncompressed cryptographically invalid PubKey + PollutePubKey(pubkey); + TestWatchOnlyPubKey(m_wallet, pubkey); + + // compressed valid PubKey + key.MakeNewKey(true); + pubkey = key.GetPubKey(); + assert(pubkey.IsCompressed()); + TestWatchOnlyPubKey(m_wallet, pubkey); + + // compressed cryptographically invalid PubKey + PollutePubKey(pubkey); + TestWatchOnlyPubKey(m_wallet, pubkey); + + // invalid empty PubKey + pubkey = CPubKey(); + TestWatchOnlyPubKey(m_wallet, pubkey); +} + class ListCoinsTestingSetup : public TestChain100Setup { public: diff --git a/test/functional/combine_logs.py b/test/functional/combine_logs.py index 367d0f6916..a70d9c4ac1 100755 --- a/test/functional/combine_logs.py +++ b/test/functional/combine_logs.py @@ -8,7 +8,6 @@ If no argument is provided, the most recent test directory will be used.""" import argparse from collections import defaultdict, namedtuple -import glob import heapq import itertools import os @@ -78,10 +77,11 @@ def read_logs(tmp_dir): for each of the input log files.""" # Find out what the folder is called that holds the debug.log file - chain = glob.glob("{}/node0/*/debug.log".format(tmp_dir)) - if chain: - chain = chain[0] # pick the first one if more than one chain was found (should never happen) - chain = re.search(r'node0/(.+?)/debug\.log$', chain).group(1) # extract the chain name + glob = pathlib.Path(tmp_dir).glob('node0/**/debug.log') + path = next(glob, None) + if path: + assert next(glob, None) is None # more than one debug.log, should never happen + chain = re.search(r'node0/(.+?)/debug\.log$', path.as_posix()).group(1) # extract the chain name else: chain = 'regtest' # fallback to regtest (should only happen when none exists) diff --git a/test/functional/data/rpc_bip67.json b/test/functional/data/rpc_bip67.json new file mode 100644 index 0000000000..4d6f793d4a --- /dev/null +++ b/test/functional/data/rpc_bip67.json @@ -0,0 +1,58 @@ +[ + { + "keys": [ + "02ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8", + "02fe6f0a5a297eb38c391581c4413e084773ea23954d93f7753db7dc0adc188b2f" + ], + "sorted_keys": [ + "02fe6f0a5a297eb38c391581c4413e084773ea23954d93f7753db7dc0adc188b2f", + "02ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8" + ], + "script": "522102fe6f0a5a297eb38c391581c4413e084773ea23954d93f7753db7dc0adc188b2f2102ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f852ae", + "address": "2N19tNw3Ss4L9QDERtCw7FhXb6jBsYmeXNu" + }, + { + "keys": [ + "02632b12f4ac5b1d1b72b2a3b508c19172de44f6f46bcee50ba33f3f9291e47ed0", + "027735a29bae7780a9755fae7a1c4374c656ac6a69ea9f3697fda61bb99a4f3e77", + "02e2cc6bd5f45edd43bebe7cb9b675f0ce9ed3efe613b177588290ad188d11b404" + ], + "sorted_keys": [ + "02632b12f4ac5b1d1b72b2a3b508c19172de44f6f46bcee50ba33f3f9291e47ed0", + "027735a29bae7780a9755fae7a1c4374c656ac6a69ea9f3697fda61bb99a4f3e77", + "02e2cc6bd5f45edd43bebe7cb9b675f0ce9ed3efe613b177588290ad188d11b404" + ], + "script": "522102632b12f4ac5b1d1b72b2a3b508c19172de44f6f46bcee50ba33f3f9291e47ed021027735a29bae7780a9755fae7a1c4374c656ac6a69ea9f3697fda61bb99a4f3e772102e2cc6bd5f45edd43bebe7cb9b675f0ce9ed3efe613b177588290ad188d11b40453ae", + "address": "2N3sVXU7MZefmYnZhrVX2bA7LyH6vygFZZ7" + }, + { + "keys": [ + "030000000000000000000000000000000000004141414141414141414141414141", + "020000000000000000000000000000000000004141414141414141414141414141", + "020000000000000000000000000000000000004141414141414141414141414140", + "030000000000000000000000000000000000004141414141414141414141414140" + ], + "sorted_keys": [ + "020000000000000000000000000000000000004141414141414141414141414140", + "020000000000000000000000000000000000004141414141414141414141414141", + "030000000000000000000000000000000000004141414141414141414141414140", + "030000000000000000000000000000000000004141414141414141414141414141" + ], + "script": "522102000000000000000000000000000000000000414141414141414141414141414021020000000000000000000000000000000000004141414141414141414141414141210300000000000000000000000000000000000041414141414141414141414141402103000000000000000000000000000000000000414141414141414141414141414154ae", + "address": "2Mt3L9TcDUAfLpSoyB3SNYtJGLiU49DKEWJ" + }, + { + "keys": [ + "022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da", + "03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9", + "021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18" + ], + "sorted_keys": [ + "021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18", + "022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da", + "03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9" + ], + "script": "5221021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc1821022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da2103e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e953ae", + "address": "2NFd5JqpwmQNz3gevZJ3rz9ofuHvqaP9Cye" + } +] diff --git a/test/functional/data/rpc_psbt.json b/test/functional/data/rpc_psbt.json index 57f2608ee9..0f6cd97fd8 100644 --- a/test/functional/data/rpc_psbt.json +++ b/test/functional/data/rpc_psbt.json @@ -18,7 +18,15 @@ "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wCAwABAAAAAAEAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A", "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAgAAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A", "cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAQAWABRi6emC//NN2COWEDFrCQzSo7dHywABACIAIIdrrYMvHRaAFe1BIyqeploYFdnvE8Dvh1n2S1srJ4plIQEAJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A", - "cHNidP8BAHMCAAAAAbiWoY6pOQepFsEGhUPXaulX9rvye2NH+NrdlAHg+WgpAQAAAAD/////AkBLTAAAAAAAF6kUqWwXCcLM5BN2zoNqMNT5qMlIi7+HQEtMAAAAAAAXqRSVF/in2XNxAlN1OSxkyp0z+Wtg2YcAAAAAAAEBIBNssgAAAAAAF6kUamsvautR8hRlMRY6OKNTx03DK96HAQcXFgAUo8u1LWpHprjt/uENAwBpGZD0UH0BCGsCRzBEAiAONfH3DYiw67ZbylrsxCF/XXpVwyWBRgofyRbPslzvwgIgIKCsWw5sHSIPh1icNvcVLZLHWj6NA7Dk+4Os2pOnMbQBIQPGStfYHPtyhpV7zIWtn0Q4GXv5gK1zy/tnJ+cBXu4iiwABABYAFMwmJQEz+HDpBEEabxJ5PogPsqZRAAEAFgAUyCrGc3h3FYCmiIspbv2pSTKZ5jU" + "cHNidP8BAHMCAAAAAbiWoY6pOQepFsEGhUPXaulX9rvye2NH+NrdlAHg+WgpAQAAAAD/////AkBLTAAAAAAAF6kUqWwXCcLM5BN2zoNqMNT5qMlIi7+HQEtMAAAAAAAXqRSVF/in2XNxAlN1OSxkyp0z+Wtg2YcAAAAAAAEBIBNssgAAAAAAF6kUamsvautR8hRlMRY6OKNTx03DK96HAQcXFgAUo8u1LWpHprjt/uENAwBpGZD0UH0BCGsCRzBEAiAONfH3DYiw67ZbylrsxCF/XXpVwyWBRgofyRbPslzvwgIgIKCsWw5sHSIPh1icNvcVLZLHWj6NA7Dk+4Os2pOnMbQBIQPGStfYHPtyhpV7zIWtn0Q4GXv5gK1zy/tnJ+cBXu4iiwABABYAFMwmJQEz+HDpBEEabxJ5PogPsqZRAAEAFgAUyCrGc3h3FYCmiIspbv2pSTKZ5jU", + "cHNidP8BACoCAAAAAAFAQg8AAAAAABepFG6Rty1Vk+fUOR4v9E6R6YXDFkHwhwAAAAAAAQEAAQEBagA=", + "cHNidP8BACoCAAAAAAFAQg8AAAAAABepFG6Rty1Vk+fUOR4v9E6R6YXDFkHwhwAAAAAAAQAAAQABagA=", + "cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQEJ//////////8AAQEJAADK/gAAAAAAAA==", + "cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQMErd7f7gEDBAEAAAAA", + "cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQQAAQQBagA=", + "cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQEJAOH1BQAAAAAAAQUAAQUBUQA=", + "cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQcAAQcBUQA=", + "cHNidP8BADMBAAAAAREREREREREREREREREREREREfrK3hERERERERERERERfwAAAAD/////AAAAAAAAAQEJAOH1BQAAAAAAAQgBAAEIAwEBUQA=" ], "valid" : [ "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAA", diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py index 677362756c..682a00ff4d 100755 --- a/test/functional/feature_bip68_sequence.py +++ b/test/functional/feature_bip68_sequence.py @@ -8,7 +8,6 @@ import time from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment from test_framework.messages import COIN, COutPoint, CTransaction, CTxIn, CTxOut, FromHex, ToHex -from test_framework.script import CScript from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, @@ -17,6 +16,7 @@ from test_framework.util import ( satoshi_round, softfork_active, ) +from test_framework.script_util import DUMMY_P2WPKH_SCRIPT SEQUENCE_LOCKTIME_DISABLE_FLAG = (1<<31) SEQUENCE_LOCKTIME_TYPE_FLAG = (1<<22) # this means use time (0 means height) @@ -29,10 +29,9 @@ NOT_FINAL_ERROR = "non-BIP68-final (code 64)" class BIP68Test(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 - # TODO remove output type argument and fix resulting "tx-size-small" errors self.extra_args = [ - ["-acceptnonstdtxn=1", "-addresstype=p2sh-segwit"], - ["-acceptnonstdtxn=0", "-addresstype=p2sh-segwit"], + ["-acceptnonstdtxn=1"], + ["-acceptnonstdtxn=0"], ] def skip_test_if_missing_module(self): @@ -85,7 +84,7 @@ class BIP68Test(BitcoinTestFramework): # input to mature. sequence_value = SEQUENCE_LOCKTIME_DISABLE_FLAG | 1 tx1.vin = [CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), nSequence=sequence_value)] - tx1.vout = [CTxOut(value, CScript([b'a']))] + tx1.vout = [CTxOut(value, DUMMY_P2WPKH_SCRIPT)] tx1_signed = self.nodes[0].signrawtransactionwithwallet(ToHex(tx1))["hex"] tx1_id = self.nodes[0].sendrawtransaction(tx1_signed) @@ -97,7 +96,7 @@ class BIP68Test(BitcoinTestFramework): tx2.nVersion = 2 sequence_value = sequence_value & 0x7fffffff tx2.vin = [CTxIn(COutPoint(tx1_id, 0), nSequence=sequence_value)] - tx2.vout = [CTxOut(int(value - self.relayfee * COIN), CScript([b'a' * 35]))] + tx2.vout = [CTxOut(int(value - self.relayfee * COIN), DUMMY_P2WPKH_SCRIPT)] tx2.rehash() assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, ToHex(tx2)) @@ -192,7 +191,7 @@ class BIP68Test(BitcoinTestFramework): value += utxos[j]["amount"]*COIN # Overestimate the size of the tx - signatures should be less than 120 bytes, and leave 50 for the output tx_size = len(ToHex(tx))//2 + 120*num_inputs + 50 - tx.vout.append(CTxOut(int(value-self.relayfee*tx_size*COIN/1000), CScript([b'a']))) + tx.vout.append(CTxOut(int(value-self.relayfee*tx_size*COIN/1000), DUMMY_P2WPKH_SCRIPT)) rawtx = self.nodes[0].signrawtransactionwithwallet(ToHex(tx))["hex"] if (using_sequence_locks and not should_pass): @@ -221,7 +220,7 @@ class BIP68Test(BitcoinTestFramework): tx2 = CTransaction() tx2.nVersion = 2 tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)] - tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))] + tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), DUMMY_P2WPKH_SCRIPT)] tx2_raw = self.nodes[0].signrawtransactionwithwallet(ToHex(tx2))["hex"] tx2 = FromHex(tx2, tx2_raw) tx2.rehash() @@ -239,7 +238,7 @@ class BIP68Test(BitcoinTestFramework): tx = CTransaction() tx.nVersion = 2 tx.vin = [CTxIn(COutPoint(orig_tx.sha256, 0), nSequence=sequence_value)] - tx.vout = [CTxOut(int(orig_tx.vout[0].nValue - relayfee * COIN), CScript([b'a' * 35]))] + tx.vout = [CTxOut(int(orig_tx.vout[0].nValue - relayfee * COIN), DUMMY_P2WPKH_SCRIPT)] tx.rehash() if (orig_tx.hash in node.getrawmempool()): @@ -352,7 +351,7 @@ class BIP68Test(BitcoinTestFramework): tx2 = CTransaction() tx2.nVersion = 1 tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)] - tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))] + tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), DUMMY_P2WPKH_SCRIPT)] # sign tx2 tx2_raw = self.nodes[0].signrawtransactionwithwallet(ToHex(tx2))["hex"] @@ -367,7 +366,7 @@ class BIP68Test(BitcoinTestFramework): tx3 = CTransaction() tx3.nVersion = 2 tx3.vin = [CTxIn(COutPoint(tx2.sha256, 0), nSequence=sequence_value)] - tx3.vout = [CTxOut(int(tx2.vout[0].nValue - self.relayfee * COIN), CScript([b'a' * 35]))] + tx3.vout = [CTxOut(int(tx2.vout[0].nValue - self.relayfee * COIN), DUMMY_P2WPKH_SCRIPT)] tx3.rehash() assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, ToHex(tx3)) diff --git a/test/functional/feature_cltv.py b/test/functional/feature_cltv.py index e00219ca4a..13f1c9216a 100755 --- a/test/functional/feature_cltv.py +++ b/test/functional/feature_cltv.py @@ -22,9 +22,6 @@ from io import BytesIO CLTV_HEIGHT = 1351 -# Reject codes that we might receive in this test -REJECT_INVALID = 16 -REJECT_NONSTANDARD = 64 def cltv_invalidate(tx): '''Modify the signature in vin 0 of the tx to fail CLTV diff --git a/test/functional/feature_dersig.py b/test/functional/feature_dersig.py index 1bd9586364..92f6eea5b2 100755 --- a/test/functional/feature_dersig.py +++ b/test/functional/feature_dersig.py @@ -9,19 +9,15 @@ Test that the DERSIG soft-fork activates at (regtest) height 1251. from test_framework.blocktools import create_coinbase, create_block, create_transaction from test_framework.messages import msg_block -from test_framework.mininode import mininode_lock, P2PInterface +from test_framework.mininode import P2PInterface from test_framework.script import CScript from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, - wait_until, ) DERSIG_HEIGHT = 1251 -# Reject codes that we might receive in this test -REJECT_INVALID = 16 -REJECT_NONSTANDARD = 64 # A canonical signature consists of: # <30> <total len> <02> <len R> <R> <02> <len S> <S> <hashtype> @@ -44,7 +40,7 @@ def unDERify(tx): class BIP66Test(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 - self.extra_args = [['-whitelist=127.0.0.1', '-par=1', '-enablebip61']] # Use only one script thread to get the exact reject reason for testing + self.extra_args = [['-whitelist=127.0.0.1', '-par=1']] # Use only one script thread to get the exact log msg for testing self.setup_clean_chain = True self.rpc_timeout = 120 @@ -129,12 +125,6 @@ class BIP66Test(BitcoinTestFramework): assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip) self.nodes[0].p2p.sync_with_ping() - wait_until(lambda: "reject" in self.nodes[0].p2p.last_message.keys(), lock=mininode_lock) - with mininode_lock: - assert self.nodes[0].p2p.last_message["reject"].code in [REJECT_INVALID, REJECT_NONSTANDARD] - assert_equal(self.nodes[0].p2p.last_message["reject"].data, block.sha256) - assert b'Non-canonical DER signature' in self.nodes[0].p2p.last_message["reject"].reason - self.log.info("Test that a version 3 block with a DERSIG-compliant transaction is accepted") block.vtx[1] = create_transaction(self.nodes[0], self.coinbase_txids[1], self.nodeaddress, amount=1.0) block.hashMerkleRoot = block.calc_merkle_root() diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py index a1d4ce4c73..e7afbd0272 100755 --- a/test/functional/feature_rbf.py +++ b/test/functional/feature_rbf.py @@ -10,13 +10,14 @@ from test_framework.messages import COIN, COutPoint, CTransaction, CTxIn, CTxOut from test_framework.script import CScript, OP_DROP from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, assert_raises_rpc_error, satoshi_round +from test_framework.script_util import DUMMY_P2WPKH_SCRIPT MAX_REPLACEMENT_LIMIT = 100 def txToHex(tx): return tx.serialize().hex() -def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])): +def make_utxo(node, amount, confirmed=True, scriptPubKey=DUMMY_P2WPKH_SCRIPT): """Create a txout with a given amount and scriptPubKey Mines coins as needed. @@ -65,7 +66,6 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])): class ReplaceByFeeTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 - # TODO remove output type argument and fix resulting "tx-size-small" errors self.extra_args = [ [ "-acceptnonstdtxn=1", @@ -74,7 +74,6 @@ class ReplaceByFeeTest(BitcoinTestFramework): "-limitancestorsize=101", "-limitdescendantcount=200", "-limitdescendantsize=101", - "-addresstype=p2sh-segwit", ], ] @@ -133,7 +132,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx1a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx1a_hex = txToHex(tx1a) tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0) @@ -142,7 +141,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Should fail because we haven't changed the fee tx1b = CTransaction() tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1b.vout = [CTxOut(1 * COIN, CScript([b'b' * 35]))] + tx1b.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT + b'a')] tx1b_hex = txToHex(tx1b) # This will raise an exception due to insufficient fee @@ -151,7 +150,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Extra 0.1 BTC fee tx1b = CTransaction() tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1b.vout = [CTxOut(int(0.9 * COIN), CScript([b'b' * 35]))] + tx1b.vout = [CTxOut(int(0.9 * COIN), DUMMY_P2WPKH_SCRIPT)] tx1b_hex = txToHex(tx1b) # Works when enabled tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, 0) @@ -186,7 +185,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # child fees - 40 BTC - so this attempt is rejected. dbl_tx = CTransaction() dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)] - dbl_tx.vout = [CTxOut(initial_nValue - 30 * COIN, CScript([1] * 35))] + dbl_tx.vout = [CTxOut(initial_nValue - 30 * COIN, DUMMY_P2WPKH_SCRIPT)] dbl_tx_hex = txToHex(dbl_tx) # This will raise an exception due to insufficient fee @@ -195,7 +194,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Accepted with sufficient fee dbl_tx = CTransaction() dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)] - dbl_tx.vout = [CTxOut(1 * COIN, CScript([1] * 35))] + dbl_tx.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] dbl_tx_hex = txToHex(dbl_tx) self.nodes[0].sendrawtransaction(dbl_tx_hex, 0) @@ -248,7 +247,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Attempt double-spend, will fail because too little fee paid dbl_tx = CTransaction() dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)] - dbl_tx.vout = [CTxOut(initial_nValue - fee * n, CScript([1] * 35))] + dbl_tx.vout = [CTxOut(initial_nValue - fee * n, DUMMY_P2WPKH_SCRIPT)] dbl_tx_hex = txToHex(dbl_tx) # This will raise an exception due to insufficient fee assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, 0) @@ -256,7 +255,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # 1 BTC fee is enough dbl_tx = CTransaction() dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)] - dbl_tx.vout = [CTxOut(initial_nValue - fee * n - 1 * COIN, CScript([1] * 35))] + dbl_tx.vout = [CTxOut(initial_nValue - fee * n - 1 * COIN, DUMMY_P2WPKH_SCRIPT)] dbl_tx_hex = txToHex(dbl_tx) self.nodes[0].sendrawtransaction(dbl_tx_hex, 0) @@ -276,7 +275,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): dbl_tx = CTransaction() dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)] - dbl_tx.vout = [CTxOut(initial_nValue - 2 * fee * n, CScript([1] * 35))] + dbl_tx.vout = [CTxOut(initial_nValue - 2 * fee * n, DUMMY_P2WPKH_SCRIPT)] dbl_tx_hex = txToHex(dbl_tx) # This will raise an exception assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, dbl_tx_hex, 0) @@ -291,7 +290,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx1a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx1a_hex = txToHex(tx1a) self.nodes[0].sendrawtransaction(tx1a_hex, 0) @@ -312,7 +311,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx1a = CTransaction() tx1a.vin = [CTxIn(utxo1, nSequence=0)] - tx1a.vout = [CTxOut(int(1.1 * COIN), CScript([b'a' * 35]))] + tx1a.vout = [CTxOut(int(1.1 * COIN), DUMMY_P2WPKH_SCRIPT)] tx1a_hex = txToHex(tx1a) tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0) @@ -331,7 +330,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Spend tx1a's output to test the indirect case. tx1b = CTransaction() tx1b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)] - tx1b.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx1b.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx1b_hex = txToHex(tx1b) tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, 0) tx1b_txid = int(tx1b_txid, 16) @@ -352,7 +351,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx1 = CTransaction() tx1.vin = [CTxIn(confirmed_utxo)] - tx1.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx1.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx1_hex = txToHex(tx1) self.nodes[0].sendrawtransaction(tx1_hex, 0) @@ -391,7 +390,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): for i in range(MAX_REPLACEMENT_LIMIT+1): tx_i = CTransaction() tx_i.vin = [CTxIn(COutPoint(txid, i), nSequence=0)] - tx_i.vout = [CTxOut(split_value - fee, CScript([b'a' * 35]))] + tx_i.vout = [CTxOut(split_value - fee, DUMMY_P2WPKH_SCRIPT)] tx_i_hex = txToHex(tx_i) self.nodes[0].sendrawtransaction(tx_i_hex, 0) @@ -424,7 +423,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Create a non-opting in transaction tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0xffffffff)] - tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx1a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx1a_hex = txToHex(tx1a) tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0) @@ -434,7 +433,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Shouldn't be able to double-spend tx1b = CTransaction() tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1b.vout = [CTxOut(int(0.9 * COIN), CScript([b'b' * 35]))] + tx1b.vout = [CTxOut(int(0.9 * COIN), DUMMY_P2WPKH_SCRIPT)] tx1b_hex = txToHex(tx1b) # This will raise an exception @@ -445,14 +444,14 @@ class ReplaceByFeeTest(BitcoinTestFramework): # Create a different non-opting in transaction tx2a = CTransaction() tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0xfffffffe)] - tx2a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx2a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx2a_hex = txToHex(tx2a) tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, 0) # Still shouldn't be able to double-spend tx2b = CTransaction() tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)] - tx2b.vout = [CTxOut(int(0.9 * COIN), CScript([b'b' * 35]))] + tx2b.vout = [CTxOut(int(0.9 * COIN), DUMMY_P2WPKH_SCRIPT)] tx2b_hex = txToHex(tx2b) # This will raise an exception @@ -478,12 +477,12 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx3b = CTransaction() tx3b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)] - tx3b.vout = [CTxOut(int(0.5 * COIN), CScript([b'e' * 35]))] + tx3b.vout = [CTxOut(int(0.5 * COIN), DUMMY_P2WPKH_SCRIPT)] tx3b_hex = txToHex(tx3b) tx3c = CTransaction() tx3c.vin = [CTxIn(COutPoint(tx2a_txid, 0), nSequence=0)] - tx3c.vout = [CTxOut(int(0.5 * COIN), CScript([b'f' * 35]))] + tx3c.vout = [CTxOut(int(0.5 * COIN), DUMMY_P2WPKH_SCRIPT)] tx3c_hex = txToHex(tx3c) self.nodes[0].sendrawtransaction(tx3b_hex, 0) @@ -500,7 +499,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx1a = CTransaction() tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)] - tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx1a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx1a_hex = txToHex(tx1a) tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, 0) @@ -526,14 +525,14 @@ class ReplaceByFeeTest(BitcoinTestFramework): tx2a = CTransaction() tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)] - tx2a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))] + tx2a.vout = [CTxOut(1 * COIN, DUMMY_P2WPKH_SCRIPT)] tx2a_hex = txToHex(tx2a) self.nodes[0].sendrawtransaction(tx2a_hex, 0) # Lower fee, but we'll prioritise it tx2b = CTransaction() tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)] - tx2b.vout = [CTxOut(int(1.01 * COIN), CScript([b'a' * 35]))] + tx2b.vout = [CTxOut(int(1.01 * COIN), DUMMY_P2WPKH_SCRIPT)] tx2b.rehash() tx2b_hex = txToHex(tx2b) diff --git a/test/functional/p2p_feefilter.py b/test/functional/p2p_feefilter.py index 7f901b1886..4f242bd94a 100755 --- a/test/functional/p2p_feefilter.py +++ b/test/functional/p2p_feefilter.py @@ -41,6 +41,12 @@ class TestP2PConn(P2PInterface): class FeeFilterTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 + # We lower the various required feerates for this test + # to catch a corner-case where feefilter used to slightly undercut + # mempool and wallet feerate calculation based on GetFee + # rounding down 3 places, leading to stranded transactions. + # See issue #16499 + self.extra_args = [["-minrelaytxfee=0.00000100", "-mintxfee=0.00000100"]]*self.num_nodes def skip_test_if_missing_module(self): self.skip_if_no_wallet() @@ -54,22 +60,25 @@ class FeeFilterTest(BitcoinTestFramework): self.nodes[0].add_p2p_connection(TestP2PConn()) - # Test that invs are received for all txs at feerate of 20 sat/byte - node1.settxfee(Decimal("0.00020000")) + # Test that invs are received by test connection for all txs at + # feerate of .2 sat/byte + node1.settxfee(Decimal("0.00000200")) txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)] assert allInvsMatch(txids, self.nodes[0].p2p) self.nodes[0].p2p.clear_invs() - # Set a filter of 15 sat/byte - self.nodes[0].p2p.send_and_ping(msg_feefilter(15000)) + # Set a filter of .15 sat/byte on test connection + self.nodes[0].p2p.send_and_ping(msg_feefilter(150)) - # Test that txs are still being received (paying 20 sat/byte) + # Test that txs are still being received by test connection (paying .15 sat/byte) + node1.settxfee(Decimal("0.00000150")) txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)] assert allInvsMatch(txids, self.nodes[0].p2p) self.nodes[0].p2p.clear_invs() - # Change tx fee rate to 10 sat/byte and test they are no longer received - node1.settxfee(Decimal("0.00010000")) + # Change tx fee rate to .1 sat/byte and test they are no longer received + # by the test connection + node1.settxfee(Decimal("0.00000100")) [node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)] self.sync_mempools() # must be sure node 0 has received all txs diff --git a/test/functional/rpc_createmultisig.py b/test/functional/rpc_createmultisig.py index 056e193d55..2a64a29967 100755 --- a/test/functional/rpc_createmultisig.py +++ b/test/functional/rpc_createmultisig.py @@ -4,6 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test multisig RPCs""" +from test_framework.descriptors import descsum_create from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_raises_rpc_error, @@ -14,6 +15,8 @@ from test_framework.key import ECPubKey import binascii import decimal import itertools +import json +import os class RpcCreateMultiSigTest(BitcoinTestFramework): def set_test_params(self): @@ -72,6 +75,18 @@ class RpcCreateMultiSigTest(BitcoinTestFramework): assert_equal(legacy_addr, node0.addmultisigaddress(2, keys, '', 'bech32')['address']) assert_equal(legacy_addr, node0.addmultisigaddress(2, keys, '', 'p2sh-segwit')['address']) + self.log.info('Testing sortedmulti descriptors with BIP 67 test vectors') + with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data/rpc_bip67.json'), encoding='utf-8') as f: + vectors = json.load(f) + + for t in vectors: + key_str = ','.join(t['keys']) + desc = descsum_create('sh(sortedmulti(2,{}))'.format(key_str)) + assert_equal(self.nodes[0].deriveaddresses(desc)[0], t['address']) + sorted_key_str = ','.join(t['sorted_keys']) + sorted_key_desc = descsum_create('sh(multi(2,{}))'.format(sorted_key_str)) + assert_equal(self.nodes[0].deriveaddresses(sorted_key_desc)[0], t['address']) + def check_addmultisigaddress_errors(self): self.log.info('Check that addmultisigaddress fails when the private keys are missing') addresses = [self.nodes[1].getnewaddress(address_type='legacy') for _ in range(2)] diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py index 3cb5f56bee..25520a2151 100755 --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -1317,38 +1317,6 @@ class msg_headers: return "msg_headers(headers=%s)" % repr(self.headers) -class msg_reject: - __slots__ = ("code", "data", "message", "reason") - command = b"reject" - REJECT_MALFORMED = 1 - - def __init__(self): - self.message = b"" - self.code = 0 - self.reason = b"" - self.data = 0 - - def deserialize(self, f): - self.message = deser_string(f) - self.code = struct.unpack("<B", f.read(1))[0] - self.reason = deser_string(f) - if (self.code != self.REJECT_MALFORMED and - (self.message == b"block" or self.message == b"tx")): - self.data = deser_uint256(f) - - def serialize(self): - r = ser_string(self.message) - r += struct.pack("<B", self.code) - r += ser_string(self.reason) - if (self.code != self.REJECT_MALFORMED and - (self.message == b"block" or self.message == b"tx")): - r += ser_uint256(self.data) - return r - - def __repr__(self): - return "msg_reject: %s %d %s [%064x]" \ - % (self.message, self.code, self.reason, self.data) - class msg_feefilter: __slots__ = ("feerate",) diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py index 166438cf70..f95c158a68 100755 --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -41,7 +41,6 @@ from test_framework.messages import ( msg_notfound, msg_ping, msg_pong, - msg_reject, msg_sendcmpct, msg_sendheaders, msg_tx, @@ -74,7 +73,6 @@ MESSAGEMAP = { b"notfound": msg_notfound, b"ping": msg_ping, b"pong": msg_pong, - b"reject": msg_reject, b"sendcmpct": msg_sendcmpct, b"sendheaders": msg_sendheaders, b"tx": msg_tx, diff --git a/test/functional/test_framework/script_util.py b/test/functional/test_framework/script_util.py new file mode 100755 index 0000000000..5ef67226c4 --- /dev/null +++ b/test/functional/test_framework/script_util.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# Copyright (c) 2019 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Useful Script constants and utils.""" +from test_framework.script import CScript + +# To prevent a "tx-size-small" policy rule error, a transaction has to have a +# non-witness size of at least 82 bytes (MIN_STANDARD_TX_NONWITNESS_SIZE in +# src/policy/policy.h). Considering a Tx with the smallest possible single +# input (blank, empty scriptSig), and with an output omitting the scriptPubKey, +# we get to a minimum size of 60 bytes: +# +# Tx Skeleton: 4 [Version] + 1 [InCount] + 1 [OutCount] + 4 [LockTime] = 10 bytes +# Blank Input: 32 [PrevTxHash] + 4 [Index] + 1 [scriptSigLen] + 4 [SeqNo] = 41 bytes +# Output: 8 [Amount] + 1 [scriptPubKeyLen] = 9 bytes +# +# Hence, the scriptPubKey of the single output has to have a size of at +# least 22 bytes, which corresponds to the size of a P2WPKH scriptPubKey. +# The following script constant consists of a single push of 21 bytes of 'a': +# <PUSH_21> <21-bytes of 'a'> +# resulting in a 22-byte size. It should be used whenever (small) fake +# scriptPubKeys are needed, to guarantee that the minimum transaction size is +# met. +DUMMY_P2WPKH_SCRIPT = CScript([b'a' * 21]) diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 2bed8c3231..cde99a2219 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -244,7 +244,7 @@ class PortSeed: # Must be initialized with a unique integer for each process n = None -def get_rpc_proxy(url, node_number, timeout=None, coveragedir=None): +def get_rpc_proxy(url, node_number, *, timeout=None, coveragedir=None): """ Args: url (str): URL of the RPC server to call @@ -252,6 +252,7 @@ def get_rpc_proxy(url, node_number, timeout=None, coveragedir=None): Kwargs: timeout (int): HTTP timeout in seconds + coveragedir (str): Directory Returns: AuthServiceProxy. convenience object for making RPC calls. diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py index b72f5c6008..479d67fb66 100755 --- a/test/functional/wallet_address_types.py +++ b/test/functional/wallet_address_types.py @@ -80,6 +80,9 @@ class AddressTypeTest(BitcoinTestFramework): ["-changetype=p2sh-segwit"], [], ] + # whitelist all peers to speed up tx relay / mempool sync + for args in self.extra_args: + args.append("-whitelist=127.0.0.1") def skip_test_if_missing_module(self): self.skip_if_no_wallet() diff --git a/test/functional/wallet_backup.py b/test/functional/wallet_backup.py index 93178c5ab2..bb835dc811 100755 --- a/test/functional/wallet_backup.py +++ b/test/functional/wallet_backup.py @@ -48,7 +48,13 @@ class WalletBackupTest(BitcoinTestFramework): self.num_nodes = 4 self.setup_clean_chain = True # nodes 1, 2,3 are spenders, let's give them a keypool=100 - self.extra_args = [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []] + # whitelist all peers to speed up tx relay / mempool sync + self.extra_args = [ + ["-keypool=100", "-whitelist=127.0.0.1"], + ["-keypool=100", "-whitelist=127.0.0.1"], + ["-keypool=100", "-whitelist=127.0.0.1"], + ["-whitelist=127.0.0.1"] + ] self.rpc_timeout = 120 def skip_test_if_missing_module(self): diff --git a/test/lint/lint-filenames.sh b/test/lint/lint-filenames.sh index 5391e43d91..6716cac0fe 100755 --- a/test/lint/lint-filenames.sh +++ b/test/lint/lint-filenames.sh @@ -12,7 +12,7 @@ export LC_ALL=C EXIT_CODE=0 OUTPUT=$(git ls-files --full-name -- "*.[cC][pP][pP]" "*.[hH]" "*.[pP][yY]" "*.[sS][hH]" | \ grep -vE '^[a-z0-9_./-]+$' | \ - grep -vE '^src/(secp256k1|univalue)/') + grep -vE '^src/(secp256k1/|univalue/|test/fuzz/FuzzedDataProvider.h)') if [[ ${OUTPUT} != "" ]]; then echo "Use only lowercase alphanumerics (a-z0-9), underscores (_), hyphens (-) and dots (.)" diff --git a/test/lint/lint-include-guards.sh b/test/lint/lint-include-guards.sh index 464969794b..0d654e796e 100755 --- a/test/lint/lint-include-guards.sh +++ b/test/lint/lint-include-guards.sh @@ -10,7 +10,7 @@ export LC_ALL=C HEADER_ID_PREFIX="BITCOIN_" HEADER_ID_SUFFIX="_H" -REGEXP_EXCLUDE_FILES_WITH_PREFIX="src/(crypto/ctaes/|leveldb/|secp256k1/|tinyformat.h|univalue/)" +REGEXP_EXCLUDE_FILES_WITH_PREFIX="src/(crypto/ctaes/|leveldb/|secp256k1/|test/fuzz/FuzzedDataProvider.h|tinyformat.h|univalue/)" EXIT_CODE=0 for HEADER_FILE in $(git ls-files -- "*.h" | grep -vE "^${REGEXP_EXCLUDE_FILES_WITH_PREFIX}") |