diff options
42 files changed, 637 insertions, 383 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 1e6e6937da..9464ec1685 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -9,6 +9,7 @@ task: MAKEJOBS: "-j9" CONFIGURE_OPTS: "--disable-dependency-tracking" GOAL: "install" + TEST_RUNNER_PORT_MIN: "14000" # Must be larger than 12321, which is used for the http cache. See https://cirrus-ci.org/guide/writing-tasks/#http-cache CCACHE_SIZE: "200M" CCACHE_COMPRESS: 1 CCACHE_DIR: "/tmp/ccache_dir" @@ -37,6 +38,7 @@ task: env: MAKEJOBS: "-j9" RUN_CI_ON_HOST: "1" + TEST_RUNNER_PORT_MIN: "14000" # Must be larger than 12321, which is used for the http cache. See https://cirrus-ci.org/guide/writing-tasks/#http-cache CCACHE_SIZE: "200M" CCACHE_DIR: "/tmp/ccache_dir" ccache_cache: diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 00d5478c4e..d2c3b23375 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,9 +1,14 @@ +<!-- +*** Please remove the following help text before submitting: *** + Pull requests without a rationale and clear improvement may be closed immediately. +--> +<!-- Please provide clear motivation for your patch and explain how it improves Bitcoin Core user experience or Bitcoin Core developer experience -significantly. +significantly: * Any test improvements or new tests that improve coverage are always welcome. * All other changes should have accompanying unit tests (see `src/test/`) or @@ -24,8 +29,11 @@ significantly. is often a subjective matter. Unless they are explicitly mentioned to be preferred in the [developer notes](/doc/developer-notes.md), stylistic code changes are usually rejected. +--> +<!-- Bitcoin Core has a thorough review process and even the most trivial change needs to pass a lot of eyes and requires non-zero or even substantial time effort to review. There is a huge lack of active reviewers on the project, so patches often sit for a long time. +--> diff --git a/.travis.yml b/.travis.yml index ec08ab2efb..e93f6ca0dc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -117,6 +117,7 @@ jobs: name: 'x86_64 Linux [GOAL: install] [xenial] [no depends, only system libs, sanitizers: thread (TSan), no wallet]' env: >- FILE_ENV="./ci/test/00_setup_env_amd64_tsan.sh" + TEST_RUNNER_EXTRA="--exclude feature_block" # Not enough memory on travis machines - stage: test name: 'x86_64 Linux [GOAL: install] [bionic] [no depends, only system libs, sanitizers: address/leak (ASan + LSan) + undefined (UBSan) + integer]' diff --git a/build-aux/m4/ax_boost_base.m4 b/build-aux/m4/ax_boost_base.m4 index d540395763..16fa69b41f 100644 --- a/build-aux/m4/ax_boost_base.m4 +++ b/build-aux/m4/ax_boost_base.m4 @@ -33,7 +33,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 45 +#serial 47 # example boost program (need to pass version) m4_define([_AX_BOOST_BASE_PROGRAM], @@ -113,6 +113,7 @@ AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[ dnl are found, e.g. when only header-only libraries are installed! AS_CASE([${host_cpu}], [x86_64],[libsubdirs="lib64 libx32 lib lib64"], + [mips*64*],[libsubdirs="lib64 lib32 lib lib64"], [ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64],[libsubdirs="lib64 lib lib64"], [libsubdirs="lib"] ) diff --git a/build-aux/m4/ax_boost_chrono.m4 b/build-aux/m4/ax_boost_chrono.m4 index 6ea77b9b3e..4cd3b86041 100644 --- a/build-aux/m4/ax_boost_chrono.m4 +++ b/build-aux/m4/ax_boost_chrono.m4 @@ -29,7 +29,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 4 +#serial 5 AC_DEFUN([AX_BOOST_CHRONO], [ @@ -105,7 +105,7 @@ AC_DEFUN([AX_BOOST_CHRONO], fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the library!) + AC_MSG_ERROR(Could not find a version of the Boost::Chrono library!) fi if test "x$link_chrono" = "xno"; then AC_MSG_ERROR(Could not link against $ax_lib !) diff --git a/build-aux/m4/ax_boost_filesystem.m4 b/build-aux/m4/ax_boost_filesystem.m4 index f5c9d56470..12f7bc5e2e 100644 --- a/build-aux/m4/ax_boost_filesystem.m4 +++ b/build-aux/m4/ax_boost_filesystem.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_filesystem.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_filesystem.html # =========================================================================== # # SYNOPSIS @@ -31,7 +31,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 26 +#serial 28 AC_DEFUN([AX_BOOST_FILESYSTEM], [ @@ -80,7 +80,6 @@ AC_DEFUN([AX_BOOST_FILESYSTEM], if test "x$ax_cv_boost_filesystem" = "xyes"; then AC_DEFINE(HAVE_BOOST_FILESYSTEM,,[define if the Boost::Filesystem library is available]) BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` - ax_lib= if test "x$ax_boost_user_filesystem_lib" = "x"; then for libextension in `ls -r $BOOSTLIBDIR/libboost_filesystem* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do ax_lib=${libextension} @@ -105,7 +104,7 @@ AC_DEFUN([AX_BOOST_FILESYSTEM], fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the boost_filesystem library!) + AC_MSG_ERROR(Could not find a version of the Boost::Filesystem library!) fi if test "x$link_filesystem" != "xyes"; then AC_MSG_ERROR(Could not link against $ax_lib !) diff --git a/build-aux/m4/ax_boost_system.m4 b/build-aux/m4/ax_boost_system.m4 index 207d7be8de..323e2a676a 100644 --- a/build-aux/m4/ax_boost_system.m4 +++ b/build-aux/m4/ax_boost_system.m4 @@ -31,7 +31,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 19 +#serial 20 AC_DEFUN([AX_BOOST_SYSTEM], [ @@ -108,7 +108,7 @@ AC_DEFUN([AX_BOOST_SYSTEM], fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the library!) + AC_MSG_ERROR(Could not find a version of the Boost::System library!) fi if test "x$link_system" = "xno"; then AC_MSG_ERROR(Could not link against $ax_lib !) diff --git a/build-aux/m4/ax_boost_thread.m4 b/build-aux/m4/ax_boost_thread.m4 index 9f0bd0b23c..e9dea43535 100644 --- a/build-aux/m4/ax_boost_thread.m4 +++ b/build-aux/m4/ax_boost_thread.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_thread.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_thread.html # =========================================================================== # # SYNOPSIS @@ -30,73 +30,75 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 27 +#serial 32 AC_DEFUN([AX_BOOST_THREAD], [ - AC_ARG_WITH([boost-thread], - AS_HELP_STRING([--with-boost-thread@<:@=special-lib@:>@], - [use the Thread library from boost - it is possible to specify a certain library for the linker - e.g. --with-boost-thread=boost_thread-gcc-mt ]), + AC_ARG_WITH([boost-thread], + AS_HELP_STRING([--with-boost-thread@<:@=special-lib@:>@], + [use the Thread library from boost - + it is possible to specify a certain library for the linker + e.g. --with-boost-thread=boost_thread-gcc-mt ]), [ - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then + if test "$withval" = "yes"; then want_boost="yes" ax_boost_user_thread_lib="" else - want_boost="yes" - ax_boost_user_thread_lib="$withval" - fi + want_boost="yes" + ax_boost_user_thread_lib="$withval" + fi ], [want_boost="yes"] - ) + ) - if test "x$want_boost" = "xyes"; then + if test "x$want_boost" = "xyes"; then AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_CANONICAL_BUILD]) - CPPFLAGS_SAVED="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS + CPPFLAGS_SAVED="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" + export CPPFLAGS - LDFLAGS_SAVED="$LDFLAGS" - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS + LDFLAGS_SAVED="$LDFLAGS" + LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" + export LDFLAGS AC_CACHE_CHECK(whether the Boost::Thread library is available, - ax_cv_boost_thread, + ax_cv_boost_thread, [AC_LANG_PUSH([C++]) - CXXFLAGS_SAVE=$CXXFLAGS + CXXFLAGS_SAVE=$CXXFLAGS - if test "x$host_os" = "xsolaris" ; then - CXXFLAGS="-pthreads $CXXFLAGS" - elif test "x$host_os" = "xmingw32" ; then - CXXFLAGS="-mthreads $CXXFLAGS" - else - CXXFLAGS="-pthread $CXXFLAGS" - fi - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/thread/thread.hpp>]], - [[boost::thread_group thrds; - return 0;]])], - ax_cv_boost_thread=yes, ax_cv_boost_thread=no) - CXXFLAGS=$CXXFLAGS_SAVE + if test "x$host_os" = "xsolaris" ; then + CXXFLAGS="-pthreads $CXXFLAGS" + elif test "x$host_os" = "xmingw32" ; then + CXXFLAGS="-mthreads $CXXFLAGS" + else + CXXFLAGS="-pthread $CXXFLAGS" + fi + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM( + [[@%:@include <boost/thread/thread.hpp>]], + [[boost::thread_group thrds; + return 0;]])], + ax_cv_boost_thread=yes, ax_cv_boost_thread=no) + CXXFLAGS=$CXXFLAGS_SAVE AC_LANG_POP([C++]) - ]) - if test "x$ax_cv_boost_thread" = "xyes"; then + ]) + if test "x$ax_cv_boost_thread" = "xyes"; then if test "x$host_os" = "xsolaris" ; then - BOOST_CPPFLAGS="-pthreads $BOOST_CPPFLAGS" - elif test "x$host_os" = "xmingw32" ; then - BOOST_CPPFLAGS="-mthreads $BOOST_CPPFLAGS" - else - BOOST_CPPFLAGS="-pthread $BOOST_CPPFLAGS" - fi + BOOST_CPPFLAGS="-pthreads $BOOST_CPPFLAGS" + elif test "x$host_os" = "xmingw32" ; then + BOOST_CPPFLAGS="-mthreads $BOOST_CPPFLAGS" + else + BOOST_CPPFLAGS="-pthread $BOOST_CPPFLAGS" + fi - AC_SUBST(BOOST_CPPFLAGS) + AC_SUBST(BOOST_CPPFLAGS) - AC_DEFINE(HAVE_BOOST_THREAD,,[define if the Boost::Thread library is available]) + AC_DEFINE(HAVE_BOOST_THREAD,, + [define if the Boost::Thread library is available]) BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` - LDFLAGS_SAVE=$LDFLAGS + LDFLAGS_SAVE=$LDFLAGS case "x$host_os" in *bsd* ) LDFLAGS="-pthread $LDFLAGS" @@ -104,47 +106,58 @@ AC_DEFUN([AX_BOOST_THREAD], ;; esac if test "x$ax_boost_user_thread_lib" = "x"; then - ax_lib= for libextension in `ls -r $BOOSTLIBDIR/libboost_thread* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'`; do ax_lib=${libextension} - AC_CHECK_LIB($ax_lib, exit, - [BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break], + AC_CHECK_LIB($ax_lib, exit, + [link_thread="yes"; break], [link_thread="no"]) - done + done if test "x$link_thread" != "xyes"; then for libextension in `ls -r $BOOSTLIBDIR/boost_thread* 2>/dev/null | sed 's,.*/,,' | sed 's,\..*,,'`; do ax_lib=${libextension} - AC_CHECK_LIB($ax_lib, exit, - [BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break], + AC_CHECK_LIB($ax_lib, exit, + [link_thread="yes"; break], [link_thread="no"]) - done + done fi else for ax_lib in $ax_boost_user_thread_lib boost_thread-$ax_boost_user_thread_lib; do - AC_CHECK_LIB($ax_lib, exit, - [BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break], + AC_CHECK_LIB($ax_lib, exit, + [link_thread="yes"; break], [link_thread="no"]) done fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the boost_thread library!) + AC_MSG_ERROR(Could not find a version of the Boost::Thread library!) fi - if test "x$link_thread" = "xno"; then - AC_MSG_ERROR(Could not link against $ax_lib !) - else - case "x$host_os" in - *bsd* ) - BOOST_LDFLAGS="-pthread $BOOST_LDFLAGS" - break; - ;; - esac - - fi - fi + if test "x$link_thread" = "xno"; then + AC_MSG_ERROR(Could not link against $ax_lib !) + else + BOOST_THREAD_LIB="-l$ax_lib" + case "x$host_os" in + *bsd* ) + BOOST_LDFLAGS="-pthread $BOOST_LDFLAGS" + break; + ;; + xsolaris ) + BOOST_THREAD_LIB="$BOOST_THREAD_LIB -lpthread" + break; + ;; + xmingw32 ) + break; + ;; + * ) + BOOST_THREAD_LIB="$BOOST_THREAD_LIB -lpthread" + break; + ;; + esac + AC_SUBST(BOOST_THREAD_LIB) + fi + fi - CPPFLAGS="$CPPFLAGS_SAVED" - LDFLAGS="$LDFLAGS_SAVED" - fi + CPPFLAGS="$CPPFLAGS_SAVED" + LDFLAGS="$LDFLAGS_SAVED" + fi ]) diff --git a/build-aux/m4/ax_boost_unit_test_framework.m4 b/build-aux/m4/ax_boost_unit_test_framework.m4 index 3d8e93e964..4cca32fcfd 100644 --- a/build-aux/m4/ax_boost_unit_test_framework.m4 +++ b/build-aux/m4/ax_boost_unit_test_framework.m4 @@ -29,7 +29,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 21 +#serial 22 AC_DEFUN([AX_BOOST_UNIT_TEST_FRAMEWORK], [ @@ -124,7 +124,7 @@ AC_DEFUN([AX_BOOST_UNIT_TEST_FRAMEWORK], done fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the library!) + AC_MSG_ERROR(Could not find a version of the Boost::Unit_Test_Framework library!) fi if test "x$link_unit_test_framework" != "xyes"; then AC_MSG_ERROR(Could not link against $ax_lib !) diff --git a/ci/lint/04_install.sh b/ci/lint/04_install.sh index 6c3019a1aa..12c3bfce45 100755 --- a/ci/lint/04_install.sh +++ b/ci/lint/04_install.sh @@ -8,7 +8,6 @@ export LC_ALL=C travis_retry pip3 install codespell==1.15.0 travis_retry pip3 install flake8==3.7.8 -travis_retry pip3 install vulture==1.0 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/ diff --git a/ci/test/00_setup_env.sh b/ci/test/00_setup_env.sh index 51b5cfdd3f..94598835ac 100755 --- a/ci/test/00_setup_env.sh +++ b/ci/test/00_setup_env.sh @@ -6,11 +6,17 @@ export LC_ALL=C.UTF-8 -echo "Setting default values in env" +echo "Setting specific values in env" +if [ -n "${FILE_ENV}" ]; then + set -o errexit; + # shellcheck disable=SC1090 + source "${FILE_ENV}" +fi BASE_ROOT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )"/../../ >/dev/null 2>&1 && pwd ) export BASE_ROOT_DIR +echo "Fallback to default values in env (if not yet set)" # The number of parallel jobs to pass down to make and test_runner.py export MAKEJOBS=${MAKEJOBS:--j4} # A folder for the ci system to put temporary files (ccache, datadirs for tests, ...) @@ -20,12 +26,16 @@ export RUN_UNIT_TESTS=${RUN_UNIT_TESTS:-true} export RUN_FUNCTIONAL_TESTS=${RUN_FUNCTIONAL_TESTS:-true} export RUN_FUZZ_TESTS=${RUN_FUZZ_TESTS:-false} export DOCKER_NAME_TAG=${DOCKER_NAME_TAG:-ubuntu:18.04} -export BOOST_TEST_RANDOM=${BOOST_TEST_RANDOM:-1$TRAVIS_BUILD_ID} +# Randomize test order. +# See https://www.boost.org/doc/libs/1_71_0/libs/test/doc/html/boost_test/utf_reference/rt_param_reference/random.html +export BOOST_TEST_RANDOM=${BOOST_TEST_RANDOM:-1} export CCACHE_SIZE=${CCACHE_SIZE:-100M} export CCACHE_TEMPDIR=${CCACHE_TEMPDIR:-/tmp/.ccache-temp} export CCACHE_COMPRESS=${CCACHE_COMPRESS:-1} export CCACHE_DIR=${CCACHE_DIR:-$BASE_SCRATCH_DIR/.ccache} -export BASE_BUILD_DIR=${BASE_BUILD_DIR:-${TRAVIS_BUILD_DIR:-$BASE_ROOT_DIR}} +# Folder where the build is done (depends and dist). Can not be changed and is equal to the root of the git repo +export BASE_BUILD_DIR=${BASE_BUILD_DIR:-$BASE_ROOT_DIR} +# Folder where the build is done (bin and lib). Can not be changed. export BASE_OUTDIR=${BASE_OUTDIR:-$BASE_BUILD_DIR/out/$HOST} export SDK_URL=${SDK_URL:-https://bitcoincore.org/depends-sources/sdks} export WINEDEBUG=${WINEDEBUG:-fixme-all} @@ -34,10 +44,3 @@ export GOAL=${GOAL:-install} export DIR_QA_ASSETS=${DIR_QA_ASSETS:-${BASE_BUILD_DIR}/qa-assets} export PATH=${BASE_ROOT_DIR}/ci/retry:$PATH export CI_RETRY_EXE=${CI_RETRY_EXE:retry} - -echo "Setting specific values in env" -if [ -n "${FILE_ENV}" ]; then - set -o errexit; - # shellcheck disable=SC1090 - source "${FILE_ENV}" -fi diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 56045ade50..f4832b6168 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -176,9 +176,9 @@ define $(package)_preprocess_cmds patch -p1 -i $($(package)_patch_dir)/no-xlib.patch &&\ echo "QMAKE_LINK_OBJECT_MAX = 10" >> qtbase/mkspecs/win32-g++/qmake.conf &&\ echo "QMAKE_LINK_OBJECT_SCRIPT = object_script" >> qtbase/mkspecs/win32-g++/qmake.conf &&\ - sed -i.old "s|QMAKE_CFLAGS = |!host_build: QMAKE_CFLAGS = $($(package)_cflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ - sed -i.old "s|QMAKE_LFLAGS = |!host_build: QMAKE_LFLAGS = $($(package)_ldflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ - sed -i.old "s|QMAKE_CXXFLAGS = |!host_build: QMAKE_CXXFLAGS = $($(package)_cxxflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ + sed -i.old "s|QMAKE_CFLAGS += |!host_build: QMAKE_CFLAGS = $($(package)_cflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ + sed -i.old "s|QMAKE_CXXFLAGS += |!host_build: QMAKE_CXXFLAGS = $($(package)_cxxflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ + sed -i.old "0,/^QMAKE_LFLAGS_/s|^QMAKE_LFLAGS_|!host_build: QMAKE_LFLAGS = $($(package)_ldflags)\n&|" qtbase/mkspecs/win32-g++/qmake.conf && \ sed -i.old "s/LIBRARY_PATH/(CROSS_)?\0/g" qtbase/mkspecs/features/toolchain.prf endef diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 399d54eb85..cd7ccf80ab 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -790,7 +790,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = src +INPUT = src doc/README_doxygen.md # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -974,7 +974,7 @@ FILTER_SOURCE_PATTERNS = # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. -USE_MDFILE_AS_MAINPAGE = +USE_MDFILE_AS_MAINPAGE = doc/README_doxygen.md #--------------------------------------------------------------------------- # Configuration options related to source browsing diff --git a/doc/README_doxygen.md b/doc/README_doxygen.md new file mode 100644 index 0000000000..6888383a98 --- /dev/null +++ b/doc/README_doxygen.md @@ -0,0 +1,15 @@ +\mainpage notitle + +\section intro_sec Introduction + +This is the developer documentation of the reference client for an experimental new digital currency called Bitcoin, +which enables instant payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer technology to operate +with no central authority: managing transactions and issuing money are carried out collectively by the network. + +The software is a community-driven open source project, released under the MIT license. + +See https://github.com/bitcoin/bitcoin and https://bitcoincore.org/ for further information about the project. + +\section Navigation +Use <a href="modules.html"><code>Modules</code></a>, <a href="namespaces.html"><code>Namespaces</code></a>, <a href="classes.html"><code>Classes</code></a>, or <a href="files.html"><code>Files</code></a> at the top of the page to start navigating the code. + diff --git a/doc/translation_process.md b/doc/translation_process.md index 0e9245250f..39f878cea3 100644 --- a/doc/translation_process.md +++ b/doc/translation_process.md @@ -73,16 +73,10 @@ To assist in updating translations, a helper script is available in the [maintai ```bash git ls-files src/qt/locale/*ts|xargs -n1 basename|sed 's/\(bitcoin_\(.*\)\).ts/ <file alias="\2">locale\/\1.qm<\/file>/' ``` -4. Update `src/Makefile.qt.include` manually or via +4. Update `src/Makefile.qt_locale.include` manually or via ```bash git ls-files src/qt/locale/*ts|xargs -n1 basename|sed 's/\(bitcoin_\(.*\)\).ts/ qt\/locale\/\1.ts \\/' ``` -5. Update `build_msvc/libbitcoin_qt/libbitcoin_qt.vcxproj` or via -```bash -git ls-files src/qt/locale/*ts|xargs -n1 basename | - sed 's/@/%40/' | - sed 's/\(bitcoin_\(.*\)\).ts/ <None Include="..\\..\\src\\qt\\locale\\\1.ts">\n <DeploymentContent>true<\/DeploymentContent>\n <\/None>/' -``` **Do not directly download translations** one by one from the Transifex website, as we do a few post-processing steps before committing the translations. diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 7540122418..a8d3154107 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -6,93 +6,7 @@ bin_PROGRAMS += qt/bitcoin-qt EXTRA_LIBRARIES += qt/libbitcoinqt.a # bitcoin qt core # -QT_TS = \ - qt/locale/bitcoin_af.ts \ - qt/locale/bitcoin_af_ZA.ts \ - qt/locale/bitcoin_ar.ts \ - qt/locale/bitcoin_be_BY.ts \ - qt/locale/bitcoin_bg_BG.ts \ - qt/locale/bitcoin_bg.ts \ - qt/locale/bitcoin_ca_ES.ts \ - qt/locale/bitcoin_ca.ts \ - qt/locale/bitcoin_ca@valencia.ts \ - qt/locale/bitcoin_cs.ts \ - qt/locale/bitcoin_cy.ts \ - qt/locale/bitcoin_da.ts \ - qt/locale/bitcoin_de.ts \ - qt/locale/bitcoin_el_GR.ts \ - qt/locale/bitcoin_el.ts \ - qt/locale/bitcoin_en_GB.ts \ - qt/locale/bitcoin_en.ts \ - qt/locale/bitcoin_eo.ts \ - qt/locale/bitcoin_es_AR.ts \ - qt/locale/bitcoin_es_CL.ts \ - qt/locale/bitcoin_es_CO.ts \ - qt/locale/bitcoin_es_DO.ts \ - qt/locale/bitcoin_es_ES.ts \ - qt/locale/bitcoin_es_MX.ts \ - qt/locale/bitcoin_es.ts \ - qt/locale/bitcoin_es_UY.ts \ - qt/locale/bitcoin_es_VE.ts \ - qt/locale/bitcoin_et_EE.ts \ - qt/locale/bitcoin_et.ts \ - qt/locale/bitcoin_eu_ES.ts \ - qt/locale/bitcoin_fa_IR.ts \ - qt/locale/bitcoin_fa.ts \ - qt/locale/bitcoin_fi.ts \ - qt/locale/bitcoin_fr_CA.ts \ - qt/locale/bitcoin_fr_FR.ts \ - qt/locale/bitcoin_fr.ts \ - qt/locale/bitcoin_gl.ts \ - qt/locale/bitcoin_he.ts \ - qt/locale/bitcoin_hi_IN.ts \ - qt/locale/bitcoin_hr.ts \ - qt/locale/bitcoin_hu.ts \ - qt/locale/bitcoin_id_ID.ts \ - qt/locale/bitcoin_it_IT.ts \ - qt/locale/bitcoin_it.ts \ - qt/locale/bitcoin_ja.ts \ - qt/locale/bitcoin_ka.ts \ - qt/locale/bitcoin_kk_KZ.ts \ - qt/locale/bitcoin_ko_KR.ts \ - qt/locale/bitcoin_ku_IQ.ts \ - qt/locale/bitcoin_ky.ts \ - qt/locale/bitcoin_la.ts \ - qt/locale/bitcoin_lt.ts \ - qt/locale/bitcoin_lv_LV.ts \ - qt/locale/bitcoin_mk_MK.ts \ - qt/locale/bitcoin_mn.ts \ - qt/locale/bitcoin_ms_MY.ts \ - qt/locale/bitcoin_nb.ts \ - qt/locale/bitcoin_ne.ts \ - qt/locale/bitcoin_nl.ts \ - qt/locale/bitcoin_pam.ts \ - qt/locale/bitcoin_pl.ts \ - qt/locale/bitcoin_pt_BR.ts \ - qt/locale/bitcoin_pt_PT.ts \ - qt/locale/bitcoin_ro_RO.ts \ - qt/locale/bitcoin_ro.ts \ - qt/locale/bitcoin_ru_RU.ts \ - qt/locale/bitcoin_ru.ts \ - qt/locale/bitcoin_sk.ts \ - qt/locale/bitcoin_sl_SI.ts \ - qt/locale/bitcoin_sq.ts \ - qt/locale/bitcoin_sr@latin.ts \ - qt/locale/bitcoin_sr.ts \ - qt/locale/bitcoin_sv.ts \ - qt/locale/bitcoin_ta.ts \ - qt/locale/bitcoin_th_TH.ts \ - qt/locale/bitcoin_tr_TR.ts \ - qt/locale/bitcoin_tr.ts \ - qt/locale/bitcoin_uk.ts \ - qt/locale/bitcoin_ur_PK.ts \ - qt/locale/bitcoin_uz@Cyrl.ts \ - qt/locale/bitcoin_vi.ts \ - qt/locale/bitcoin_vi_VN.ts \ - qt/locale/bitcoin_zh_CN.ts \ - qt/locale/bitcoin_zh_HK.ts \ - qt/locale/bitcoin_zh.ts \ - qt/locale/bitcoin_zh_TW.ts +include Makefile.qt_locale.include QT_FORMS_UI = \ qt/forms/addressbookpage.ui \ diff --git a/src/Makefile.qt_locale.include b/src/Makefile.qt_locale.include new file mode 100644 index 0000000000..d9f23e8da2 --- /dev/null +++ b/src/Makefile.qt_locale.include @@ -0,0 +1,87 @@ +QT_TS = \ + qt/locale/bitcoin_af.ts \ + qt/locale/bitcoin_af_ZA.ts \ + qt/locale/bitcoin_ar.ts \ + qt/locale/bitcoin_be_BY.ts \ + qt/locale/bitcoin_bg_BG.ts \ + qt/locale/bitcoin_bg.ts \ + qt/locale/bitcoin_ca_ES.ts \ + qt/locale/bitcoin_ca.ts \ + qt/locale/bitcoin_ca@valencia.ts \ + qt/locale/bitcoin_cs.ts \ + qt/locale/bitcoin_cy.ts \ + qt/locale/bitcoin_da.ts \ + qt/locale/bitcoin_de.ts \ + qt/locale/bitcoin_el_GR.ts \ + qt/locale/bitcoin_el.ts \ + qt/locale/bitcoin_en_GB.ts \ + qt/locale/bitcoin_en.ts \ + qt/locale/bitcoin_eo.ts \ + qt/locale/bitcoin_es_AR.ts \ + qt/locale/bitcoin_es_CL.ts \ + qt/locale/bitcoin_es_CO.ts \ + qt/locale/bitcoin_es_DO.ts \ + qt/locale/bitcoin_es_ES.ts \ + qt/locale/bitcoin_es_MX.ts \ + qt/locale/bitcoin_es.ts \ + qt/locale/bitcoin_es_UY.ts \ + qt/locale/bitcoin_es_VE.ts \ + qt/locale/bitcoin_et_EE.ts \ + qt/locale/bitcoin_et.ts \ + qt/locale/bitcoin_eu_ES.ts \ + qt/locale/bitcoin_fa_IR.ts \ + qt/locale/bitcoin_fa.ts \ + qt/locale/bitcoin_fi.ts \ + qt/locale/bitcoin_fr_CA.ts \ + qt/locale/bitcoin_fr_FR.ts \ + qt/locale/bitcoin_fr.ts \ + qt/locale/bitcoin_gl.ts \ + qt/locale/bitcoin_he.ts \ + qt/locale/bitcoin_hi_IN.ts \ + qt/locale/bitcoin_hr.ts \ + qt/locale/bitcoin_hu.ts \ + qt/locale/bitcoin_id_ID.ts \ + qt/locale/bitcoin_it_IT.ts \ + qt/locale/bitcoin_it.ts \ + qt/locale/bitcoin_ja.ts \ + qt/locale/bitcoin_ka.ts \ + qt/locale/bitcoin_kk_KZ.ts \ + qt/locale/bitcoin_ko_KR.ts \ + qt/locale/bitcoin_ku_IQ.ts \ + qt/locale/bitcoin_ky.ts \ + qt/locale/bitcoin_la.ts \ + qt/locale/bitcoin_lt.ts \ + qt/locale/bitcoin_lv_LV.ts \ + qt/locale/bitcoin_mk_MK.ts \ + qt/locale/bitcoin_mn.ts \ + qt/locale/bitcoin_ms_MY.ts \ + qt/locale/bitcoin_nb.ts \ + qt/locale/bitcoin_ne.ts \ + qt/locale/bitcoin_nl.ts \ + qt/locale/bitcoin_pam.ts \ + qt/locale/bitcoin_pl.ts \ + qt/locale/bitcoin_pt_BR.ts \ + qt/locale/bitcoin_pt_PT.ts \ + qt/locale/bitcoin_ro_RO.ts \ + qt/locale/bitcoin_ro.ts \ + qt/locale/bitcoin_ru_RU.ts \ + qt/locale/bitcoin_ru.ts \ + qt/locale/bitcoin_sk.ts \ + qt/locale/bitcoin_sl_SI.ts \ + qt/locale/bitcoin_sq.ts \ + qt/locale/bitcoin_sr@latin.ts \ + qt/locale/bitcoin_sr.ts \ + qt/locale/bitcoin_sv.ts \ + qt/locale/bitcoin_ta.ts \ + qt/locale/bitcoin_th_TH.ts \ + qt/locale/bitcoin_tr_TR.ts \ + qt/locale/bitcoin_tr.ts \ + qt/locale/bitcoin_uk.ts \ + qt/locale/bitcoin_ur_PK.ts \ + qt/locale/bitcoin_uz@Cyrl.ts \ + qt/locale/bitcoin_vi.ts \ + qt/locale/bitcoin_vi_VN.ts \ + qt/locale/bitcoin_zh_CN.ts \ + qt/locale/bitcoin_zh_HK.ts \ + qt/locale/bitcoin_zh.ts \ + qt/locale/bitcoin_zh_TW.ts diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 83de684a2b..615b955f6e 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -25,24 +25,6 @@ const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr; -/* Introduction text for doxygen: */ - -/*! \mainpage Developer documentation - * - * \section intro_sec Introduction - * - * This is the developer documentation of the reference client for an experimental new digital currency called Bitcoin, - * which enables instant payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer technology to operate - * with no central authority: managing transactions and issuing money are carried out collectively by the network. - * - * The software is a community-driven open source project, released under the MIT license. - * - * See https://github.com/bitcoin/bitcoin and https://bitcoincore.org/ for further information about the project. - * - * \section Navigation - * Use the buttons <code>Namespaces</code>, <code>Classes</code> or <code>Files</code> at the top of the page to start navigating the code. - */ - static void WaitForShutdown() { while (!ShutdownRequested()) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index ad766471dc..5964877eb8 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -71,6 +71,7 @@ public: consensus.BIP66Height = 363725; // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931 consensus.CSVHeight = 419328; // 000000000000000004a1b34462cb8aeebd5799177f7a29cf28f2d1961716b5b5 consensus.SegwitHeight = 481824; // 0000000000000000001c8018d9cb3b742ef25114f27563e3fc4a1902167f9893 + consensus.MinBIP9WarningHeight = consensus.SegwitHeight + consensus.nMinerConfirmationWindow; consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks consensus.nPowTargetSpacing = 10 * 60; @@ -177,6 +178,7 @@ public: consensus.BIP66Height = 330776; // 000000002104c8c45e99a8853285a3b592602a3ccde2b832481da85e9e4ba182 consensus.CSVHeight = 770112; // 00000000025e930139bac5c6c31a403776da130831ab85be56578f3fa75369bb consensus.SegwitHeight = 834624; // 00000000002b980fcd729daaa248fd9316a5200e9b367f4ff2c42453e84201ca + consensus.MinBIP9WarningHeight = consensus.SegwitHeight + consensus.nMinerConfirmationWindow; consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks consensus.nPowTargetSpacing = 10 * 60; @@ -261,6 +263,7 @@ public: consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in functional tests) consensus.CSVHeight = 432; // CSV activated on regtest (Used in rpc activation tests) consensus.SegwitHeight = 0; // SEGWIT is always activated on regtest unless overridden + consensus.MinBIP9WarningHeight = 0; consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks consensus.nPowTargetSpacing = 10 * 60; diff --git a/src/coins.h b/src/coins.h index dca1beabb6..d8135e0d9a 100644 --- a/src/coins.h +++ b/src/coins.h @@ -95,8 +95,16 @@ public: * This *must* return size_t. With Boost 1.46 on 32-bit systems the * unordered_map will behave unpredictably if the custom hasher returns a * uint64_t, resulting in failures when syncing the chain (#4634). + * + * Having the hash noexcept allows libstdc++'s unordered_map to recalculate + * the hash during rehash, so it does not have to cache the value. This + * reduces node's memory by sizeof(size_t). The required recalculation has + * a slight performance penalty (around 1.6%), but this is compensated by + * memory savings of about 9% which allow for a larger dbcache setting. + * + * @see https://gcc.gnu.org/onlinedocs/gcc-9.2.0/libstdc++/manual/manual/unordered_associative.html */ - size_t operator()(const COutPoint& id) const { + size_t operator()(const COutPoint& id) const noexcept { return SipHashUint256Extra(k0, k1, id.hash, id.n); } }; diff --git a/src/consensus/params.h b/src/consensus/params.h index 8263b0fef4..2f8c490dc4 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -62,6 +62,9 @@ struct Params { * Note that segwit v0 script rules are enforced on all blocks except the * BIP 16 exception blocks. */ int SegwitHeight; + /** Don't warn about unknown BIP 9 activations below this height. + * This prevents us from warning about the CSV and segwit activations. */ + int MinBIP9WarningHeight; /** * Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period, * (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments. diff --git a/src/net.cpp b/src/net.cpp index 89f82aa3d2..63b7833822 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -50,6 +50,9 @@ static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed" // Dump addresses to peers.dat every 15 minutes (900s) static constexpr int DUMP_PEERS_INTERVAL = 15 * 60; +/** Number of DNS seeds to query when the number of connections is low. */ +static constexpr int DNSSEEDS_TO_QUERY_AT_ONCE = 3; + // We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization. #define FEELER_SLEEP_WINDOW 1 @@ -1535,35 +1538,41 @@ void StopMapPort() void CConnman::ThreadDNSAddressSeed() { - // goal: only query DNS seeds if address need is acute - // Avoiding DNS seeds when we don't need them improves user privacy by - // creating fewer identifying DNS requests, reduces trust by giving seeds - // less influence on the network topology, and reduces traffic to the seeds. - if ((addrman.size() > 0) && - (!gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED))) { - if (!interruptNet.sleep_for(std::chrono::seconds(11))) - return; + FastRandomContext rng; + std::vector<std::string> seeds = Params().DNSSeeds(); + Shuffle(seeds.begin(), seeds.end(), rng); + int seeds_right_now = 0; // Number of seeds left before testing if we have enough connections + int found = 0; - LOCK(cs_vNodes); - int nRelevant = 0; - for (const CNode* pnode : vNodes) { - nRelevant += pnode->fSuccessfullyConnected && !pnode->fFeeler && !pnode->fOneShot && !pnode->m_manual_connection && !pnode->fInbound; - } - if (nRelevant >= 2) { - LogPrintf("P2P peers available. Skipped DNS seeding.\n"); - return; - } + if (gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED)) { + // When -forcednsseed is provided, query all. + seeds_right_now = seeds.size(); } - const std::vector<std::string> &vSeeds = Params().DNSSeeds(); - int found = 0; + for (const std::string& seed : seeds) { + // goal: only query DNS seed if address need is acute + // Avoiding DNS seeds when we don't need them improves user privacy by + // creating fewer identifying DNS requests, reduces trust by giving seeds + // less influence on the network topology, and reduces traffic to the seeds. + if (addrman.size() > 0 && seeds_right_now == 0) { + if (!interruptNet.sleep_for(std::chrono::seconds(11))) return; - LogPrintf("Loading addresses from DNS seeds (could take a while)\n"); + LOCK(cs_vNodes); + int nRelevant = 0; + for (const CNode* pnode : vNodes) { + nRelevant += pnode->fSuccessfullyConnected && !pnode->fFeeler && !pnode->fOneShot && !pnode->m_manual_connection && !pnode->fInbound; + } + if (nRelevant >= 2) { + LogPrintf("P2P peers available. Skipped DNS seeding.\n"); + return; + } + seeds_right_now += DNSSEEDS_TO_QUERY_AT_ONCE; + } - for (const std::string &seed : vSeeds) { if (interruptNet) { return; } + LogPrintf("Loading addresses from DNS seed %s\n", seed); if (HaveNameProxy()) { AddOneShot(seed); } else { @@ -1576,13 +1585,11 @@ void CConnman::ThreadDNSAddressSeed() continue; } unsigned int nMaxIPs = 256; // Limits number of IPs learned from a DNS seed - if (LookupHost(host.c_str(), vIPs, nMaxIPs, true)) - { - for (const CNetAddr& ip : vIPs) - { + if (LookupHost(host.c_str(), vIPs, nMaxIPs, true)) { + for (const CNetAddr& ip : vIPs) { int nOneDay = 24*3600; CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()), requiredServiceBits); - addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old + addr.nTime = GetTime() - 3*nOneDay - rng.randrange(4*nOneDay); // use a random age between 3 and 7 days old vAdd.push_back(addr); found++; } @@ -1593,8 +1600,8 @@ void CConnman::ThreadDNSAddressSeed() AddOneShot(seed); } } + --seeds_right_now; } - LogPrintf("%d addresses found from DNS seeds\n", found); } diff --git a/src/qt/forms/receivecoinsdialog.ui b/src/qt/forms/receivecoinsdialog.ui index 0d280f2993..0214356eaa 100644 --- a/src/qt/forms/receivecoinsdialog.ui +++ b/src/qt/forms/receivecoinsdialog.ui @@ -189,7 +189,7 @@ </widget> </item> <item> - <widget class="QCheckBox" name="useLegacyAddress"> + <widget class="QCheckBox" name="useBech32"> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> @@ -206,10 +206,10 @@ <enum>Qt::StrongFocus</enum> </property> <property name="toolTip"> - <string>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When checked, an address compatible with older wallets will be created instead.</string> + <string>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</string> </property> <property name="text"> - <string>Generate legacy address</string> + <string>Generate native segwit (Bech32) address</string> </property> </widget> </item> @@ -360,7 +360,7 @@ <tabstops> <tabstop>reqLabel</tabstop> <tabstop>reqAmount</tabstop> - <tabstop>useLegacyAddress</tabstop> + <tabstop>useBech32</tabstop> <tabstop>reqMessage</tabstop> <tabstop>receiveButton</tabstop> <tabstop>clearButton</tabstop> diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 9e05c63aa0..53c80639b9 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -154,6 +154,7 @@ Intro::Intro(QWidget *parent, uint64_t blockchain_size, uint64_t chain_state_siz storageRequiresMsg.arg(requiredSpace) + " " + tr("The wallet will also be stored in this directory.") ); + this->adjustSize(); startThread(); } diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index 7d9e7eab4e..d34fd9eb45 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -2696,17 +2696,7 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+136"/> - <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When checked, an address compatible with older wallets will be created instead.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="+3"/> - <source>Generate legacy address</source> - <translation type="unfinished"></translation> - </message> - <message> - <location line="-178"/> + <location line="-39"/> <location line="+153"/> <source>An optional amount to request. Leave this empty or zero to not request a specific amount.</source> <translation type="unfinished"></translation> @@ -2727,7 +2717,17 @@ <translation type="unfinished"></translation> </message> <message> - <location line="+142"/> + <location line="+78"/> + <source>Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+3"/> + <source>Generate native segwit (Bech32) address</source> + <translation type="unfinished"></translation> + </message> + <message> + <location line="+61"/> <source>Requested payments history</source> <translation type="unfinished"></translation> </message> diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index e8cf432131..df8d5115d5 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -96,13 +96,13 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model) if (model->node().isAddressTypeSet()) { // user explicitly set the type, use it if (model->wallet().getDefaultAddressType() == OutputType::BECH32) { - ui->useLegacyAddress->setCheckState(Qt::Unchecked); + ui->useBech32->setCheckState(Qt::Checked); } else { - ui->useLegacyAddress->setCheckState(Qt::Checked); + ui->useBech32->setCheckState(Qt::Unchecked); } } else { // Always fall back to bech32 in the gui - ui->useLegacyAddress->setCheckState(Qt::Unchecked); + ui->useBech32->setCheckState(Qt::Checked); } // Set the button to be enabled or disabled based on whether the wallet can give out new addresses. @@ -155,7 +155,7 @@ void ReceiveCoinsDialog::on_receiveButton_clicked() QString label = ui->reqLabel->text(); /* Generate new receiving address */ OutputType address_type; - if (!ui->useLegacyAddress->isChecked()) { + if (ui->useBech32->isChecked()) { address_type = OutputType::BECH32; } else { address_type = model->wallet().getDefaultAddressType(); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 9513c2b9ac..02717fa80f 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1159,7 +1159,7 @@ static void BIP9SoftForkDescPushBack(UniValue& softforks, const std::string &nam { bip9.pushKV("bit", consensusParams.vDeployments[id].bit); } - bip9.pushKV("startTime", consensusParams.vDeployments[id].nStartTime); + bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime); bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout); int64_t since_height = VersionBitsTipStateSinceHeight(consensusParams, id); bip9.pushKV("since", since_height); @@ -1213,7 +1213,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) " \"bip9\": { (object) status of bip9 softforks (only for \"bip9\" type)\n" " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" " \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n" - " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" + " \"start_time\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" " \"timeout\": xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" " \"since\": xx, (numeric) height of the first block to which the status applies\n" " \"statistics\": { (object) numeric statistics about BIP9 signalling for a softfork\n" diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 461e8025da..f548d356cf 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -39,9 +39,9 @@ #include <univalue.h> -/** High fee rate for sendrawtransaction and testmempoolaccept. - * By default, transaction with a fee rate higher than this will be rejected by - * the RPCs. This can be overridden with the maxfeerate argument. +/** Maximum fee rate for sendrawtransaction and testmempoolaccept. + * By default, a transaction with a fee rate higher than this will be rejected + * by the RPCs. This can be overridden with the maxfeerate argument. */ static const CFeeRate DEFAULT_MAX_RAW_TX_FEE_RATE{COIN / 10}; diff --git a/src/streams.h b/src/streams.h index 4e600f1826..517eefc932 100644 --- a/src/streams.h +++ b/src/streams.h @@ -735,16 +735,17 @@ protected: size_t nBytes = fread((void*)&vchBuf[pos], 1, readNow, src); if (nBytes == 0) { throw std::ios_base::failure(feof(src) ? "CBufferedFile::Fill: end of file" : "CBufferedFile::Fill: fread failed"); - } else { - nSrcPos += nBytes; - return true; } + nSrcPos += nBytes; + return true; } public: CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn), nSrcPos(0), nReadPos(0), nReadLimit(std::numeric_limits<uint64_t>::max()), nRewind(nRewindIn), vchBuf(nBufSize, 0) { + if (nRewindIn >= nBufSize) + throw std::ios_base::failure("Rewind limit must be less than buffer size"); src = fileIn; } @@ -777,8 +778,6 @@ public: void read(char *pch, size_t nSize) { if (nSize + nReadPos > nReadLimit) throw std::ios_base::failure("Read attempted past buffer limit"); - if (nSize + nRewind > vchBuf.size()) - throw std::ios_base::failure("Read larger than buffer size"); while (nSize > 0) { if (nReadPos == nSrcPos) Fill(); @@ -802,16 +801,19 @@ public: //! rewind to a given reading position bool SetPos(uint64_t nPos) { - nReadPos = nPos; - if (nReadPos + nRewind < nSrcPos) { - nReadPos = nSrcPos - nRewind; + size_t bufsize = vchBuf.size(); + if (nPos + bufsize < nSrcPos) { + // rewinding too far, rewind as far as possible + nReadPos = nSrcPos - bufsize; return false; - } else if (nReadPos > nSrcPos) { + } + if (nPos > nSrcPos) { + // can't go this far forward, go as far as possible nReadPos = nSrcPos; return false; - } else { - return true; } + nReadPos = nPos; + return true; } bool Seek(uint64_t nPos) { diff --git a/src/test/README.md b/src/test/README.md index 8901fae7bd..96dcb072bc 100644 --- a/src/test/README.md +++ b/src/test/README.md @@ -1,3 +1,15 @@ +# Unit tests + +The sources in this directory are unit test cases. Boost includes a +unit testing framework, and since Bitcoin Core already uses Boost, it makes +sense to simply use this framework rather than require developers to +configure some other framework (we want as few impediments to creating +unit tests as possible). + +The build system is set up to compile an executable called `test_bitcoin` +that runs all of the unit tests. The main source file is called +`setup_common.cpp`. + ### Compiling/running unit tests Unit tests will be automatically compiled if dependencies were met in `./configure` @@ -12,7 +24,7 @@ to run the bitcoind tests. To add more bitcoind tests, add `BOOST_AUTO_TEST_CASE` functions to the existing .cpp files in the `test/` directory or add new .cpp files that -implement new BOOST_AUTO_TEST_SUITE sections. +implement new `BOOST_AUTO_TEST_SUITE` sections. To run the bitcoin-qt tests manually, launch `src/qt/test/test_bitcoin-qt` @@ -32,20 +44,24 @@ example, to run just the getarg_tests verbosely: Run `test_bitcoin --help` for the full list. -### Note on adding test cases - -The sources in this directory are unit test cases. Boost includes a -unit testing framework, and since bitcoin already uses boost, it makes -sense to simply use this framework rather than require developers to -configure some other framework (we want as few impediments to creating -unit tests as possible). +### Adding test cases -The build system is setup to compile an executable called `test_bitcoin` -that runs all of the unit tests. The main source file is called -setup_common.cpp. To add a new unit test file to our test suite you need +To add a new unit test file to our test suite you need to add the file to `src/Makefile.test.include`. The pattern is to create one test file for each class or source file for which you want to create -unit tests. The file naming convention is `<source_filename>_tests.cpp` +unit tests. The file naming convention is `<source_filename>_tests.cpp` and such files should wrap their tests in a test suite called `<source_filename>_tests`. For an example of this pattern, -examine `uint256_tests.cpp`. +see `uint256_tests.cpp`. + +### Logging and debugging in unit tests + +To write to logs from unit tests you need to use specific message methods +provided by Boost. The simplest is `BOOST_TEST_MESSAGE`. + +For debugging you can launch the test_bitcoin executable with `gdb`or `lldb` and +start debugging, just like you would with bitcoind: + +```bash +gdb src/test/test_bitcoin +``` diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp index b812cef801..638819d564 100644 --- a/src/test/streams_tests.cpp +++ b/src/test/streams_tests.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include <random.h> #include <streams.h> #include <test/setup_common.h> @@ -202,4 +203,247 @@ BOOST_AUTO_TEST_CASE(streams_serializedata_xor) std::string(ds.begin(), ds.end())); } +BOOST_AUTO_TEST_CASE(streams_buffered_file) +{ + FILE* file = fsbridge::fopen("streams_test_tmp", "w+b"); + // The value at each offset is the offset. + for (uint8_t j = 0; j < 40; ++j) { + fwrite(&j, 1, 1, file); + } + rewind(file); + + // The buffer size (second arg) must be greater than the rewind + // amount (third arg). + try { + CBufferedFile bfbad(file, 25, 25, 222, 333); + BOOST_CHECK(false); + } catch (const std::exception& e) { + BOOST_CHECK(strstr(e.what(), + "Rewind limit must be less than buffer size") != nullptr); + } + + // The buffer is 25 bytes, allow rewinding 10 bytes. + CBufferedFile bf(file, 25, 10, 222, 333); + BOOST_CHECK(!bf.eof()); + + // These two members have no functional effect. + BOOST_CHECK_EQUAL(bf.GetType(), 222); + BOOST_CHECK_EQUAL(bf.GetVersion(), 333); + + uint8_t i; + bf >> i; + BOOST_CHECK_EQUAL(i, 0); + bf >> i; + BOOST_CHECK_EQUAL(i, 1); + + // After reading bytes 0 and 1, we're positioned at 2. + BOOST_CHECK_EQUAL(bf.GetPos(), 2); + + // Rewind to offset 0, ok (within the 10 byte window). + BOOST_CHECK(bf.SetPos(0)); + bf >> i; + BOOST_CHECK_EQUAL(i, 0); + + // We can go forward to where we've been, but beyond may fail. + BOOST_CHECK(bf.SetPos(2)); + bf >> i; + BOOST_CHECK_EQUAL(i, 2); + + // If you know the maximum number of bytes that should be + // read to deserialize the variable, you can limit the read + // extent. The current file offset is 3, so the following + // SetLimit() allows zero bytes to be read. + BOOST_CHECK(bf.SetLimit(3)); + try { + bf >> i; + BOOST_CHECK(false); + } catch (const std::exception& e) { + BOOST_CHECK(strstr(e.what(), + "Read attempted past buffer limit") != nullptr); + } + // The default argument removes the limit completely. + BOOST_CHECK(bf.SetLimit()); + // The read position should still be at 3 (no change). + BOOST_CHECK_EQUAL(bf.GetPos(), 3); + + // Read from current offset, 3, forward until position 10. + for (uint8_t j = 3; j < 10; ++j) { + bf >> i; + BOOST_CHECK_EQUAL(i, j); + } + BOOST_CHECK_EQUAL(bf.GetPos(), 10); + + // We're guaranteed (just barely) to be able to rewind to zero. + BOOST_CHECK(bf.SetPos(0)); + BOOST_CHECK_EQUAL(bf.GetPos(), 0); + bf >> i; + BOOST_CHECK_EQUAL(i, 0); + + // We can set the position forward again up to the farthest + // into the stream we've been, but no farther. (Attempting + // to go farther may succeed, but it's not guaranteed.) + BOOST_CHECK(bf.SetPos(10)); + bf >> i; + BOOST_CHECK_EQUAL(i, 10); + BOOST_CHECK_EQUAL(bf.GetPos(), 11); + + // Now it's only guaranteed that we can rewind to offset 1 + // (current read position, 11, minus rewind amount, 10). + BOOST_CHECK(bf.SetPos(1)); + BOOST_CHECK_EQUAL(bf.GetPos(), 1); + bf >> i; + BOOST_CHECK_EQUAL(i, 1); + + // We can stream into large variables, even larger than + // the buffer size. + BOOST_CHECK(bf.SetPos(11)); + { + uint8_t a[40 - 11]; + bf >> a; + for (uint8_t j = 0; j < sizeof(a); ++j) { + BOOST_CHECK_EQUAL(a[j], 11 + j); + } + } + BOOST_CHECK_EQUAL(bf.GetPos(), 40); + + // We've read the entire file, the next read should throw. + try { + bf >> i; + BOOST_CHECK(false); + } catch (const std::exception& e) { + BOOST_CHECK(strstr(e.what(), + "CBufferedFile::Fill: end of file") != nullptr); + } + // Attempting to read beyond the end sets the EOF indicator. + BOOST_CHECK(bf.eof()); + + // Still at offset 40, we can go back 10, to 30. + BOOST_CHECK_EQUAL(bf.GetPos(), 40); + BOOST_CHECK(bf.SetPos(30)); + bf >> i; + BOOST_CHECK_EQUAL(i, 30); + BOOST_CHECK_EQUAL(bf.GetPos(), 31); + + // We're too far to rewind to position zero. + BOOST_CHECK(!bf.SetPos(0)); + // But we should now be positioned at least as far back as allowed + // by the rewind window (relative to our farthest read position, 40). + BOOST_CHECK(bf.GetPos() <= 30); + + // We can explicitly close the file, or the destructor will do it. + bf.fclose(); + + fs::remove("streams_test_tmp"); +} + +BOOST_AUTO_TEST_CASE(streams_buffered_file_rand) +{ + // Make this test deterministic. + SeedInsecureRand(true); + + for (int rep = 0; rep < 50; ++rep) { + FILE* file = fsbridge::fopen("streams_test_tmp", "w+b"); + size_t fileSize = InsecureRandRange(256); + for (uint8_t i = 0; i < fileSize; ++i) { + fwrite(&i, 1, 1, file); + } + rewind(file); + + size_t bufSize = InsecureRandRange(300) + 1; + size_t rewindSize = InsecureRandRange(bufSize); + CBufferedFile bf(file, bufSize, rewindSize, 222, 333); + size_t currentPos = 0; + size_t maxPos = 0; + for (int step = 0; step < 100; ++step) { + if (currentPos >= fileSize) + break; + + // We haven't read to the end of the file yet. + BOOST_CHECK(!bf.eof()); + BOOST_CHECK_EQUAL(bf.GetPos(), currentPos); + + // Pretend the file consists of a series of objects of varying + // sizes; the boundaries of the objects can interact arbitrarily + // with the CBufferFile's internal buffer. These first three + // cases simulate objects of various sizes (1, 2, 5 bytes). + switch (InsecureRandRange(5)) { + case 0: { + uint8_t a[1]; + if (currentPos + 1 > fileSize) + continue; + bf.SetLimit(currentPos + 1); + bf >> a; + for (uint8_t i = 0; i < 1; ++i) { + BOOST_CHECK_EQUAL(a[i], currentPos); + currentPos++; + } + break; + } + case 1: { + uint8_t a[2]; + if (currentPos + 2 > fileSize) + continue; + bf.SetLimit(currentPos + 2); + bf >> a; + for (uint8_t i = 0; i < 2; ++i) { + BOOST_CHECK_EQUAL(a[i], currentPos); + currentPos++; + } + break; + } + case 2: { + uint8_t a[5]; + if (currentPos + 5 > fileSize) + continue; + bf.SetLimit(currentPos + 5); + bf >> a; + for (uint8_t i = 0; i < 5; ++i) { + BOOST_CHECK_EQUAL(a[i], currentPos); + currentPos++; + } + break; + } + case 3: { + // Find a byte value (that is at or ahead of the current position). + size_t find = currentPos + InsecureRandRange(8); + if (find >= fileSize) + find = fileSize - 1; + bf.FindByte(static_cast<char>(find)); + // The value at each offset is the offset. + BOOST_CHECK_EQUAL(bf.GetPos(), find); + currentPos = find; + + bf.SetLimit(currentPos + 1); + uint8_t i; + bf >> i; + BOOST_CHECK_EQUAL(i, currentPos); + currentPos++; + break; + } + case 4: { + size_t requestPos = InsecureRandRange(maxPos + 4); + bool okay = bf.SetPos(requestPos); + // The new position may differ from the requested position + // because we may not be able to rewind beyond the rewind + // window, and we may not be able to move forward beyond the + // farthest position we've reached so far. + currentPos = bf.GetPos(); + BOOST_CHECK_EQUAL(okay, currentPos == requestPos); + // Check that we can position within the rewind window. + if (requestPos <= maxPos && + maxPos > rewindSize && + requestPos >= maxPos - rewindSize) { + // We requested a position within the rewind window. + BOOST_CHECK(okay); + } + break; + } + } + if (maxPos < currentPos) + maxPos = currentPos; + } + } + fs::remove("streams_test_tmp"); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/validation.cpp b/src/validation.cpp index 4caee52424..1faaa411c4 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1821,7 +1821,8 @@ public: bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override { - return ((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && + return pindex->nHeight >= params.MinBIP9WarningHeight && + ((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && ((pindex->nVersion >> bit) & 1) != 0 && ((ComputeBlockVersion(pindex->pprev, params) >> bit) & 1) == 0; } @@ -3280,9 +3281,7 @@ bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& pa return (height >= params.SegwitHeight); } -// Compute at which vout of the block's coinbase transaction the witness -// commitment occurs, or -1 if not found. -static int GetWitnessCommitmentIndex(const CBlock& block) +int GetWitnessCommitmentIndex(const CBlock& block) { int commitpos = -1; if (!block.vtx.empty()) { diff --git a/src/validation.h b/src/validation.h index 615b83f028..96d249b6d3 100644 --- a/src/validation.h +++ b/src/validation.h @@ -384,6 +384,9 @@ bool IsWitnessEnabled(const CBlockIndex* pindexPrev, const Consensus::Params& pa /** When there are blocks in the active chain with missing data, rewind the chainstate and remove them from the block index */ bool RewindBlockIndex(const CChainParams& params) LOCKS_EXCLUDED(cs_main); +/** Compute at which vout of the block's coinbase transaction the witness commitment occurs, or -1 if not found */ +int GetWitnessCommitmentIndex(const CBlock& block); + /** Update uncommitted block structures (currently: only the witness reserved value). This is safe for submitted blocks. */ void UpdateUncommittedBlockStructures(CBlock& block, const CBlockIndex* pindexPrev, const Consensus::Params& consensusParams); diff --git a/test/README.md b/test/README.md index 8f08b7afe4..26fd525064 100644 --- a/test/README.md +++ b/test/README.md @@ -136,8 +136,10 @@ killall bitcoind ##### Test logging -The tests contain logging at different levels (debug, info, warning, etc). By -default: +The tests contain logging at five different levels (DEBUG, INFO, WARNING, ERROR +and CRITICAL). From within your functional tests you can log to these different +levels using the logger included in the test_framework, e.g. +`self.log.debug(object)`. By default: - when run through the test_runner harness, *all* logs are written to `test_framework.log` and no logs are output to the console. @@ -182,18 +184,32 @@ call methods that interact with the bitcoind nodes-under-test. If further introspection of the bitcoind instances themselves becomes necessary, this can be accomplished by first setting a pdb breakpoint at an appropriate location, running the test to that point, then using -`gdb` to attach to the process and debug. +`gdb` (or `lldb` on macOS) to attach to the process and debug. -For instance, to attach to `self.node[1]` during a run: +For instance, to attach to `self.node[1]` during a run you can get +the pid of the node within `pdb`. + +``` +(pdb) self.node[1].process.pid +``` + +Alternatively, you can find the pid by inspecting the temp folder for the specific test +you are running. The path to that folder is printed at the beginning of every +test run: ```bash 2017-06-27 14:13:56.686000 TestFramework (INFO): Initializing test directory /tmp/user/1000/testo9vsdjo3 ``` -use the directory path to get the pid from the pid file: +Use the path to find the pid file in the temp folder: ```bash cat /tmp/user/1000/testo9vsdjo3/node1/regtest/bitcoind.pid +``` + +Then you can use the pid to start `gdb`: + +```bash gdb /home/example/bitcoind <pid> ``` diff --git a/test/functional/README.md b/test/functional/README.md index 5e3009e6af..197c2afbe4 100644 --- a/test/functional/README.md +++ b/test/functional/README.md @@ -116,7 +116,7 @@ Basic code to support P2P connectivity to a bitcoind. Utilities for manipulating transaction scripts (originally from python-bitcoinlib) #### [test_framework/key.py](test_framework/key.py) -Wrapper around OpenSSL EC_Key (originally from python-bitcoinlib) +Test-only secp256k1 elliptic curve implementation #### [test_framework/bignum.py](test_framework/bignum.py) Helpers for script.py diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py index d2826dd1b7..c69c7f90e8 100755 --- a/test/functional/feature_segwit.py +++ b/test/functional/feature_segwit.py @@ -257,7 +257,7 @@ class SegWitTest(BitcoinTestFramework): tx.vin.append(CTxIn(COutPoint(int(txid2, 16), 0), b"")) tx.vout.append(CTxOut(int(49.95 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) # Huge fee tx.calc_sha256() - txid3 = self.nodes[0].sendrawtransaction(ToHex(tx), 0) + txid3 = self.nodes[0].sendrawtransaction(hexstring=ToHex(tx), maxfeerate=0) assert tx.wit.is_null() assert txid3 in self.nodes[0].getrawmempool() @@ -566,7 +566,7 @@ class SegWitTest(BitcoinTestFramework): tx.vout.append(CTxOut(10000000, i)) tx.rehash() signresults = self.nodes[0].signrawtransactionwithwallet(tx.serialize_without_witness().hex())['hex'] - txid = self.nodes[0].sendrawtransaction(signresults, 0) + txid = self.nodes[0].sendrawtransaction(hexstring=signresults, maxfeerate=0) txs_mined[txid] = self.nodes[0].generate(1)[0] self.sync_blocks() watchcount = 0 @@ -618,7 +618,7 @@ class SegWitTest(BitcoinTestFramework): tx.vout.append(CTxOut(0, CScript())) tx.rehash() signresults = self.nodes[0].signrawtransactionwithwallet(tx.serialize_without_witness().hex())['hex'] - self.nodes[0].sendrawtransaction(signresults, 0) + self.nodes[0].sendrawtransaction(hexstring=signresults, maxfeerate=0) self.nodes[0].generate(1) self.sync_blocks() diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index 266a0d6cd2..278ce6d911 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -134,7 +134,7 @@ class BlockchainTest(BitcoinTestFramework): 'bip9': { 'status': 'started', 'bit': 28, - 'startTime': 0, + 'start_time': 0, 'timeout': 0x7fffffffffffffff, # testdummy does not have a timeout so is set to the max int64 value 'since': 144, 'statistics': { diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py index eb98334988..ca0d47a5f8 100755 --- a/test/functional/rpc_rawtransaction.py +++ b/test/functional/rpc_rawtransaction.py @@ -438,48 +438,50 @@ class RawTransactionsTest(BitcoinTestFramework): self.log.info('sendrawtransaction/testmempoolaccept with maxfeerate') - # Test a transaction with small fee + # Test a transaction with a small fee. txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0) rawTx = self.nodes[0].getrawtransaction(txId, True) vout = next(o for o in rawTx['vout'] if o['value'] == Decimal('1.00000000')) self.sync_all() inputs = [{ "txid" : txId, "vout" : vout['n'] }] - outputs = { self.nodes[0].getnewaddress() : Decimal("0.999990000") } # 10000 sat fee + # Fee 10,000 satoshis, (1 - (10000 sat * 0.00000001 BTC/sat)) = 0.9999 + outputs = { self.nodes[0].getnewaddress() : Decimal("0.99990000") } rawTx = self.nodes[2].createrawtransaction(inputs, outputs) rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx) assert_equal(rawTxSigned['complete'], True) - # 10000 sat fee, ~100 b transaction, fee rate should land around 100 sat/b = 0.00100000 BTC/kB + # Fee 10,000 satoshis, ~100 b transaction, fee rate should land around 100 sat/byte = 0.00100000 BTC/kB # Thus, testmempoolaccept should reject testres = self.nodes[2].testmempoolaccept([rawTxSigned['hex']], 0.00001000)[0] assert_equal(testres['allowed'], False) assert_equal(testres['reject-reason'], '256: absurdly-high-fee') # and sendrawtransaction should throw assert_raises_rpc_error(-26, "absurdly-high-fee", self.nodes[2].sendrawtransaction, rawTxSigned['hex'], 0.00001000) - # And below calls should both succeed + # and the following calls should both succeed testres = self.nodes[2].testmempoolaccept(rawtxs=[rawTxSigned['hex']])[0] assert_equal(testres['allowed'], True) self.nodes[2].sendrawtransaction(hexstring=rawTxSigned['hex']) - # Test a transaction with large fee + # Test a transaction with a large fee. txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0) rawTx = self.nodes[0].getrawtransaction(txId, True) vout = next(o for o in rawTx['vout'] if o['value'] == Decimal('1.00000000')) self.sync_all() inputs = [{ "txid" : txId, "vout" : vout['n'] }] - outputs = { self.nodes[0].getnewaddress() : Decimal("0.98000000") } # 2000000 sat fee + # Fee 2,000,000 satoshis, (1 - (2000000 sat * 0.00000001 BTC/sat)) = 0.98 + outputs = { self.nodes[0].getnewaddress() : Decimal("0.98000000") } rawTx = self.nodes[2].createrawtransaction(inputs, outputs) rawTxSigned = self.nodes[2].signrawtransactionwithwallet(rawTx) assert_equal(rawTxSigned['complete'], True) - # 2000000 sat fee, ~100 b transaction, fee rate should land around 20000 sat/b = 0.20000000 BTC/kB + # Fee 2,000,000 satoshis, ~100 b transaction, fee rate should land around 20,000 sat/byte = 0.20000000 BTC/kB # Thus, testmempoolaccept should reject testres = self.nodes[2].testmempoolaccept([rawTxSigned['hex']])[0] assert_equal(testres['allowed'], False) assert_equal(testres['reject-reason'], '256: absurdly-high-fee') # and sendrawtransaction should throw assert_raises_rpc_error(-26, "absurdly-high-fee", self.nodes[2].sendrawtransaction, rawTxSigned['hex']) - # And below calls should both succeed + # and the following calls should both succeed testres = self.nodes[2].testmempoolaccept(rawtxs=[rawTxSigned['hex']], maxfeerate='0.20000000')[0] assert_equal(testres['allowed'], True) self.nodes[2].sendrawtransaction(hexstring=rawTxSigned['hex'], maxfeerate='0.20000000') diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 1c254b6755..598e87558b 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -7,13 +7,13 @@ from base64 import b64encode from binascii import unhexlify from decimal import Decimal, ROUND_DOWN +from subprocess import CalledProcessError import inspect import json import logging import os import random import re -from subprocess import CalledProcessError import time from . import coverage @@ -235,10 +235,11 @@ def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf'), lock=N # The maximum number of nodes a single test can spawn MAX_NODES = 12 # Don't assign rpc or p2p ports lower than this -PORT_MIN = 11000 +PORT_MIN = int(os.getenv('TEST_RUNNER_PORT_MIN', default=11000)) # The number of ports to "reserve" for p2p and rpc, each PORT_RANGE = 5000 + class PortSeed: # Must be initialized with a unique integer for each process n = None diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index 5b1c672a48..96ea5c9c35 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -169,8 +169,8 @@ class WalletTest(BitcoinTestFramework): txns_to_send.append(self.nodes[0].signrawtransactionwithwallet(raw_tx)) # Have node 1 (miner) send the transactions - self.nodes[1].sendrawtransaction(txns_to_send[0]["hex"], 0) - self.nodes[1].sendrawtransaction(txns_to_send[1]["hex"], 0) + self.nodes[1].sendrawtransaction(hexstring=txns_to_send[0]["hex"], maxfeerate=0) + self.nodes[1].sendrawtransaction(hexstring=txns_to_send[1]["hex"], maxfeerate=0) # Have node1 mine a block to confirm transactions: self.nodes[1].generate(1) @@ -433,7 +433,7 @@ class WalletTest(BitcoinTestFramework): # Split into two chains rawtx = self.nodes[0].createrawtransaction([{"txid": singletxid, "vout": 0}], {chain_addrs[0]: node0_balance / 2 - Decimal('0.01'), chain_addrs[1]: node0_balance / 2 - Decimal('0.01')}) signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx) - singletxid = self.nodes[0].sendrawtransaction(signedtx["hex"], 0) + singletxid = self.nodes[0].sendrawtransaction(hexstring=signedtx["hex"], maxfeerate=0) self.nodes[0].generate(1) # Make a long chain of unconfirmed payments without hitting mempool limit diff --git a/test/lint/lint-python-dead-code-whitelist b/test/lint/lint-python-dead-code-whitelist deleted file mode 100644 index 33bb7b44fa..0000000000 --- a/test/lint/lint-python-dead-code-whitelist +++ /dev/null @@ -1,46 +0,0 @@ -BadInputOutpointIndex # unused class (test/functional/data/invalid_txs.py) -_.carbon_path # unused attribute (contrib/macdeploy/custom_dsstore.py) -connection_lost # unused function (test/functional/test_framework/mininode.py) -connection_made # unused function (test/functional/test_framework/mininode.py) -_.converter # unused attribute (test/functional/test_framework/test_framework.py) -_.daemon # unused attribute (test/functional/test_framework/socks5.py) -data_received # unused function (test/functional/test_framework/mininode.py) -DuplicateInput # unused class (test/functional/data/invalid_txs.py) -DisabledOpcodeTemplates # unused class (test/functional/data/invalid_txs.py) -_.filename # unused attribute (contrib/macdeploy/custom_dsstore.py) -InvalidOPIFConstruction # unused class (test/functional/data/invalid_txs.py) -_.is_compressed # unused property (test/functional/test_framework/key.py) -legacy # unused variable (test/functional/test_framework/address.py) -msg_generic # unused class (test/functional/test_framework/messages.py) -NonexistentInput # unused class (test/functional/data/invalid_txs.py) -on_addr # unused function (test/functional/test_framework/mininode.py) -on_blocktxn # unused function (test/functional/test_framework/mininode.py) -on_block # unused function (test/functional/test_framework/mininode.py) -on_cmpctblock # unused function (test/functional/test_framework/mininode.py) -on_feefilter # unused function (test/functional/test_framework/mininode.py) -on_getaddr # unused function (test/functional/test_framework/mininode.py) -on_getblocks # unused function (test/functional/test_framework/mininode.py) -on_getblocktxn # unused function (test/functional/test_framework/mininode.py) -on_getdata # unused function (test/functional/test_framework/mininode.py) -on_getheaders # unused function (test/functional/test_framework/mininode.py) -on_headers # unused function (test/functional/test_framework/mininode.py) -on_inv # unused function (test/functional/test_framework/mininode.py) -on_mempool # unused function (test/functional/test_framework/mininode.py) -on_notfound # unused function (test/functional/test_framework/mininode.py) -on_ping # unused function (test/functional/test_framework/mininode.py) -on_pong # unused function (test/functional/test_framework/mininode.py) -on_reject # unused function (test/functional/test_framework/mininode.py) -on_sendcmpct # unused function (test/functional/test_framework/mininode.py) -on_sendheaders # unused function (test/functional/test_framework/mininode.py) -on_tx # unused function (test/functional/test_framework/mininode.py) -on_verack # unused function (test/functional/test_framework/mininode.py) -on_version # unused function (test/functional/test_framework/mininode.py) -_.optionxform # unused attribute (test/util/bitcoin-util-test.py) -OutputMissing # unused class (test/functional/data/invalid_txs.py) -_.posix_path # unused attribute (contrib/macdeploy/custom_dsstore.py) -profile_with_perf # unused function (test/functional/test_framework/test_node.py) -SizeTooSmall # unused class (test/functional/data/invalid_txs.py) -SpendNegative # unused class (test/functional/data/invalid_txs.py) -SpendTooMuch # unused class (test/functional/data/invalid_txs.py) -TooManySigops # unused class (test/functional/data/invalid_txs.py) -verify_ecdsa # unused function (test/functional/test_framework/key.py) diff --git a/test/lint/lint-python-dead-code.sh b/test/lint/lint-python-dead-code.sh deleted file mode 100755 index af37d393e8..0000000000 --- a/test/lint/lint-python-dead-code.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) 2018 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -# -# Find dead Python code. - -export LC_ALL=C - -if ! command -v vulture > /dev/null; then - echo "Skipping Python dead code linting since vulture is not installed. Install by running \"pip3 install vulture\"" - exit 0 -fi - -VULTURE_SUPPRESSIONS=$(dirname "${BASH_SOURCE[0]}")/lint-python-dead-code-whitelist -if ! vulture \ - --min-confidence 60 \ - $(git rev-parse --show-toplevel) \ - "${VULTURE_SUPPRESSIONS}"; then - echo "False positives? Suppressions can be added to ${VULTURE_SUPPRESSIONS}" - exit 1 -fi |