diff options
137 files changed, 721 insertions, 645 deletions
diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..4044722374 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,27 @@ +# Security Policy + +## Supported Versions + +Versions of Bitcoin Core that are currently supported with security updates: + +| Version | Supported | +| ------- | ------------------ | +| 0.18 | :white_check_mark: | +| 0.17 | :white_check_mark: | +| 0.16 | :white_check_mark: | +| 0.15 | :white_check_mark: | +| < 0.15 | :x: | + +## Reporting a Vulnerability + +To report security issues send an email to security@bitcoincore.org (not for support). + +The following keys may be used to communicate sensitive information to developers: + +| Name | Fingerprint | +|------|-------------| +| Wladimir van der Laan | 71A3 B167 3540 5025 D447 E8F2 7481 0B01 2346 C9A6 | +| Jonas Schnelli | 32EE 5C4C 3FA1 5CCA DB46 ABE5 29D4 BCB6 416F 53EC | +| Pieter Wuille | 133E AC17 9436 F14A 5CF1 B794 860F EB80 4E66 9320 | + +You can import a key by running the following command with that individual’s fingerprint: `gpg --recv-keys "<fingerprint>"` Ensure that you put quotes around fingerprints containing spaces. diff --git a/build-aux/m4/ax_boost_base.m4 b/build-aux/m4/ax_boost_base.m4 index 650c94fa64..d540395763 100644 --- a/build-aux/m4/ax_boost_base.m4 +++ b/build-aux/m4/ax_boost_base.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_base.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_base.html # =========================================================================== # # SYNOPSIS @@ -33,7 +33,15 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 27 +#serial 45 + +# example boost program (need to pass version) +m4_define([_AX_BOOST_BASE_PROGRAM], + [AC_LANG_PROGRAM([[ +#include <boost/version.hpp> +]],[[ +(void) ((void)sizeof(char[1 - 2*!!((BOOST_VERSION) < ($1))])); +]])]) AC_DEFUN([AX_BOOST_BASE], [ @@ -44,110 +52,121 @@ AC_ARG_WITH([boost], or disable it (ARG=no) @<:@ARG=yes@:>@ ])], [ - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then - want_boost="yes" - ac_boost_path="" - else - want_boost="yes" - ac_boost_path="$withval" - fi + AS_CASE([$withval], + [no],[want_boost="no";_AX_BOOST_BASE_boost_path=""], + [yes],[want_boost="yes";_AX_BOOST_BASE_boost_path=""], + [want_boost="yes";_AX_BOOST_BASE_boost_path="$withval"]) ], [want_boost="yes"]) AC_ARG_WITH([boost-libdir], - AS_HELP_STRING([--with-boost-libdir=LIB_DIR], - [Force given directory for boost libraries. Note that this will override library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]), - [ - if test -d "$withval" - then - ac_boost_lib_path="$withval" - else - AC_MSG_ERROR(--with-boost-libdir expected directory name) - fi - ], - [ac_boost_lib_path=""] -) + [AS_HELP_STRING([--with-boost-libdir=LIB_DIR], + [Force given directory for boost libraries. + Note that this will override library path detection, + so use this parameter only if default library detection fails + and you know exactly where your boost libraries are located.])], + [ + AS_IF([test -d "$withval"], + [_AX_BOOST_BASE_boost_lib_path="$withval"], + [AC_MSG_ERROR([--with-boost-libdir expected directory name])]) + ], + [_AX_BOOST_BASE_boost_lib_path=""]) -if test "x$want_boost" = "xyes"; then - boost_lib_version_req=ifelse([$1], ,1.20.0,$1) - boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'` - boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'` - boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'` - boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` - if test "x$boost_lib_version_req_sub_minor" = "x" ; then - boost_lib_version_req_sub_minor="0" - fi - WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor` - AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req) +BOOST_LDFLAGS="" +BOOST_CPPFLAGS="" +AS_IF([test "x$want_boost" = "xyes"], + [_AX_BOOST_BASE_RUNDETECT([$1],[$2],[$3])]) +AC_SUBST(BOOST_CPPFLAGS) +AC_SUBST(BOOST_LDFLAGS) +]) + + +# convert a version string in $2 to numeric and affect to polymorphic var $1 +AC_DEFUN([_AX_BOOST_BASE_TONUMERICVERSION],[ + AS_IF([test "x$2" = "x"],[_AX_BOOST_BASE_TONUMERICVERSION_req="1.20.0"],[_AX_BOOST_BASE_TONUMERICVERSION_req="$2"]) + _AX_BOOST_BASE_TONUMERICVERSION_req_shorten=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([[0-9]]*\.[[0-9]]*\)'` + _AX_BOOST_BASE_TONUMERICVERSION_req_major=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([[0-9]]*\)'` + AS_IF([test "x$_AX_BOOST_BASE_TONUMERICVERSION_req_major" = "x"], + [AC_MSG_ERROR([You should at least specify libboost major version])]) + _AX_BOOST_BASE_TONUMERICVERSION_req_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\.\([[0-9]]*\)'` + AS_IF([test "x$_AX_BOOST_BASE_TONUMERICVERSION_req_minor" = "x"], + [_AX_BOOST_BASE_TONUMERICVERSION_req_minor="0"]) + _AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` + AS_IF([test "X$_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor" = "X"], + [_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor="0"]) + _AX_BOOST_BASE_TONUMERICVERSION_RET=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req_major \* 100000 \+ $_AX_BOOST_BASE_TONUMERICVERSION_req_minor \* 100 \+ $_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor` + AS_VAR_SET($1,$_AX_BOOST_BASE_TONUMERICVERSION_RET) +]) + +dnl Run the detection of boost should be run only if $want_boost +AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[ + _AX_BOOST_BASE_TONUMERICVERSION(WANT_BOOST_VERSION,[$1]) succeeded=no + + AC_REQUIRE([AC_CANONICAL_HOST]) dnl On 64-bit systems check for system libraries in both lib64 and lib. dnl The former is specified by FHS, but e.g. Debian does not adhere to dnl this (as it rises problems for generic multi-arch support). dnl The last entry in the list is chosen by default when no libraries dnl are found, e.g. when only header-only libraries are installed! - libsubdirs="lib" - ax_arch=`uname -m` - case $ax_arch in - x86_64) - libsubdirs="lib64 libx32 lib lib64" - ;; - ppc64|s390x|sparc64|aarch64|ppc64le) - libsubdirs="lib64 lib lib64" - ;; - esac + AS_CASE([${host_cpu}], + [x86_64],[libsubdirs="lib64 libx32 lib lib64"], + [ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64],[libsubdirs="lib64 lib lib64"], + [libsubdirs="lib"] + ) dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give dnl them priority over the other paths since, if libs are found there, they dnl are almost assuredly the ones desired. - AC_REQUIRE([AC_CANONICAL_HOST]) - libsubdirs="lib/${host_cpu}-${host_os} $libsubdirs" - - case ${host_cpu} in - i?86) - libsubdirs="lib/i386-${host_os} $libsubdirs" - ;; - esac - - dnl some arches may advertise a cpu type that doesn't line up with their - dnl prefix's cpu type. For example, uname may report armv7l while libs are - dnl installed to /usr/lib/arm-linux-gnueabihf. Try getting the compiler's - dnl value for an extra chance of finding the correct path. - libsubdirs="lib/`$CXX -dumpmachine 2>/dev/null` $libsubdirs" + AS_CASE([${host_cpu}], + [i?86],[multiarch_libsubdir="lib/i386-${host_os}"], + [multiarch_libsubdir="lib/${host_cpu}-${host_os}"] + ) dnl first we check the system location for boost libraries dnl this location ist chosen if boost libraries are installed with the --layout=system option dnl or if you install boost with RPM - if test "$ac_boost_path" != ""; then - BOOST_CPPFLAGS="-I$ac_boost_path/include" - for ac_boost_path_tmp in $libsubdirs; do - if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then - BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp" - break - fi - done - elif test "$cross_compiling" != yes; then - for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do - if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then - for libsubdir in $libsubdirs ; do - if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi + AS_IF([test "x$_AX_BOOST_BASE_boost_path" != "x"],[ + AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) includes in "$_AX_BOOST_BASE_boost_path/include"]) + AS_IF([test -d "$_AX_BOOST_BASE_boost_path/include" && test -r "$_AX_BOOST_BASE_boost_path/include"],[ + AC_MSG_RESULT([yes]) + BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path/include" + for _AX_BOOST_BASE_boost_path_tmp in $multiarch_libsubdir $libsubdirs; do + AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) lib path in "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp"]) + AS_IF([test -d "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp" && test -r "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp" ],[ + AC_MSG_RESULT([yes]) + BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp"; + break; + ], + [AC_MSG_RESULT([no])]) + done],[ + AC_MSG_RESULT([no])]) + ],[ + if test X"$cross_compiling" = Xyes; then + search_libsubdirs=$multiarch_libsubdir + else + search_libsubdirs="$multiarch_libsubdir $libsubdirs" + fi + for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local ; do + if test -d "$_AX_BOOST_BASE_boost_path_tmp/include/boost" && test -r "$_AX_BOOST_BASE_boost_path_tmp/include/boost" ; then + for libsubdir in $search_libsubdirs ; do + if ls "$_AX_BOOST_BASE_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi done - BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir" - BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include" + BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path_tmp/$libsubdir" + BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path_tmp/include" break; fi done - fi + ]) dnl overwrite ld flags if we have required special directory with dnl --with-boost-libdir parameter - if test "$ac_boost_lib_path" != ""; then - BOOST_LDFLAGS="-L$ac_boost_lib_path" - fi + AS_IF([test "x$_AX_BOOST_BASE_boost_lib_path" != "x"], + [BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_lib_path"]) + AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION)]) CPPFLAGS_SAVED="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" export CPPFLAGS @@ -158,15 +177,7 @@ if test "x$want_boost" = "xyes"; then AC_REQUIRE([AC_PROG_CXX]) AC_LANG_PUSH(C++) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - @%:@include <boost/version.hpp> - ]], [[ - #if BOOST_VERSION >= $WANT_BOOST_VERSION - // Everything is okay - #else - # error Boost version is too old - #endif - ]])],[ + AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[ AC_MSG_RESULT(yes) succeeded=yes found_system=yes @@ -178,40 +189,50 @@ if test "x$want_boost" = "xyes"; then dnl if we found no boost with system layout we search for boost libraries dnl built and installed without the --layout=system option or for a staged(not installed) version - if test "x$succeeded" != "xyes"; then + if test "x$succeeded" != "xyes" ; then CPPFLAGS="$CPPFLAGS_SAVED" LDFLAGS="$LDFLAGS_SAVED" BOOST_CPPFLAGS= - BOOST_LDFLAGS= + if test -z "$_AX_BOOST_BASE_boost_lib_path" ; then + BOOST_LDFLAGS= + fi _version=0 - if test "$ac_boost_path" != ""; then - if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then - for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do - _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` + if test -n "$_AX_BOOST_BASE_boost_path" ; then + if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path"; then + for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do + _version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` V_CHECK=`expr $_version_tmp \> $_version` - if test "$V_CHECK" = "1" ; then + if test "x$V_CHECK" = "x1" ; then _version=$_version_tmp fi VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` - BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" + BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path/include/boost-$VERSION_UNDERSCORE" done dnl if nothing found search for layout used in Windows distributions if test -z "$BOOST_CPPFLAGS"; then - if test -d "$ac_boost_path/boost" && test -r "$ac_boost_path/boost"; then - BOOST_CPPFLAGS="-I$ac_boost_path" + if test -d "$_AX_BOOST_BASE_boost_path/boost" && test -r "$_AX_BOOST_BASE_boost_path/boost"; then + BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path" fi fi + dnl if we found something and BOOST_LDFLAGS was unset before + dnl (because "$_AX_BOOST_BASE_boost_lib_path" = ""), set it here. + if test -n "$BOOST_CPPFLAGS" && test -z "$BOOST_LDFLAGS"; then + for libsubdir in $libsubdirs ; do + if ls "$_AX_BOOST_BASE_boost_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi + done + BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path/$libsubdir" + fi fi else - if test "$cross_compiling" != yes; then - for ac_boost_path in /usr /usr/local /opt /opt/local ; do - if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then - for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do - _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` + if test "x$cross_compiling" != "xyes" ; then + for _AX_BOOST_BASE_boost_path in /usr /usr/local /opt /opt/local ; do + if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path" ; then + for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do + _version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` V_CHECK=`expr $_version_tmp \> $_version` - if test "$V_CHECK" = "1" ; then + if test "x$V_CHECK" = "x1" ; then _version=$_version_tmp - best_path=$ac_boost_path + best_path=$_AX_BOOST_BASE_boost_path fi done fi @@ -219,7 +240,7 @@ if test "x$want_boost" = "xyes"; then VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE" - if test "$ac_boost_lib_path" = ""; then + if test -z "$_AX_BOOST_BASE_boost_lib_path" ; then for libsubdir in $libsubdirs ; do if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi done @@ -227,7 +248,7 @@ if test "x$want_boost" = "xyes"; then fi fi - if test "x$BOOST_ROOT" != "x"; then + if test -n "$BOOST_ROOT" ; then for libsubdir in $libsubdirs ; do if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi done @@ -236,7 +257,7 @@ if test "x$want_boost" = "xyes"; then stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'` stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'` V_CHECK=`expr $stage_version_shorten \>\= $_version` - if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then + if test "x$V_CHECK" = "x1" && test -z "$_AX_BOOST_BASE_boost_lib_path" ; then AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT) BOOST_CPPFLAGS="-I$BOOST_ROOT" BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir" @@ -251,15 +272,7 @@ if test "x$want_boost" = "xyes"; then export LDFLAGS AC_LANG_PUSH(C++) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - @%:@include <boost/version.hpp> - ]], [[ - #if BOOST_VERSION >= $WANT_BOOST_VERSION - // Everything is okay - #else - # error Boost version is too old - #endif - ]])],[ + AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[ AC_MSG_RESULT(yes) succeeded=yes found_system=yes @@ -268,17 +281,15 @@ if test "x$want_boost" = "xyes"; then AC_LANG_POP([C++]) fi - if test "$succeeded" != "yes" ; then - if test "$_version" = "0" ; then - AC_MSG_NOTICE([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.]]) + if test "x$succeeded" != "xyes" ; then + if test "x$_version" = "x0" ; then + AC_MSG_NOTICE([[We could not detect the boost libraries (version $1 or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.]]) else AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).]) fi # execute ACTION-IF-NOT-FOUND (if present): ifelse([$3], , :, [$3]) else - AC_SUBST(BOOST_CPPFLAGS) - AC_SUBST(BOOST_LDFLAGS) AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available]) # execute ACTION-IF-FOUND (if present): ifelse([$2], , :, [$2]) @@ -286,6 +297,5 @@ if test "x$want_boost" = "xyes"; then CPPFLAGS="$CPPFLAGS_SAVED" LDFLAGS="$LDFLAGS_SAVED" -fi ]) diff --git a/build-aux/m4/ax_boost_system.m4 b/build-aux/m4/ax_boost_system.m4 index 1c05450cbe..207d7be8de 100644 --- a/build-aux/m4/ax_boost_system.m4 +++ b/build-aux/m4/ax_boost_system.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_system.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_system.html # =========================================================================== # # SYNOPSIS @@ -31,7 +31,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 18 +#serial 19 AC_DEFUN([AX_BOOST_SYSTEM], [ @@ -84,7 +84,6 @@ AC_DEFUN([AX_BOOST_SYSTEM], LDFLAGS_SAVE=$LDFLAGS if test "x$ax_boost_user_system_lib" = "x"; then - ax_lib= for libextension in `ls -r $BOOSTLIBDIR/libboost_system* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do ax_lib=${libextension} AC_CHECK_LIB($ax_lib, exit, @@ -109,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 boost_system library!) + AC_MSG_ERROR(Could not find a version of the library!) fi if test "x$link_system" = "xno"; then AC_MSG_ERROR(Could not link against $ax_lib !) diff --git a/contrib/devtools/github-merge.py b/contrib/devtools/github-merge.py index a57ecf9818..df1f3c8024 100755 --- a/contrib/devtools/github-merge.py +++ b/contrib/devtools/github-merge.py @@ -283,7 +283,7 @@ def main(): message += '\n\nPull request description:\n\n ' + body.replace('\n', '\n ') + '\n' message += get_acks_from_comments(head_commit=subprocess.check_output([GIT,'log','-1','--pretty=format:%H',head_branch]).decode('utf-8')[:6], comments=comments) try: - subprocess.check_call([GIT,'merge','-q','--commit','--no-edit','--no-ff','-m',message.encode('utf-8'),head_branch]) + subprocess.check_call([GIT,'merge','-q','--commit','--no-edit','--no-ff','--no-gpg-sign','-m',message.encode('utf-8'),head_branch]) except subprocess.CalledProcessError: print("ERROR: Cannot be merged cleanly.",file=stderr) subprocess.check_call([GIT,'merge','--abort']) @@ -307,7 +307,7 @@ def main(): print("ERROR: Unable to compute tree hash") sys.exit(4) try: - subprocess.check_call([GIT,'commit','--amend','-m',message.encode('utf-8')]) + subprocess.check_call([GIT,'commit','--amend','--no-gpg-sign','-m',message.encode('utf-8')]) except subprocess.CalledProcessError: print("ERROR: Cannot update message.", file=stderr) sys.exit(4) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 5845d8fd89..4f2238abdb 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -50,8 +50,6 @@ script: | export QT_RCC_TEST=1 export QT_RCC_SOURCE_DATE_OVERRIDE=1 - export GZIP="-9n" - export TAR_OPTIONS="--mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" export TZ="UTC" export BUILD_DIR=`pwd` mkdir -p ${WRAP_DIR} @@ -150,8 +148,8 @@ script: | # Correct tar file order mkdir -p temp pushd temp - tar xf ../$SOURCEDIST - find bitcoin-* | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ../$SOURCEDIST + tar -xf ../$SOURCEDIST + find bitcoin-* | sort | tar --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ../$SOURCEDIST popd # Workaround for tarball not building with the bare tag version (prep) @@ -184,8 +182,8 @@ script: | 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}/ - find ${DISTNAME} -not -name "*.dbg" | sort | tar --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 --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}-debug.tar.gz + find ${DISTNAME} -not -name "*.dbg" | sort | tar --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME" --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_DATE\\\ $REFERENCE_TIME" --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 ../../ rm -rf distsrc-${i} done diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 24292d089a..866d233f0f 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -44,8 +44,6 @@ script: | export QT_RCC_TEST=1 export QT_RCC_SOURCE_DATE_OVERRIDE=1 - export GZIP="-9n" - export TAR_OPTIONS="--mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" export TZ="UTC" export BUILD_DIR=`pwd` mkdir -p ${WRAP_DIR} @@ -114,8 +112,8 @@ script: | # Correct tar file order mkdir -p temp pushd temp - tar xf ../$SOURCEDIST - find bitcoin-* | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ../$SOURCEDIST + tar -xf ../$SOURCEDIST + find bitcoin-* | sort | tar --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ../$SOURCEDIST popd # Workaround for tarball not building with the bare tag version (prep) @@ -152,7 +150,7 @@ script: | cp ${BASEPREFIX}/${i}/native/bin/${i}-pagestuff unsigned-app-${i}/pagestuff mv dist unsigned-app-${i} pushd unsigned-app-${i} - find . | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-osx-unsigned.tar.gz + find . | sort | tar --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-osx-unsigned.tar.gz popd make deploy @@ -162,7 +160,7 @@ script: | find . -name "lib*.la" -delete find . -name "lib*.a" -delete rm -rf ${DISTNAME}/lib/pkgconfig - find ${DISTNAME} | sort | tar --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} | sort | tar --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME" --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}.tar.gz cd ../../ done mkdir -p $OUTDIR/src diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index c055109715..58ba1ddad5 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -40,8 +40,6 @@ script: | export QT_RCC_TEST=1 export QT_RCC_SOURCE_DATE_OVERRIDE=1 - export GZIP="-9n" - export TAR_OPTIONS="--mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" export TZ="UTC" export BUILD_DIR=`pwd` mkdir -p ${WRAP_DIR} @@ -130,8 +128,8 @@ script: | # Correct tar file order mkdir -p temp pushd temp - tar xf ../$SOURCEDIST - find bitcoin-* | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ../$SOURCEDIST + tar -xf ../$SOURCEDIST + find bitcoin-* | sort | tar --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME" --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 @@ -177,6 +175,6 @@ script: | cd $BUILD_DIR/windeploy mkdir unsigned cp $OUTDIR/bitcoin-*setup-unsigned.exe unsigned/ - find . | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-win-unsigned.tar.gz + find . | sort | tar --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME" --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/verify-commits/trusted-keys b/contrib/verify-commits/trusted-keys index a10da9d822..27fede6277 100644 --- a/contrib/verify-commits/trusted-keys +++ b/contrib/verify-commits/trusted-keys @@ -3,3 +3,4 @@ 32EE5C4C3FA15CCADB46ABE529D4BCB6416F53EC B8B3F1C0E58C15DB6A81D30C3648A882F4316B9B CA03882CB1FC067B5D3ACFE4D300116E1C875A3D +E777299FC265DD04793070EB944D35F9AC3DB76A diff --git a/depends/packages.md b/depends/packages.md index 7d2bd4670d..2c592885b6 100644 --- a/depends/packages.md +++ b/depends/packages.md @@ -5,6 +5,10 @@ The package "mylib" will be used here as an example General tips: - mylib_foo is written as $(package)_foo in order to make recipes more similar. +- Secondary dependency packages relative to the bitcoin binaries/libraries (i.e. + those not in `ALLOWED_LIBRARIES` in `contrib/devtools/symbol-check.py`) don't + need to be shared and should be built statically whenever possible. See + [below](#secondary-dependencies) for more details. ## Identifiers Each package is required to define at least these variables: @@ -146,3 +150,34 @@ $($(package)_config_opts) will be appended. Most autotools projects can be properly staged using: $(MAKE) DESTDIR=$($(package)_staging_dir) install + +## Build outputs: + +In general, the output of a depends package should not contain any libtool +archives. Instead, the package should output `.pc` (`pkg-config`) files where +possible. + +From the [Gentoo Wiki entry](https://wiki.gentoo.org/wiki/Project:Quality_Assurance/Handling_Libtool_Archives): + +> Libtool pulls in all direct and indirect dependencies into the .la files it +> creates. This leads to massive overlinking, which is toxic to the Gentoo +> ecosystem, as it leads to a massive number of unnecessary rebuilds. + +## Secondary dependencies: + +Secondary dependency packages relative to the bitcoin binaries/libraries (i.e. +those not in `ALLOWED_LIBRARIES` in `contrib/devtools/symbol-check.py`) don't +need to be shared and should be built statically whenever possible. This +improves general build reliability as illustrated by the following example: + +When linking an executable against a shared library `libprimary` that has its +own shared dependency `libsecondary`, we may need to specify the path to +`libsecondary` on the link command using the `-rpath/-rpath-link` options, it is +not sufficient to just say `libprimary`. + +For us, it's much easier to just link a static `libsecondary` into a shared +`libprimary`. Especially because in our case, we are linking against a dummy +`libprimary` anyway that we'll throw away. We don't care if the end-user has a +static or dynamic `libseconday`, that's not our concern. With a static +`libseconday`, when we need to link `libprimary` into our executable, there's no +dependency chain to worry about as `libprimary` has all the symbols. diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 61806c7509..5df49b2af8 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -1,8 +1,8 @@ package=boost -$(package)_version=1_64_0 -$(package)_download_path=https://dl.bintray.com/boostorg/release/1.64.0/source/ +$(package)_version=1_70_0 +$(package)_download_path=https://dl.bintray.com/boostorg/release/1.70.0/source/ $(package)_file_name=$(package)_$($(package)_version).tar.bz2 -$(package)_sha256_hash=7bcc5caace97baa948931d712ea5f37038dbb1c5d89b43ad4def4ed7cb683332 +$(package)_sha256_hash=430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778 define $(package)_set_vars $(package)_config_opts_release=variant=release diff --git a/depends/packages/dbus.mk b/depends/packages/dbus.mk index bbe0375409..ad10b0fdd7 100644 --- a/depends/packages/dbus.mk +++ b/depends/packages/dbus.mk @@ -6,7 +6,7 @@ $(package)_sha256_hash=6049ddd5f3f3e2618f615f1faeda0a115104423a7996b7aa73e2f36e3 $(package)_dependencies=expat define $(package)_set_vars - $(package)_config_opts=--disable-tests --disable-doxygen-docs --disable-xml-docs --disable-static --without-x + $(package)_config_opts=--disable-tests --disable-doxygen-docs --disable-xml-docs --disable-shared --without-x endef define $(package)_config_cmds @@ -21,3 +21,7 @@ define $(package)_stage_cmds $(MAKE) -C dbus DESTDIR=$($(package)_staging_dir) install-libLTLIBRARIES install-dbusincludeHEADERS install-nodist_dbusarchincludeHEADERS && \ $(MAKE) DESTDIR=$($(package)_staging_dir) install-pkgconfigDATA endef + +define $(package)_postprocess_cmds + rm lib/*.la +endef diff --git a/depends/packages/expat.mk b/depends/packages/expat.mk index 8d06882cdb..b811f84a38 100644 --- a/depends/packages/expat.mk +++ b/depends/packages/expat.mk @@ -5,7 +5,8 @@ $(package)_file_name=$(package)-$($(package)_version).tar.bz2 $(package)_sha256_hash=17b43c2716d521369f82fc2dc70f359860e90fa440bea65b3b85f0b246ea81f2 define $(package)_set_vars -$(package)_config_opts=--disable-static --without-docbook + $(package)_config_opts=--disable-shared --without-docbook + $(package)_config_opts_linux=--with-pic endef define $(package)_config_cmds @@ -19,3 +20,7 @@ endef define $(package)_stage_cmds $(MAKE) DESTDIR=$($(package)_staging_dir) install endef + +define $(package)_postprocess_cmds + rm lib/*.la +endef diff --git a/depends/packages/fontconfig.mk b/depends/packages/fontconfig.mk index d0996b4534..293631739d 100644 --- a/depends/packages/fontconfig.mk +++ b/depends/packages/fontconfig.mk @@ -26,3 +26,7 @@ endef define $(package)_stage_cmds $(MAKE) DESTDIR=$($(package)_staging_dir) install endef + +define $(package)_postprocess_cmds + rm lib/*.la +endef diff --git a/depends/packages/freetype.mk b/depends/packages/freetype.mk index a98e82ed16..f24fc69d81 100644 --- a/depends/packages/freetype.mk +++ b/depends/packages/freetype.mk @@ -20,3 +20,7 @@ endef define $(package)_stage_cmds $(MAKE) DESTDIR=$($(package)_staging_dir) install endef + +define $(package)_postprocess_cmds + rm lib/*.la +endef diff --git a/depends/packages/libX11.mk b/depends/packages/libX11.mk index a013da5192..f46bd9219e 100644 --- a/depends/packages/libX11.mk +++ b/depends/packages/libX11.mk @@ -6,8 +6,9 @@ $(package)_sha256_hash=2aa027e837231d2eeea90f3a4afe19948a6eb4c8b2bec0241eba7dbc8 $(package)_dependencies=libxcb xtrans xextproto xproto define $(package)_set_vars -$(package)_config_opts=--disable-xkb --disable-static -$(package)_config_opts_linux=--with-pic + # See libXext for --disable-malloc0returnsnull rationale. + $(package)_config_opts=--disable-xkb --disable-static --disable-malloc0returnsnull + $(package)_config_opts_linux=--with-pic endef define $(package)_preprocess_cmds @@ -25,3 +26,7 @@ endef define $(package)_stage_cmds $(MAKE) DESTDIR=$($(package)_staging_dir) install endef + +define $(package)_postprocess_cmds + rm lib/*.la +endef diff --git a/depends/packages/libXau.mk b/depends/packages/libXau.mk index ce42140689..0e4a60ad25 100644 --- a/depends/packages/libXau.mk +++ b/depends/packages/libXau.mk @@ -25,3 +25,7 @@ endef define $(package)_stage_cmds $(MAKE) DESTDIR=$($(package)_staging_dir) install endef + +define $(package)_postprocess_cmds + rm lib/*.la +endef diff --git a/depends/packages/libXext.mk b/depends/packages/libXext.mk index 458b967784..77f32a340e 100644 --- a/depends/packages/libXext.mk +++ b/depends/packages/libXext.mk @@ -1,12 +1,35 @@ package=libXext -$(package)_version=1.3.2 +$(package)_version=1.3.3 $(package)_download_path=https://xorg.freedesktop.org/releases/individual/lib/ $(package)_file_name=$(package)-$($(package)_version).tar.bz2 -$(package)_sha256_hash=f829075bc646cdc085fa25d98d5885d83b1759ceb355933127c257e8e50432e0 +$(package)_sha256_hash=b518d4d332231f313371fdefac59e3776f4f0823bcb23cf7c7305bfb57b16e35 $(package)_dependencies=xproto xextproto libX11 libXau define $(package)_set_vars - $(package)_config_opts=--disable-static + # A number of steps in the autoconfig process implicitly assume that the build + # system and the host system are the same. For example, library components + # want to build and run test programs to determine the behavior of certain + # host system elements. This is clearly impossible when crosscompiling. To + # work around these issues, the --enable-malloc0returnsnull (or + # --disable-malloc0returnsnull, depending on the host system) must be passed + # to configure. + # -- https://www.x.org/wiki/CrossCompilingXorg/ + # + # Concretely, between the releases of libXext 1.3.2 and 1.3.3, + # XORG_CHECK_MALLOC_ZERO from xorg-macros was changed to use the autoconf + # cache, expecting cross-compilation environments to seed this cache as there + # is no single correct value when cross compiling (think uclibc, musl, etc.). + # You can see the actual change in commit 72fdc868b56fe2b7bdc9a69872651baeca72 + # in the freedesktop/xorg-macros repo. + # + # As a result of this change, if we don't seed the cache and we don't use + # either --{en,dis}able-malloc0returnsnull, the AC_RUN_IFELSE block has no + # optional action-if-cross-compiling argument and configure prints an error + # message and exits as documented in the autoconf manual. Prior to this + # commit, the AC_RUN_IFELSE block had an action-if-cross-compiling argument + # which set the more pessimistic default value MALLOC_ZERO_RETURNS_NULL=yes. + # This is why the flag was not required prior to libXext 1.3.3. + $(package)_config_opts=--disable-static --disable-malloc0returnsnull endef define $(package)_preprocess_cmds @@ -24,3 +47,7 @@ endef define $(package)_stage_cmds $(MAKE) DESTDIR=$($(package)_staging_dir) install endef + +define $(package)_postprocess_cmds + rm lib/*.la +endef diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk index 5f622f8e6e..a3ade899b7 100644 --- a/depends/packages/libevent.mk +++ b/depends/packages/libevent.mk @@ -27,4 +27,5 @@ define $(package)_stage_cmds endef define $(package)_postprocess_cmds + rm lib/*.la endef diff --git a/depends/packages/libxcb.mk b/depends/packages/libxcb.mk index 3ddd5a7dd9..9402951826 100644 --- a/depends/packages/libxcb.mk +++ b/depends/packages/libxcb.mk @@ -32,5 +32,5 @@ define $(package)_stage_cmds endef define $(package)_postprocess_cmds - rm -rf share/man share/doc + rm -rf share/man share/doc lib/*.la endef diff --git a/depends/packages/protobuf.mk b/depends/packages/protobuf.mk index d201d1183f..52975b14ec 100644 --- a/depends/packages/protobuf.mk +++ b/depends/packages/protobuf.mk @@ -30,5 +30,5 @@ define $(package)_stage_cmds endef define $(package)_postprocess_cmds - rm lib/libprotoc.a + rm lib/libprotoc.a lib/*.la endef diff --git a/depends/packages/qrencode.mk b/depends/packages/qrencode.mk index 313e4adf2a..56681b52a1 100644 --- a/depends/packages/qrencode.mk +++ b/depends/packages/qrencode.mk @@ -24,3 +24,7 @@ endef define $(package)_stage_cmds $(MAKE) DESTDIR=$($(package)_staging_dir) install endef + +define $(package)_postprocess_cmds + rm lib/*.la +endef diff --git a/depends/packages/xtrans.mk b/depends/packages/xtrans.mk index 67d2d976c4..1993ff8344 100644 --- a/depends/packages/xtrans.mk +++ b/depends/packages/xtrans.mk @@ -6,7 +6,7 @@ $(package)_sha256_hash=054d4ee3efd52508c753e9f7bc655ef185a29bd2850dd9e2fc2ccc335 $(package)_dependencies= define $(package)_set_vars -$(package)_config_opts_linux=--with-pic --disable-static +$(package)_config_opts_linux=--with-pic --disable-shared endef define $(package)_preprocess_cmds diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk index dfbc50580c..e69a37e093 100644 --- a/depends/packages/zeromq.mk +++ b/depends/packages/zeromq.mk @@ -31,5 +31,5 @@ endef define $(package)_postprocess_cmds sed -i.old "s/ -lstdc++//" lib/pkgconfig/libzmq.pc && \ - rm -rf bin share + rm -rf bin share lib/*.la endef diff --git a/doc/dependencies.md b/doc/dependencies.md index 1b3df62867..4c0e8d2567 100644 --- a/doc/dependencies.md +++ b/doc/dependencies.md @@ -6,7 +6,7 @@ These are the dependencies currently used by Bitcoin Core. You can find instruct | Dependency | Version used | Minimum required | CVEs | Shared | [Bundled Qt library](https://doc.qt.io/qt-5/configure-options.html#third-party-libraries) | | --- | --- | --- | --- | --- | --- | | Berkeley DB | [4.8.30](https://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html) | 4.8.x | No | | | -| Boost | [1.64.0](https://www.boost.org/users/download/) | [1.47.0](https://github.com/bitcoin/bitcoin/pull/8920) | No | | | +| Boost | [1.70.0](https://www.boost.org/users/download/) | [1.47.0](https://github.com/bitcoin/bitcoin/pull/8920) | No | | | | Clang | | [3.3+](https://llvm.org/releases/download.html) (C++11 support) | | | | | D-Bus | [1.10.18](https://cgit.freedesktop.org/dbus/dbus/tree/NEWS?h=dbus-1.10) | | No | Yes | | | Expat | [2.2.6](https://libexpat.github.io/) | | No | Yes | | diff --git a/doc/release-process.md b/doc/release-process.md index e9c6d5bf0d..8f1222cb88 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -41,10 +41,12 @@ Release Process #### After branch-off (on master) - Update the version of `contrib/gitian-descriptors/*.yml`. +- Update the versions in `SECURITY.md` as per the software lifecycle [maintenance policy](https://bitcoincore.org/en/lifecycle/#maintenance-period), generally bumping all up one major version. #### After branch-off (on the major release branch) - Update the versions and the link to the release notes draft in `doc/release-notes.md`. +- Delete `SECURITY.md`. #### Before final release @@ -270,6 +272,7 @@ The list of files should be: bitcoin-${VERSION}-aarch64-linux-gnu.tar.gz bitcoin-${VERSION}-arm-linux-gnueabihf.tar.gz bitcoin-${VERSION}-i686-pc-linux-gnu.tar.gz +bitcoin-${VERSION}-riscv64-linux-gnu.tar.gz bitcoin-${VERSION}-x86_64-linux-gnu.tar.gz bitcoin-${VERSION}-osx64.tar.gz bitcoin-${VERSION}-osx.dmg diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 1144ca8a78..c9c029818e 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -97,6 +97,7 @@ BITCOIN_TESTS =\ test/bswap_tests.cpp \ test/checkqueue_tests.cpp \ test/coins_tests.cpp \ + test/compilerbug_tests.cpp \ test/compress_tests.cpp \ test/crypto_tests.cpp \ test/cuckoocache_tests.cpp \ diff --git a/src/addrman.cpp b/src/addrman.cpp index 8a5f78d1c5..32676f8fa5 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -7,7 +7,6 @@ #include <hash.h> #include <serialize.h> -#include <streams.h> int CAddrInfo::GetTriedBucket(const uint256& nKey) const { diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index aa66d13102..be145a0e63 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -6,7 +6,6 @@ #include <arith_uint256.h> #include <uint256.h> -#include <util/strencodings.h> #include <crypto/common.h> #include <stdio.h> diff --git a/src/bench/base58.cpp b/src/bench/base58.cpp index e7702ec461..0f4b52cf79 100644 --- a/src/bench/base58.cpp +++ b/src/bench/base58.cpp @@ -4,7 +4,6 @@ #include <bench/bench.h> -#include <validation.h> #include <base58.h> #include <array> diff --git a/src/bench/bech32.cpp b/src/bench/bech32.cpp index 3c4b453a23..80f13eeb3b 100644 --- a/src/bench/bech32.cpp +++ b/src/bench/bech32.cpp @@ -4,7 +4,6 @@ #include <bench/bench.h> -#include <validation.h> #include <bech32.h> #include <util/strencodings.h> diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp index 3cf0bf9530..a788b23823 100644 --- a/src/bench/bench_bitcoin.cpp +++ b/src/bench/bench_bitcoin.cpp @@ -4,8 +4,6 @@ #include <bench/bench.h> -#include <crypto/sha256.h> -#include <key.h> #include <util/strencodings.h> #include <util/system.h> diff --git a/src/bench/chacha20.cpp b/src/bench/chacha20.cpp index 69d8c96ec0..030067aca5 100644 --- a/src/bench/chacha20.cpp +++ b/src/bench/chacha20.cpp @@ -5,7 +5,6 @@ #include <iostream> #include <bench/bench.h> -#include <hash.h> #include <crypto/chacha20.h> /* Number of bytes to process per iteration */ diff --git a/src/bench/checkqueue.cpp b/src/bench/checkqueue.cpp index 6ab542067a..000a0259bb 100644 --- a/src/bench/checkqueue.cpp +++ b/src/bench/checkqueue.cpp @@ -4,7 +4,6 @@ #include <bench/bench.h> #include <util/system.h> -#include <validation.h> #include <checkqueue.h> #include <prevector.h> #include <vector> diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp index dc0b054420..fb2bab9dee 100644 --- a/src/bench/crypto_hash.cpp +++ b/src/bench/crypto_hash.cpp @@ -5,11 +5,9 @@ #include <iostream> #include <bench/bench.h> -#include <bloom.h> #include <hash.h> #include <random.h> #include <uint256.h> -#include <util/time.h> #include <crypto/ripemd160.h> #include <crypto/sha1.h> #include <crypto/sha256.h> diff --git a/src/bench/duplicate_inputs.cpp b/src/bench/duplicate_inputs.cpp index 80ff13612c..2440341287 100644 --- a/src/bench/duplicate_inputs.cpp +++ b/src/bench/duplicate_inputs.cpp @@ -7,13 +7,9 @@ #include <coins.h> #include <consensus/merkle.h> #include <consensus/validation.h> -#include <miner.h> -#include <policy/policy.h> #include <pow.h> -#include <test/util.h> #include <txmempool.h> #include <validation.h> -#include <validationinterface.h> #include <list> #include <vector> diff --git a/src/bench/examples.cpp b/src/bench/examples.cpp index e7ddd5a938..3595249559 100644 --- a/src/bench/examples.cpp +++ b/src/bench/examples.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <bench/bench.h> -#include <validation.h> #include <util/time.h> // Sanity test: this should loop ten times, and diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp index 67d8a25564..b35a744055 100644 --- a/src/bench/rpc_mempool.cpp +++ b/src/bench/rpc_mempool.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <bench/bench.h> -#include <policy/policy.h> #include <rpc/blockchain.h> #include <txmempool.h> diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp index 312b66e38a..4891c57b3a 100644 --- a/src/bench/verify_script.cpp +++ b/src/bench/verify_script.cpp @@ -8,7 +8,6 @@ #include <script/bitcoinconsensus.h> #endif #include <script/script.h> -#include <script/sign.h> #include <script/standard.h> #include <streams.h> diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp index 46ca12826b..313b5a3ba0 100644 --- a/src/bench/wallet_balance.cpp +++ b/src/bench/wallet_balance.cpp @@ -4,7 +4,6 @@ #include <bench/bench.h> #include <interfaces/chain.h> -#include <key_io.h> #include <optional.h> #include <test/util.h> #include <validationinterface.h> diff --git a/src/bitcoin-wallet.cpp b/src/bitcoin-wallet.cpp index 32a539aac6..ad31f0be4a 100644 --- a/src/bitcoin-wallet.cpp +++ b/src/bitcoin-wallet.cpp @@ -8,7 +8,6 @@ #include <chainparams.h> #include <chainparamsbase.h> -#include <consensus/consensus.h> #include <logging.h> #include <util/system.h> #include <util/strencodings.h> diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index b31f86cdd9..094820293e 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -12,16 +12,12 @@ #include <compat.h> #include <fs.h> #include <interfaces/chain.h> -#include <rpc/server.h> #include <init.h> #include <noui.h> #include <shutdown.h> #include <util/system.h> -#include <httpserver.h> -#include <httprpc.h> #include <util/threadnames.h> #include <util/strencodings.h> -#include <walletinitinterface.h> #include <stdio.h> diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp index b47d9774ca..f87612edef 100644 --- a/src/consensus/merkle.cpp +++ b/src/consensus/merkle.cpp @@ -4,7 +4,6 @@ #include <consensus/merkle.h> #include <hash.h> -#include <util/strencodings.h> /* WARNING! If you're reading this because you're learning about crypto and/or designing a new system that will use merkle trees, keep in mind diff --git a/src/core_read.cpp b/src/core_read.cpp index a879a375ce..a3c9cf0159 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -11,7 +11,6 @@ #include <serialize.h> #include <streams.h> #include <univalue.h> -#include <util/system.h> #include <util/strencodings.h> #include <version.h> diff --git a/src/core_write.cpp b/src/core_write.cpp index 765a170307..4d64446d7b 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -13,7 +13,6 @@ #include <streams.h> #include <univalue.h> #include <util/system.h> -#include <util/moneystr.h> #include <util/strencodings.h> UniValue ValueFromAmount(const CAmount& amount) diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp index 2dc2133434..b3fb927760 100644 --- a/src/crypto/aes.cpp +++ b/src/crypto/aes.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <crypto/aes.h> -#include <crypto/common.h> #include <assert.h> #include <string.h> diff --git a/src/crypto/sha256_avx2.cpp b/src/crypto/sha256_avx2.cpp index 068e0e5ff6..90a72516a4 100644 --- a/src/crypto/sha256_avx2.cpp +++ b/src/crypto/sha256_avx2.cpp @@ -3,7 +3,6 @@ #include <stdint.h> #include <immintrin.h> -#include <crypto/sha256.h> #include <crypto/common.h> namespace sha256d64_avx2 { diff --git a/src/crypto/sha256_sse41.cpp b/src/crypto/sha256_sse41.cpp index adca870e2d..fc79f46f7f 100644 --- a/src/crypto/sha256_sse41.cpp +++ b/src/crypto/sha256_sse41.cpp @@ -3,7 +3,6 @@ #include <stdint.h> #include <immintrin.h> -#include <crypto/sha256.h> #include <crypto/common.h> namespace sha256d64_sse41 { diff --git a/src/httprpc.cpp b/src/httprpc.cpp index fcf760a4c6..c7a119440b 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -9,7 +9,6 @@ #include <key_io.h> #include <rpc/protocol.h> #include <rpc/server.h> -#include <random.h> #include <sync.h> #include <util/system.h> #include <util/strencodings.h> diff --git a/src/init.cpp b/src/init.cpp index 2bb270647a..6912b49717 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -51,7 +51,6 @@ #include <util/moneystr.h> #include <util/validation.h> #include <validationinterface.h> -#include <warnings.h> #include <walletinitinterface.h> #include <stdint.h> #include <stdio.h> @@ -259,7 +258,7 @@ void Shutdown(InitInterfaces& interfaces) // FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing if (pcoinsTip != nullptr) { - FlushStateToDisk(); + ::ChainstateActive().ForceFlushStateToDisk(); } // After there are no more peers/RPC left to give us new data which may generate @@ -275,7 +274,7 @@ void Shutdown(InitInterfaces& interfaces) { LOCK(cs_main); if (pcoinsTip != nullptr) { - FlushStateToDisk(); + ::ChainstateActive().ForceFlushStateToDisk(); } pcoinsTip.reset(); pcoinscatcher.reset(); @@ -1693,7 +1692,7 @@ bool AppInitMain(InitInterfaces& interfaces) nLocalServices = ServiceFlags(nLocalServices & ~NODE_NETWORK); if (!fReindex) { uiInterface.InitMessage(_("Pruning blockstore...")); - PruneAndFlush(); + ::ChainstateActive().PruneAndFlush(); } } diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index a864f21f04..161dd01ffe 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -334,8 +334,8 @@ public: return ::fHavePruned; } bool p2pEnabled() override { return g_connman != nullptr; } - bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !IsInitialBlockDownload(); } - bool isInitialBlockDownload() override { return IsInitialBlockDownload(); } + bool isReadyToBroadcast() override { return !::fImporting && !::fReindex && !isInitialBlockDownload(); } + bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); } bool shutdownRequested() override { return ShutdownRequested(); } int64_t getAdjustedTime() override { return GetAdjustedTime(); } void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); } diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp index 618cd02ea6..584d218dba 100644 --- a/src/interfaces/node.cpp +++ b/src/interfaces/node.cpp @@ -23,7 +23,6 @@ #include <policy/settings.h> #include <primitives/block.h> #include <rpc/server.h> -#include <scheduler.h> #include <shutdown.h> #include <sync.h> #include <txmempool.h> @@ -197,7 +196,7 @@ public: } return GuessVerificationProgress(Params().TxData(), tip); } - bool isInitialBlockDownload() override { return IsInitialBlockDownload(); } + bool isInitialBlockDownload() override { return ::ChainstateActive().IsInitialBlockDownload(); } bool getReindex() override { return ::fReindex; } bool getImporting() override { return ::fImporting; } void setNetworkActive(bool active) override diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp index b57299d78d..240670cbe7 100644 --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -5,27 +5,19 @@ #include <interfaces/wallet.h> #include <amount.h> -#include <chain.h> #include <consensus/validation.h> -#include <init.h> #include <interfaces/chain.h> #include <interfaces/handler.h> -#include <net.h> #include <policy/feerate.h> #include <policy/fees.h> -#include <policy/policy.h> #include <primitives/transaction.h> -#include <rpc/server.h> -#include <scheduler.h> #include <script/ismine.h> #include <script/standard.h> #include <support/allocators/secure.h> #include <sync.h> -#include <timedata.h> #include <ui_interface.h> #include <uint256.h> #include <util/system.h> -#include <validation.h> #include <wallet/feebumper.h> #include <wallet/fees.h> #include <wallet/rpcwallet.h> diff --git a/src/key.cpp b/src/key.cpp index c17f6a0ae2..3ba21753a2 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -5,7 +5,6 @@ #include <key.h> -#include <arith_uint256.h> #include <crypto/common.h> #include <crypto/hmac_sha512.h> #include <random.h> diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp index a54268d655..052aebbc80 100644 --- a/src/merkleblock.cpp +++ b/src/merkleblock.cpp @@ -7,7 +7,6 @@ #include <hash.h> #include <consensus/consensus.h> -#include <util/strencodings.h> CMerkleBlock::CMerkleBlock(const CBlock& block, CBloomFilter* filter, const std::set<uint256>* txids) diff --git a/src/miner.cpp b/src/miner.cpp index 3d53515435..015645c9c6 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -13,8 +13,6 @@ #include <consensus/merkle.h> #include <consensus/tx_verify.h> #include <consensus/validation.h> -#include <hash.h> -#include <net.h> #include <policy/feerate.h> #include <policy/policy.h> #include <pow.h> @@ -24,7 +22,6 @@ #include <util/moneystr.h> #include <util/system.h> #include <util/validation.h> -#include <validationinterface.h> #include <algorithm> #include <queue> diff --git a/src/net_processing.cpp b/src/net_processing.cpp index a3b865a69e..0d9e314afd 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -25,9 +25,7 @@ #include <scheduler.h> #include <tinyformat.h> #include <txmempool.h> -#include <ui_interface.h> #include <util/system.h> -#include <util/moneystr.h> #include <util/strencodings.h> #include <util/validation.h> @@ -1240,7 +1238,7 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta // the tip yet so we have no way to check this directly here. Instead we // just check that there are currently no other blocks in flight. else if (state.IsValid() && - !IsInitialBlockDownload() && + !::ChainstateActive().IsInitialBlockDownload() && mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) { if (it != mapBlockSource.end()) { MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first, connman); @@ -1728,7 +1726,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve } // If we're in IBD, we want outbound peers that will serve us a useful // chain. Disconnect peers that are on chains with insufficient work. - if (IsInitialBlockDownload() && nCount != MAX_HEADERS_RESULTS) { + if (::ChainstateActive().IsInitialBlockDownload() && nCount != MAX_HEADERS_RESULTS) { // When nCount < MAX_HEADERS_RESULTS, we know we have no more // headers to fetch from this peer. if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < nMinimumChainWork) { @@ -1994,7 +1992,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (!pfrom->fInbound) { // Advertise our address - if (fListen && !IsInitialBlockDownload()) + if (fListen && !::ChainstateActive().IsInitialBlockDownload()) { CAddress addr = GetLocalAddress(&pfrom->addr, pfrom->GetLocalServices()); FastRandomContext insecure_rand; @@ -2229,7 +2227,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr pfrom->AddInventoryKnown(inv); if (fBlocksOnly) { LogPrint(BCLog::NET, "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->GetId()); - } else if (!fAlreadyHave && !fImporting && !fReindex && !IsInitialBlockDownload()) { + } else if (!fAlreadyHave && !fImporting && !fReindex && !::ChainstateActive().IsInitialBlockDownload()) { RequestTx(State(pfrom->GetId()), inv.hash, nNow); } } @@ -2387,7 +2385,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } LOCK(cs_main); - if (IsInitialBlockDownload() && !pfrom->fWhitelisted) { + if (::ChainstateActive().IsInitialBlockDownload() && !pfrom->fWhitelisted) { LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom->GetId()); return true; } @@ -2609,7 +2607,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (!LookupBlockIndex(cmpctblock.header.hashPrevBlock)) { // Doesn't connect (or is genesis), instead of DoSing in AcceptBlockHeader, request deeper headers - if (!IsInitialBlockDownload()) + if (!::ChainstateActive().IsInitialBlockDownload()) connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, ::ChainActive().GetLocator(pindexBestHeader), uint256())); return true; } @@ -3524,7 +3522,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto) // Address refresh broadcast int64_t nNow = GetTimeMicros(); - if (!IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) { + if (!::ChainstateActive().IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) { AdvertiseLocal(pto); pto->nNextLocalAddrSend = PoissonNextSend(nNow, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL); } @@ -3925,7 +3923,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto) // Message: getdata (blocks) // std::vector<CInv> vGetData; - if (!pto->fClient && ((fFetch && !pto->m_limited_node) || !IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { + if (!pto->fClient && ((fFetch && !pto->m_limited_node) || !::ChainstateActive().IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { std::vector<const CBlockIndex*> vToDownload; NodeId staller = -1; FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller, consensusParams); diff --git a/src/netaddress.cpp b/src/netaddress.cpp index 6ee2d8a4b3..db6c46d12a 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -204,6 +204,11 @@ bool CNetAddr::IsRFC4843() const return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10); } +bool CNetAddr::IsRFC7343() const +{ + return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x20); +} + /** * @returns Whether or not this is a dummy address that maps an onion address * into IPv6. @@ -289,7 +294,7 @@ bool CNetAddr::IsValid() const */ bool CNetAddr::IsRoutable() const { - return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal() || IsInternal()); + return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsRFC7343() || IsLocal() || IsInternal()); } /** diff --git a/src/netaddress.h b/src/netaddress.h index 8230e40606..673eaf8d7b 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -63,7 +63,8 @@ class CNetAddr bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16) bool IsRFC4193() const; // IPv6 unique local (FC00::/7) bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32) - bool IsRFC4843() const; // IPv6 ORCHID (2001:10::/28) + bool IsRFC4843() const; // IPv6 ORCHID (deprecated) (2001:10::/28) + bool IsRFC7343() const; // IPv6 ORCHIDv2 (2001:20::/28) bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64) bool IsRFC6052() const; // IPv6 well-known prefix for IPv4-embedded address (64:FF9B::/96) bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) (actually defined in RFC2765) diff --git a/src/netbase.cpp b/src/netbase.cpp index 6c386a9ade..78b3b6ae3a 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -5,10 +5,7 @@ #include <netbase.h> -#include <hash.h> #include <sync.h> -#include <uint256.h> -#include <random.h> #include <tinyformat.h> #include <util/system.h> #include <util/strencodings.h> diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 6456eec016..7e93a746ca 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -4,7 +4,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <policy/fees.h> -#include <policy/policy.h> #include <clientversion.h> #include <primitives/transaction.h> diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 63a3d06267..51de5841ec 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -9,10 +9,6 @@ #include <consensus/validation.h> #include <coins.h> -#include <policy/settings.h> -#include <tinyformat.h> -#include <util/system.h> -#include <util/strencodings.h> CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn) diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index a0c2e3f125..60c7c2d160 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -7,7 +7,6 @@ #include <hash.h> #include <tinyformat.h> -#include <util/strencodings.h> #include <crypto/common.h> uint256 CBlockHeader::GetHash() const diff --git a/src/psbt.cpp b/src/psbt.cpp index 97bda51a63..d765133190 100644 --- a/src/psbt.cpp +++ b/src/psbt.cpp @@ -2,9 +2,6 @@ // 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_verify.h> -#include <policy/policy.h> #include <psbt.h> #include <util/strencodings.h> diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index 50d6afabcd..d8c39e8862 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -10,7 +10,6 @@ #include <qt/forms/ui_addressbookpage.h> #include <qt/addresstablemodel.h> -#include <qt/bitcoingui.h> #include <qt/csvmodelwriter.h> #include <qt/editaddressdialog.h> #include <qt/guiutil.h> diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index c3143e948a..fa6c9c9f7a 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -7,7 +7,6 @@ #include <qt/guiutil.h> #include <qt/walletmodel.h> -#include <interfaces/node.h> #include <key_io.h> #include <wallet/wallet.h> diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index 00c446cc63..8a6b205cd8 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -5,8 +5,6 @@ #include <qt/bantablemodel.h> #include <qt/clientmodel.h> -#include <qt/guiconstants.h> -#include <qt/guiutil.h> #include <interfaces/node.h> #include <sync.h> diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 81255aaae9..0c232f89fe 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -31,13 +31,9 @@ #include <interfaces/node.h> #include <noui.h> #include <util/threadnames.h> -#include <rpc/server.h> #include <ui_interface.h> #include <uint256.h> #include <util/system.h> -#include <warnings.h> - -#include <walletinitinterface.h> #include <memory> #include <stdint.h> diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp index 8aa1fdba4d..b27f8a744f 100644 --- a/src/qt/bitcoinunits.cpp +++ b/src/qt/bitcoinunits.cpp @@ -4,8 +4,6 @@ #include <qt/bitcoinunits.h> -#include <primitives/transaction.h> - #include <QStringList> BitcoinUnits::BitcoinUnits(QObject *parent): diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 88a35534c2..ce950150df 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -9,18 +9,12 @@ #include <qt/guiutil.h> #include <qt/peertablemodel.h> -#include <chain.h> -#include <chainparams.h> #include <clientversion.h> #include <interfaces/handler.h> #include <interfaces/node.h> -#include <validation.h> #include <net.h> #include <netbase.h> -#include <txmempool.h> -#include <ui_interface.h> #include <util/system.h> -#include <warnings.h> #include <stdint.h> diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 6c9bae7673..6b9f79aaf8 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -10,12 +10,10 @@ #include <qt/forms/ui_coincontroldialog.h> #include <qt/addresstablemodel.h> -#include <base58.h> #include <qt/bitcoinunits.h> #include <qt/guiutil.h> #include <qt/optionsmodel.h> #include <qt/platformstyle.h> -#include <txmempool.h> #include <qt/walletmodel.h> #include <wallet/coincontrol.h> @@ -23,8 +21,6 @@ #include <key_io.h> #include <policy/fees.h> #include <policy/policy.h> -#include <validation.h> // For mempool -#include <wallet/fees.h> #include <wallet/wallet.h> #include <QApplication> diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index 496aeebf7d..85b691c470 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -9,7 +9,6 @@ #include <qt/guiutil.h> #include <interfaces/node.h> -#include <validation.h> // for cs_main #include <sync.h> #include <QDebug> diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp index d537d759de..fca2a4e8c5 100644 --- a/src/qt/platformstyle.cpp +++ b/src/qt/platformstyle.cpp @@ -4,8 +4,6 @@ #include <qt/platformstyle.h> -#include <qt/guiconstants.h> - #include <QApplication> #include <QColor> #include <QImage> diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index fc58090dcd..c58717e21e 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -7,9 +7,7 @@ #include <qt/receivecoinsdialog.h> #include <qt/forms/ui_receivecoinsdialog.h> -#include <qt/addressbookpage.h> #include <qt/addresstablemodel.h> -#include <qt/bitcoinunits.h> #include <qt/optionsmodel.h> #include <qt/platformstyle.h> #include <qt/receiverequestdialog.h> diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index 20b29145a0..e492502002 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -8,7 +8,6 @@ #include <qt/bitcoinunits.h> #include <qt/guiutil.h> #include <qt/optionsmodel.h> -#include <qt/qrimagewidget.h> #include <QClipboard> #include <QPixmap> diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 8a0b265834..cb9efe9319 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -279,18 +279,16 @@ void SendCoinsDialog::on_sendButton_clicked() QStringList formatted; for (const SendCoinsRecipient &rcp : currentTransaction.getRecipients()) { - // generate bold amount string with wallet name in case of multiwallet - QString amount = "<b>" + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount); + // generate amount string with wallet name in case of multiwallet + QString amount = BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount); if (model->isMultiwallet()) { - amount.append(" <u>"+tr("from wallet %1").arg(GUIUtil::HtmlEscape(model->getWalletName()))+"</u> "); + amount.append(tr(" from wallet '%1'").arg(model->getWalletName())); } - amount.append("</b>"); - // generate monospace address string - QString address = "<span style='font-family: monospace;'>" + rcp.address; - address.append("</span>"); + + // generate address string + QString address = rcp.address; QString recipientElement; - recipientElement = "<br />"; #ifdef ENABLE_BIP70 if (!rcp.paymentRequest.IsInitialized()) // normal payment @@ -298,7 +296,7 @@ void SendCoinsDialog::on_sendButton_clicked() { if(rcp.label.length() > 0) // label with address { - recipientElement.append(tr("%1 to %2").arg(amount, GUIUtil::HtmlEscape(rcp.label))); + recipientElement.append(tr("%1 to '%2'").arg(amount, rcp.label)); recipientElement.append(QString(" (%1)").arg(address)); } else // just address @@ -309,7 +307,7 @@ void SendCoinsDialog::on_sendButton_clicked() #ifdef ENABLE_BIP70 else if(!rcp.authenticatedMerchant.isEmpty()) // authenticated payment request { - recipientElement.append(tr("%1 to %2").arg(amount, GUIUtil::HtmlEscape(rcp.authenticatedMerchant))); + recipientElement.append(tr("%1 to '%2'").arg(amount, rcp.authenticatedMerchant)); } else // unauthenticated payment request { @@ -323,7 +321,7 @@ void SendCoinsDialog::on_sendButton_clicked() QString questionString = tr("Are you sure you want to send?"); questionString.append("<br /><span style='font-size:10pt;'>"); questionString.append(tr("Please, review your transaction.")); - questionString.append("</span><br />%1"); + questionString.append("</span>%1"); if(txFee > 0) { @@ -364,8 +362,17 @@ void SendCoinsDialog::on_sendButton_clicked() questionString.append(QString("<br /><span style='font-size:10pt; font-weight:normal;'>(=%1)</span>") .arg(alternativeUnits.join(" " + tr("or") + " "))); - SendConfirmationDialog confirmationDialog(tr("Confirm send coins"), - questionString.arg(formatted.join("<br />")), SEND_CONFIRM_DELAY, this); + QString informative_text; + QString detailed_text; + if (formatted.size() > 1) { + questionString = questionString.arg(""); + informative_text = tr("To review recipient list click \"Show Details...\""); + detailed_text = formatted.join("\n\n"); + } else { + questionString = questionString.arg("<br /><br />" + formatted.at(0)); + } + + SendConfirmationDialog confirmationDialog(tr("Confirm send coins"), questionString, informative_text, detailed_text, SEND_CONFIRM_DELAY, this); confirmationDialog.exec(); QMessageBox::StandardButton retval = static_cast<QMessageBox::StandardButton>(confirmationDialog.result()); @@ -881,10 +888,15 @@ void SendCoinsDialog::coinControlUpdateLabels() } } -SendConfirmationDialog::SendConfirmationDialog(const QString &title, const QString &text, int _secDelay, - QWidget *parent) : - QMessageBox(QMessageBox::Question, title, text, QMessageBox::Yes | QMessageBox::Cancel, parent), secDelay(_secDelay) +SendConfirmationDialog::SendConfirmationDialog(const QString& title, const QString& text, const QString& informative_text, const QString& detailed_text, int _secDelay, QWidget* parent) + : QMessageBox(parent), secDelay(_secDelay) { + setIcon(QMessageBox::Question); + setWindowTitle(title); // On macOS, the window title is ignored (as required by the macOS Guidelines). + setText(text); + setInformativeText(informative_text); + setDetailedText(detailed_text); + setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); setDefaultButton(QMessageBox::Cancel); yesButton = button(QMessageBox::Yes); updateYesButton(); diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index 337a72b878..c6c1816877 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -108,7 +108,7 @@ class SendConfirmationDialog : public QMessageBox Q_OBJECT public: - SendConfirmationDialog(const QString &title, const QString &text, int secDelay = SEND_CONFIRM_DELAY, QWidget *parent = nullptr); + SendConfirmationDialog(const QString& title, const QString& text, const QString& informative_text = "", const QString& detailed_text = "", int secDelay = SEND_CONFIRM_DELAY, QWidget* parent = nullptr); int exec(); private Q_SLOTS: diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp index 2ba1c2604c..ea1019ad1d 100644 --- a/src/qt/test/addressbooktests.cpp +++ b/src/qt/test/addressbooktests.cpp @@ -4,8 +4,6 @@ #include <interfaces/chain.h> #include <interfaces/node.h> -#include <qt/addressbookpage.h> -#include <qt/addresstablemodel.h> #include <qt/editaddressdialog.h> #include <qt/optionsmodel.h> #include <qt/platformstyle.h> diff --git a/src/qt/test/apptests.cpp b/src/qt/test/apptests.cpp index da25d83175..b9bf933ee5 100644 --- a/src/qt/test/apptests.cpp +++ b/src/qt/test/apptests.cpp @@ -5,7 +5,6 @@ #include <qt/test/apptests.h> #include <chainparams.h> -#include <init.h> #include <qt/bitcoin.h> #include <qt/bitcoingui.h> #include <qt/networkstyle.h> @@ -16,9 +15,6 @@ #if defined(HAVE_CONFIG_H) #include <config/bitcoin-config.h> #endif -#ifdef ENABLE_WALLET -#include <wallet/db.h> -#endif #include <QAction> #include <QEventLoop> diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index b0bd89b290..7a10ada438 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -4,12 +4,8 @@ #include <qt/test/rpcnestedtests.h> -#include <chainparams.h> -#include <consensus/validation.h> #include <fs.h> #include <interfaces/node.h> -#include <validation.h> -#include <rpc/register.h> #include <rpc/server.h> #include <qt/rpcconsole.h> #include <test/setup_common.h> diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index ab40e9962b..e54915ec75 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -1,10 +1,8 @@ #include <qt/test/wallettests.h> #include <qt/test/util.h> -#include <init.h> #include <interfaces/chain.h> #include <interfaces/node.h> -#include <base58.h> #include <qt/bitcoinamountfield.h> #include <qt/optionsmodel.h> #include <qt/platformstyle.h> diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 0d070d9e87..aabe9dfb58 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -20,8 +20,6 @@ #include <script/script.h> #include <timedata.h> #include <util/system.h> -#include <wallet/db.h> -#include <wallet/wallet.h> #include <policy/policy.h> #include <stdint.h> diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index aa785553c8..7d6d84aa7b 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -5,11 +5,8 @@ #include <qt/transactionrecord.h> #include <chain.h> -#include <consensus/consensus.h> #include <interfaces/wallet.h> #include <key_io.h> -#include <timedata.h> -#include <validation.h> #include <stdint.h> diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 631a9b891d..6fe35b13cf 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -15,11 +15,7 @@ #include <core_io.h> #include <interfaces/handler.h> -#include <interfaces/node.h> -#include <sync.h> #include <uint256.h> -#include <util/system.h> -#include <validation.h> #include <QColor> #include <QDateTime> diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 762ec434a1..17e174e57a 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -10,7 +10,6 @@ #include <qt/editaddressdialog.h> #include <qt/optionsmodel.h> #include <qt/platformstyle.h> -#include <qt/sendcoinsdialog.h> #include <qt/transactiondescdialog.h> #include <qt/transactionfilterproxy.h> #include <qt/transactionrecord.h> diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index b051dd159b..3a4eebd94a 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -11,17 +11,12 @@ #include <qt/forms/ui_helpmessagedialog.h> #include <qt/bitcoingui.h> -#include <qt/clientmodel.h> -#include <qt/guiconstants.h> -#include <qt/intro.h> #ifdef ENABLE_BIP70 #include <qt/paymentrequestplus.h> #endif -#include <qt/guiutil.h> #include <clientversion.h> #include <init.h> -#include <interfaces/node.h> #include <util/system.h> #include <util/strencodings.h> diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index 2694d67800..8c0dc276b0 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -8,7 +8,6 @@ #include <qt/walletmodeltransaction.h> -#include <interfaces/node.h> #include <policy/policy.h> WalletModelTransaction::WalletModelTransaction(const QList<SendCoinsRecipient> &_recipients) : diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 56018caf24..49d7ae2016 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -6,7 +6,6 @@ #include <rpc/blockchain.h> #include <amount.h> -#include <base58.h> #include <blockfilter.h> #include <chain.h> #include <chainparams.h> @@ -15,7 +14,6 @@ #include <core_io.h> #include <hash.h> #include <index/blockfilterindex.h> -#include <index/txindex.h> #include <key_io.h> #include <policy/feerate.h> #include <policy/policy.h> @@ -1095,7 +1093,7 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request) UniValue ret(UniValue::VOBJ); CCoinsStats stats; - FlushStateToDisk(); + ::ChainstateActive().ForceFlushStateToDisk(); if (GetUTXOStats(pcoinsdbview.get(), stats)) { ret.pushKV("height", (int64_t)stats.nHeight); ret.pushKV("bestblock", stats.hashBlock.GetHex()); @@ -1360,7 +1358,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) obj.pushKV("difficulty", (double)GetDifficulty(tip)); obj.pushKV("mediantime", (int64_t)tip->GetMedianTimePast()); obj.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip)); - obj.pushKV("initialblockdownload", IsInitialBlockDownload()); + obj.pushKV("initialblockdownload", ::ChainstateActive().IsInitialBlockDownload()); obj.pushKV("chainwork", tip->nChainWork.GetHex()); obj.pushKV("size_on_disk", CalculateCurrentUsage()); obj.pushKV("pruned", fPruneMode); @@ -2292,7 +2290,7 @@ UniValue scantxoutset(const JSONRPCRequest& request) std::unique_ptr<CCoinsViewCursor> pcursor; { LOCK(cs_main); - FlushStateToDisk(); + ::ChainstateActive().ForceFlushStateToDisk(); pcursor = std::unique_ptr<CCoinsViewCursor>(pcoinsdbview->Cursor()); assert(pcursor); } diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 1831562100..477f05f46c 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -442,7 +442,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0) throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, PACKAGE_NAME " is not connected!"); - if (IsInitialBlockDownload()) + if (::ChainstateActive().IsInitialBlockDownload()) throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, PACKAGE_NAME " is in initial sync and waiting for blocks..."); static unsigned int nTransactionsUpdatedLast; diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 72a2919712..2b29fd543b 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -3,25 +3,17 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <chain.h> -#include <clientversion.h> -#include <core_io.h> #include <crypto/ripemd160.h> #include <key_io.h> -#include <validation.h> #include <httpserver.h> -#include <net.h> -#include <netbase.h> #include <outputtype.h> #include <rpc/blockchain.h> #include <rpc/server.h> #include <rpc/util.h> #include <script/descriptor.h> -#include <timedata.h> #include <util/system.h> #include <util/strencodings.h> #include <util/validation.h> -#include <warnings.h> #include <stdint.h> #include <tuple> diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index e49c3e031f..d993a88458 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -5,7 +5,6 @@ #include <rpc/server.h> #include <banman.h> -#include <chainparams.h> #include <clientversion.h> #include <core_io.h> #include <net.h> @@ -17,7 +16,6 @@ #include <rpc/util.h> #include <sync.h> #include <timedata.h> -#include <ui_interface.h> #include <util/strencodings.h> #include <util/system.h> #include <validation.h> diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index 23999b305a..33b0130a94 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -10,7 +10,6 @@ #include <util/system.h> #include <util/strencodings.h> #include <util/time.h> -#include <version.h> /** * JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility, diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index b3926786db..0b760439c1 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -6,21 +6,16 @@ #include <chain.h> #include <coins.h> #include <compat/byteswap.h> -#include <consensus/tx_verify.h> #include <consensus/validation.h> #include <core_io.h> #include <index/txindex.h> -#include <init.h> -#include <interfaces/chain.h> #include <key_io.h> #include <keystore.h> #include <merkleblock.h> #include <node/coin.h> #include <node/psbt.h> #include <node/transaction.h> -#include <policy/policy.h> #include <policy/rbf.h> -#include <policy/settings.h> #include <primitives/transaction.h> #include <psbt.h> #include <rpc/rawtransaction_util.h> @@ -31,7 +26,6 @@ #include <script/sign.h> #include <script/standard.h> #include <uint256.h> -#include <util/bip32.h> #include <util/moneystr.h> #include <util/strencodings.h> #include <validation.h> diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp index 8af491977c..9c4cdc3a90 100644 --- a/src/rpc/rawtransaction_util.cpp +++ b/src/rpc/rawtransaction_util.cpp @@ -7,7 +7,6 @@ #include <coins.h> #include <core_io.h> -#include <interfaces/chain.h> #include <key_io.h> #include <keystore.h> #include <policy/policy.h> diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 9df4070cbb..ca17d379bc 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -7,11 +7,9 @@ #include <fs.h> #include <key_io.h> -#include <random.h> #include <rpc/util.h> #include <shutdown.h> #include <sync.h> -#include <ui_interface.h> #include <util/strencodings.h> #include <util/system.h> diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index 9be87fabb0..50119ba184 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -164,6 +164,9 @@ struct PubkeyProvider /** Get the descriptor string form including private data (if available in arg). */ virtual bool ToPrivateString(const SigningProvider& arg, std::string& out) const = 0; + + /** Derive a private key, if private data is available in arg. */ + virtual bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const = 0; }; class OriginPubkeyProvider final : public PubkeyProvider @@ -195,6 +198,10 @@ public: ret = "[" + OriginString() + "]" + std::move(sub); return true; } + bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override + { + return m_provider->GetPrivKey(pos, arg, key); + } }; /** An object representing a parsed constant public key in a descriptor. */ @@ -222,6 +229,10 @@ public: ret = EncodeSecret(key); return true; } + bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override + { + return arg.GetKey(m_pubkey.GetID(), key); + } }; enum class DeriveType { @@ -266,14 +277,9 @@ public: { if (key) { if (IsHardened()) { - CExtKey extkey; - if (!GetExtKey(arg, extkey)) return false; - for (auto entry : m_path) { - extkey.Derive(extkey, entry); - } - if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos); - if (m_derive == DeriveType::HARDENED) extkey.Derive(extkey, pos | 0x80000000UL); - *key = extkey.Neuter().pubkey; + CKey priv_key; + if (!GetPrivKey(pos, arg, priv_key)) return false; + *key = priv_key.GetPubKey(); } else { // TODO: optimize by caching CExtPubKey extkey = m_extkey; @@ -312,6 +318,18 @@ public: } return true; } + bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override + { + CExtKey extkey; + if (!GetExtKey(arg, extkey)) return false; + for (auto entry : m_path) { + extkey.Derive(extkey, entry); + } + if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos); + if (m_derive == DeriveType::HARDENED) extkey.Derive(extkey, pos | 0x80000000UL); + key = extkey.key; + return true; + } }; /** Base class for all Descriptor implementations. */ @@ -462,6 +480,20 @@ public: Span<const unsigned char> span = MakeSpan(cache); return ExpandHelper(pos, DUMMY_SIGNING_PROVIDER, &span, output_scripts, out, nullptr) && span.size() == 0; } + + void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const final + { + for (const auto& p : m_pubkey_args) { + CKey key; + if (!p->GetPrivKey(pos, provider, key)) continue; + out.keys.emplace(key.GetPubKey().GetID(), key); + } + if (m_script_arg) { + FlatSigningProvider subprovider; + m_script_arg->ExpandPrivate(pos, provider, subprovider); + out = Merge(out, subprovider); + } + } }; /** Construct a vector with one element, which is moved into it. */ diff --git a/src/script/descriptor.h b/src/script/descriptor.h index 907a102284..af7ae229ca 100644 --- a/src/script/descriptor.h +++ b/src/script/descriptor.h @@ -60,6 +60,14 @@ struct Descriptor { * out: scripts and public keys necessary for solving the expanded scriptPubKeys will be put here (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. + */ + virtual void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const = 0; }; /** Parse a descriptor string. Included private keys are put in out. diff --git a/src/script/script.cpp b/src/script/script.cpp index 982aa241e7..0666a385d1 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -5,7 +5,6 @@ #include <script/script.h> -#include <tinyformat.h> #include <util/strencodings.h> const char* GetOpName(opcodetype opcode) diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp index 94005cf6f3..eaf5363bd7 100644 --- a/src/script/sigcache.cpp +++ b/src/script/sigcache.cpp @@ -5,7 +5,6 @@ #include <script/sigcache.h> -#include <memusage.h> #include <pubkey.h> #include <random.h> #include <uint256.h> diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 91a301bcdf..b7d6cd925c 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -8,8 +8,6 @@ #include <crypto/sha256.h> #include <pubkey.h> #include <script/script.h> -#include <util/system.h> -#include <util/strencodings.h> typedef std::vector<unsigned char> valtype; diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 665975ca67..d03defb335 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -4,13 +4,11 @@ #include <attributes.h> #include <coins.h> -#include <consensus/validation.h> #include <script/standard.h> #include <test/setup_common.h> #include <uint256.h> #include <undo.h> #include <util/strencodings.h> -#include <validation.h> #include <map> #include <vector> diff --git a/src/test/compilerbug_tests.cpp b/src/test/compilerbug_tests.cpp new file mode 100644 index 0000000000..74e1eac3ea --- /dev/null +++ b/src/test/compilerbug_tests.cpp @@ -0,0 +1,43 @@ +// 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 <test/setup_common.h> +#include <boost/test/unit_test.hpp> + +BOOST_FIXTURE_TEST_SUITE(compilerbug_tests, BasicTestingSetup) + +#if defined(__GNUC__) +// This block will also be built under clang, which is fine (as it supports noinline) +void __attribute__ ((noinline)) set_one(unsigned char* ptr) +{ + *ptr = 1; +} + +int __attribute__ ((noinline)) check_zero(unsigned char const* in, unsigned int len) +{ + for (unsigned int i = 0; i < len; ++i) { + if (in[i] != 0) return 0; + } + return 1; +} + +void set_one_on_stack() { + unsigned char buf[1]; + set_one(buf); +} + +BOOST_AUTO_TEST_CASE(gccbug_90348) { + // Test for GCC bug 90348. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90348 + for (int i = 0; i <= 4; ++i) { + unsigned char in[4]; + for (int j = 0; j < i; ++j) { + in[j] = 0; + set_one_on_stack(); // Apparently modifies in[0] + } + BOOST_CHECK(check_zero(in, i)); + } +} +#endif + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index d47f395c15..3a2844861b 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -9,7 +9,6 @@ #include <keystore.h> #include <net.h> #include <net_processing.h> -#include <pow.h> #include <script/sign.h> #include <serialize.h> #include <util/system.h> diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 4321d7d16e..9a182d7bd3 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -7,7 +7,6 @@ #include <consensus/consensus.h> #include <consensus/merkle.h> #include <consensus/tx_verify.h> -#include <consensus/validation.h> #include <miner.h> #include <policy/policy.h> #include <pubkey.h> diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index 682f1bee26..10a732d64d 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -9,7 +9,6 @@ #include <script/script_error.h> #include <script/interpreter.h> #include <script/sign.h> -#include <script/ismine.h> #include <uint256.h> #include <test/setup_common.h> diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index dd5e3eb6d5..86c0cecbf1 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -59,6 +59,7 @@ BOOST_AUTO_TEST_CASE(netbase_properties) BOOST_CHECK(ResolveIP("FC00::").IsRFC4193()); BOOST_CHECK(ResolveIP("2001::2").IsRFC4380()); BOOST_CHECK(ResolveIP("2001:10::").IsRFC4843()); + BOOST_CHECK(ResolveIP("2001:20::").IsRFC7343()); BOOST_CHECK(ResolveIP("FE80::").IsRFC4862()); BOOST_CHECK(ResolveIP("64:FF9B::").IsRFC6052()); BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsTor()); diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 07d1326bcb..63bfe1d346 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -9,8 +9,6 @@ #include <core_io.h> #include <init.h> #include <interfaces/chain.h> -#include <key_io.h> -#include <netbase.h> #include <test/setup_common.h> diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp index 9c4606f1b3..aa9c98c173 100644 --- a/src/test/script_p2sh_tests.cpp +++ b/src/test/script_p2sh_tests.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <consensus/tx_verify.h> -#include <core_io.h> #include <key.h> #include <keystore.h> #include <validation.h> diff --git a/src/test/setup_common.cpp b/src/test/setup_common.cpp index 5b454da52b..b11d090f67 100644 --- a/src/test/setup_common.cpp +++ b/src/test/setup_common.cpp @@ -18,7 +18,6 @@ #include <rpc/server.h> #include <script/sigcache.h> #include <streams.h> -#include <ui_interface.h> #include <util/validation.h> #include <validation.h> diff --git a/src/test/torcontrol_tests.cpp b/src/test/torcontrol_tests.cpp index 6d8459f5b1..d846062d9b 100644 --- a/src/test/torcontrol_tests.cpp +++ b/src/test/torcontrol_tests.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. // #include <test/setup_common.h> -#include <torcontrol.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp index 19561d4f67..d794d09d30 100644 --- a/src/test/txindex_tests.cpp +++ b/src/test/txindex_tests.cpp @@ -8,7 +8,6 @@ #include <test/setup_common.h> #include <util/system.h> #include <util/time.h> -#include <validation.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp index fe30d5f3a7..352ce0295b 100644 --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -13,9 +13,7 @@ #include <script/sign.h> #include <test/setup_common.h> #include <util/time.h> -#include <core_io.h> #include <keystore.h> -#include <policy/policy.h> #include <boost/test/unit_test.hpp> diff --git a/src/test/util.cpp b/src/test/util.cpp index 64ecc6623a..bc09d00b7a 100644 --- a/src/test/util.cpp +++ b/src/test/util.cpp @@ -6,14 +6,11 @@ #include <chainparams.h> #include <consensus/merkle.h> -#include <consensus/validation.h> #include <key_io.h> #include <miner.h> #include <outputtype.h> #include <pow.h> -#include <scheduler.h> #include <script/standard.h> -#include <txdb.h> #include <validation.h> #include <validationinterface.h> #ifdef ENABLE_WALLET diff --git a/src/timedata.cpp b/src/timedata.cpp index 9c022c9ad1..b43639d729 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -12,7 +12,6 @@ #include <sync.h> #include <ui_interface.h> #include <util/system.h> -#include <util/strencodings.h> #include <warnings.h> diff --git a/src/txdb.cpp b/src/txdb.cpp index 494b87ad48..73fe2a8ee4 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -5,8 +5,6 @@ #include <txdb.h> -#include <chainparams.h> -#include <hash.h> #include <random.h> #include <pow.h> #include <shutdown.h> diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 80dbd9c19d..cac7beb6a1 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -13,8 +13,6 @@ #include <policy/fees.h> #include <policy/settings.h> #include <reverse_iterator.h> -#include <streams.h> -#include <timedata.h> #include <util/system.h> #include <util/moneystr.h> #include <util/time.h> diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp index 31a95486d7..746514a01f 100644 --- a/src/ui_interface.cpp +++ b/src/ui_interface.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <ui_interface.h> -#include <util/system.h> #include <boost/signals2/last_value.hpp> #include <boost/signals2/signal.hpp> diff --git a/src/util/system.cpp b/src/util/system.cpp index 6925bda4ef..6a6b82c967 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -6,8 +6,6 @@ #include <util/system.h> #include <chainparamsbase.h> -#include <random.h> -#include <serialize.h> #include <util/strencodings.h> #include <stdarg.h> diff --git a/src/validation.cpp b/src/validation.cpp index 436c62261b..b2925efe32 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -20,7 +20,6 @@ #include <index/txindex.h> #include <policy/fees.h> #include <policy/policy.h> -#include <policy/rbf.h> #include <policy/settings.h> #include <pow.h> #include <primitives/block.h> @@ -60,165 +59,27 @@ #define MICRO 0.000001 #define MILLI 0.001 -/** - * Global state - */ -namespace { - struct CBlockIndexWorkComparator - { - bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const { - // First sort by most total work, ... - if (pa->nChainWork > pb->nChainWork) return false; - if (pa->nChainWork < pb->nChainWork) return true; - - // ... then by earliest time received, ... - if (pa->nSequenceId < pb->nSequenceId) return false; - if (pa->nSequenceId > pb->nSequenceId) return true; - - // Use pointer address as tie breaker (should only happen with blocks - // loaded from disk, as those all have id 0). - if (pa < pb) return false; - if (pa > pb) return true; - - // Identical blocks. - return false; - } - }; -} // anon namespace - -enum DisconnectResult -{ - DISCONNECT_OK, // All good. - DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block. - DISCONNECT_FAILED // Something else went wrong. -}; - -class ConnectTrace; - -/** - * CChainState stores and provides an API to update our local knowledge of the - * current best chain and header tree. - * - * It generally provides access to the current block tree, as well as functions - * to provide new data, which it will appropriately validate and incorporate in - * its state as necessary. - * - * Eventually, the API here is targeted at being exposed externally as a - * consumable libconsensus library, so any functions added must only call - * other class member functions, pure functions in other parts of the consensus - * library, callbacks via the validation interface, or read/write-to-disk - * functions (eventually this will also be via callbacks). - */ -class CChainState { -private: - /** - * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for itself and all ancestors) and - * as good as our current tip or better. Entries may be failed, though, and pruning nodes may be - * missing the data for the block. - */ - std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates; - - /** - * Every received block is assigned a unique and increasing identifier, so we - * know which one to give priority in case of a fork. - */ - CCriticalSection cs_nBlockSequenceId; - /** Blocks loaded from disk are assigned id 0, so start the counter at 1. */ - int32_t nBlockSequenceId = 1; - /** Decreasing counter (used by subsequent preciousblock calls). */ - int32_t nBlockReverseSequenceId = -1; - /** chainwork for the last block that preciousblock has been applied to. */ - arith_uint256 nLastPreciousChainwork = 0; - - /** In order to efficiently track invalidity of headers, we keep the set of - * blocks which we tried to connect and found to be invalid here (ie which - * were set to BLOCK_FAILED_VALID since the last restart). We can then - * walk this set and check if a new header is a descendant of something in - * this set, preventing us from having to walk mapBlockIndex when we try - * to connect a bad block and fail. - * - * While this is more complicated than marking everything which descends - * from an invalid block as invalid at the time we discover it to be - * invalid, doing so would require walking all of mapBlockIndex to find all - * descendants. Since this case should be very rare, keeping track of all - * BLOCK_FAILED_VALID blocks in a set should be just fine and work just as - * well. - * - * Because we already walk mapBlockIndex in height-order at startup, we go - * ahead and mark descendants of invalid blocks as FAILED_CHILD at that time, - * instead of putting things in this set. - */ - std::set<CBlockIndex*> m_failed_blocks; - - /** - * the ChainState CriticalSection - * A lock that must be held when modifying this ChainState - held in ActivateBestChain() - */ - CCriticalSection m_cs_chainstate; +bool CBlockIndexWorkComparator::operator()(const CBlockIndex *pa, const CBlockIndex *pb) const { + // First sort by most total work, ... + if (pa->nChainWork > pb->nChainWork) return false; + if (pa->nChainWork < pb->nChainWork) return true; -public: - //! The current chain of blockheaders we consult and build on. - //! @see CChain, CBlockIndex. - CChain m_chain; - BlockMap mapBlockIndex GUARDED_BY(cs_main); - std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked; - CBlockIndex *pindexBestInvalid = nullptr; - - bool LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - - bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) LOCKS_EXCLUDED(cs_main); - - /** - * If a block header hasn't already been seen, call CheckBlockHeader on it, ensure - * that it doesn't descend from an invalid block, and then add it to mapBlockIndex. - */ - bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - - // Block (dis)connection on a given view: - DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view); - bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, - CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + // ... then by earliest time received, ... + if (pa->nSequenceId < pb->nSequenceId) return false; + if (pa->nSequenceId > pb->nSequenceId) return true; - // Block disconnection on our pcoinsTip: - bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions* disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - - // Manual block validity manipulation: - bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main); - bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main); - void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - - bool ReplayBlocks(const CChainParams& params, CCoinsView* view); - bool RewindBlockIndex(const CChainParams& params) LOCKS_EXCLUDED(cs_main); - bool LoadGenesisBlock(const CChainParams& chainparams); - - void PruneBlockIndexCandidates(); - - void UnloadBlockIndex(); - -private: - bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - - CBlockIndex* AddToBlockIndex(const CBlockHeader& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - /** Create a new block index entry for a given block hash */ - CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - /** - * Make various assertions about the state of the block index. - * - * By default this only executes fully when using the Regtest chain; see: fCheckBlockIndex. - */ - void CheckBlockIndex(const Consensus::Params& consensusParams); + // Use pointer address as tie breaker (should only happen with blocks + // loaded from disk, as those all have id 0). + if (pa < pb) return false; + if (pa > pb) return true; - void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) EXCLUSIVE_LOCKS_REQUIRED(cs_main); - CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main); - void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + // Identical blocks. + return false; +} - bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main); +CChainState g_chainstate; - //! Mark a block as not having block data - void EraseBlockData(CBlockIndex* index) EXCLUSIVE_LOCKS_REQUIRED(cs_main); -} g_chainstate; +CChainState& ChainstateActive() { return g_chainstate; } CChain& ChainActive() { return g_chainstate.m_chain; } @@ -234,7 +95,7 @@ CChain& ChainActive() { return g_chainstate.m_chain; } */ RecursiveMutex cs_main; -BlockMap& mapBlockIndex = g_chainstate.mapBlockIndex; +BlockMap& mapBlockIndex = ::ChainstateActive().mapBlockIndex; CBlockIndex *pindexBestHeader = nullptr; Mutex g_best_block_mutex; std::condition_variable g_best_block_cv; @@ -265,12 +126,12 @@ CScript COINBASE_FLAGS; // Internal stuff namespace { - CBlockIndex *&pindexBestInvalid = g_chainstate.pindexBestInvalid; + CBlockIndex *&pindexBestInvalid = ::ChainstateActive().pindexBestInvalid; /** All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions. * Pruned nodes may have entries where B is missing data. */ - std::multimap<CBlockIndex*, CBlockIndex*>& mapBlocksUnlinked = g_chainstate.mapBlocksUnlinked; + std::multimap<CBlockIndex*, CBlockIndex*>& mapBlocksUnlinked = ::ChainstateActive().mapBlocksUnlinked; CCriticalSection cs_LastBlockFile; std::vector<CBlockFileInfo> vinfoBlockFile; @@ -311,15 +172,7 @@ std::unique_ptr<CCoinsViewDB> pcoinsdbview; std::unique_ptr<CCoinsViewCache> pcoinsTip; std::unique_ptr<CBlockTreeDB> pblocktree; -enum class FlushStateMode { - NONE, - IF_NEEDED, - PERIODIC, - ALWAYS -}; - // See definition for documentation -static bool FlushStateToDisk(const CChainParams& chainParams, CValidationState &state, FlushStateMode mode, int nManualPruneHeight=0); static void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight); static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight); bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks = nullptr); @@ -467,7 +320,7 @@ static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) static bool IsCurrentForFeeEstimation() EXCLUSIVE_LOCKS_REQUIRED(cs_main) { AssertLockHeld(cs_main); - if (IsInitialBlockDownload()) + if (::ChainstateActive().IsInitialBlockDownload()) return false; if (::ChainActive().Tip()->GetBlockTime() < (GetTime() - MAX_FEE_ESTIMATION_TIP_AGE)) return false; @@ -992,7 +845,7 @@ static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPo } // After we've (potentially) uncached entries, ensure our coins cache is still within its size limits CValidationState stateDummy; - FlushStateToDisk(chainparams, stateDummy, FlushStateMode::PERIODIC); + ::ChainstateActive().FlushStateToDisk(chainparams, stateDummy, FlushStateMode::PERIODIC); return res; } @@ -1168,27 +1021,30 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) return nSubsidy; } -bool IsInitialBlockDownload() +// Note that though this is marked const, we may end up modifying `m_cached_finished_ibd`, which +// is a performance-related implementation detail. This function must be marked +// `const` so that `CValidationInterface` clients (which are given a `const CChainState*`) +// can call it. +// +bool CChainState::IsInitialBlockDownload() const { - // Once this function has returned false, it must remain false. - static std::atomic<bool> latchToFalse{false}; // Optimization: pre-test latch before taking the lock. - if (latchToFalse.load(std::memory_order_relaxed)) + if (m_cached_finished_ibd.load(std::memory_order_relaxed)) return false; LOCK(cs_main); - if (latchToFalse.load(std::memory_order_relaxed)) + if (m_cached_finished_ibd.load(std::memory_order_relaxed)) return false; if (fImporting || fReindex) return true; - if (::ChainActive().Tip() == nullptr) + if (m_chain.Tip() == nullptr) return true; - if (::ChainActive().Tip()->nChainWork < nMinimumChainWork) + if (m_chain.Tip()->nChainWork < nMinimumChainWork) return true; - if (::ChainActive().Tip()->GetBlockTime() < (GetTime() - nMaxTipAge)) + if (m_chain.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge)) return true; LogPrintf("Leaving InitialBlockDownload (latching to false)\n"); - latchToFalse.store(true, std::memory_order_relaxed); + m_cached_finished_ibd.store(true, std::memory_order_relaxed); return false; } @@ -1217,7 +1073,7 @@ static void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main) AssertLockHeld(cs_main); // Before we get past initial download, we cannot reliably alert about forks // (we assume we don't get stuck on a fork before finishing our initial sync) - if (IsInitialBlockDownload()) + if (::ChainstateActive().IsInitialBlockDownload()) return; // If our best fork is no longer within 72 blocks (+/- 12 hours if no one mines it) @@ -2089,16 +1945,12 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl return true; } -/** - * Update the on-disk chain state. - * The caches and indexes are flushed depending on the mode we're called with - * if they're too large, if it's been a while since the last write, - * or always and in all cases if we're in prune mode and are deleting files. - * - * If FlushStateMode::NONE is used, then FlushStateToDisk(...) won't do anything - * besides checking if we need to prune. - */ -bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &state, FlushStateMode mode, int nManualPruneHeight) { +bool CChainState::FlushStateToDisk( + const CChainParams& chainparams, + CValidationState &state, + FlushStateMode mode, + int nManualPruneHeight) +{ int64_t nMempoolUsage = mempool.DynamicMemoryUsage(); LOCK(cs_main); static int64_t nLastWrite = 0; @@ -2196,7 +2048,7 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState & } if (full_flush_completed) { // Update best block in wallet (so we can detect restored wallets). - GetMainSignals().ChainStateFlushed(::ChainActive().GetLocator()); + GetMainSignals().ChainStateFlushed(m_chain.GetLocator()); } } catch (const std::runtime_error& e) { return AbortNode(state, std::string("System error while flushing: ") + e.what()); @@ -2204,19 +2056,20 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState & return true; } -void FlushStateToDisk() { +void CChainState::ForceFlushStateToDisk() { CValidationState state; const CChainParams& chainparams = Params(); - if (!FlushStateToDisk(chainparams, state, FlushStateMode::ALWAYS)) { + if (!this->FlushStateToDisk(chainparams, state, FlushStateMode::ALWAYS)) { LogPrintf("%s: failed to flush state (%s)\n", __func__, FormatStateMessage(state)); } } -void PruneAndFlush() { +void CChainState::PruneAndFlush() { CValidationState state; fCheckForPruning = true; const CChainParams& chainparams = Params(); - if (!FlushStateToDisk(chainparams, state, FlushStateMode::NONE)) { + + if (!this->FlushStateToDisk(chainparams, state, FlushStateMode::NONE)) { LogPrintf("%s: failed to flush state (%s)\n", __func__, FormatStateMessage(state)); } } @@ -2250,7 +2103,7 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar } std::string warningMessages; - if (!IsInitialBlockDownload()) + if (!::ChainstateActive().IsInitialBlockDownload()) { int nUpgraded = 0; const CBlockIndex* pindex = pindexNew; @@ -2641,7 +2494,7 @@ static void NotifyHeaderTip() LOCKS_EXCLUDED(cs_main) { if (pindexHeader != pindexHeaderOld) { fNotify = true; - fInitialBlockDownload = IsInitialBlockDownload(); + fInitialBlockDownload = ::ChainstateActive().IsInitialBlockDownload(); pindexHeaderOld = pindexHeader; } } @@ -2767,7 +2620,7 @@ bool CChainState::ActivateBestChain(CValidationState &state, const CChainParams& } bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) { - return g_chainstate.ActivateBestChain(state, chainparams, std::move(pblock)); + return ::ChainstateActive().ActivateBestChain(state, chainparams, std::move(pblock)); } bool CChainState::PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex) @@ -2799,7 +2652,7 @@ bool CChainState::PreciousBlock(CValidationState& state, const CChainParams& par return ActivateBestChain(state, params, std::shared_ptr<const CBlock>()); } bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex) { - return g_chainstate.PreciousBlock(state, params, pindex); + return ::ChainstateActive().PreciousBlock(state, params, pindex); } bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) @@ -2888,7 +2741,7 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c } bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) { - return g_chainstate.InvalidateBlock(state, chainparams, pindex); + return ::ChainstateActive().InvalidateBlock(state, chainparams, pindex); } void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) { @@ -2926,7 +2779,7 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) { } void ResetBlockFailureFlags(CBlockIndex *pindex) { - return g_chainstate.ResetBlockFailureFlags(pindex); + return ::ChainstateActive().ResetBlockFailureFlags(pindex); } CBlockIndex* CChainState::AddToBlockIndex(const CBlockHeader& block) @@ -3464,7 +3317,7 @@ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, CValidatio LOCK(cs_main); for (const CBlockHeader& header : headers) { CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast - if (!g_chainstate.AcceptBlockHeader(header, state, chainparams, &pindex)) { + if (!::ChainstateActive().AcceptBlockHeader(header, state, chainparams, &pindex)) { if (first_invalid) *first_invalid = header; return false; } @@ -3595,7 +3448,7 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons bool ret = CheckBlock(*pblock, state, chainparams.GetConsensus()); if (ret) { // Store to disk - ret = g_chainstate.AcceptBlock(pblock, state, chainparams, &pindex, fForceProcessing, nullptr, fNewBlock); + ret = ::ChainstateActive().AcceptBlock(pblock, state, chainparams, &pindex, fForceProcessing, nullptr, fNewBlock); } if (!ret) { GetMainSignals().BlockChecked(*pblock, state); @@ -3606,7 +3459,7 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons NotifyHeaderTip(); CValidationState state; // Only used to report errors, not invalidity - ignore it - if (!g_chainstate.ActivateBestChain(state, chainparams, pblock)) + if (!::ChainstateActive().ActivateBestChain(state, chainparams, pblock)) return error("%s: ActivateBestChain failed (%s)", __func__, FormatStateMessage(state)); return true; @@ -3630,7 +3483,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state)); if (!ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindexPrev)) return error("%s: Consensus::ContextualCheckBlock: %s", __func__, FormatStateMessage(state)); - if (!g_chainstate.ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true)) + if (!::ChainstateActive().ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true)) return false; assert(state.IsValid()); @@ -3725,7 +3578,8 @@ void PruneBlockFilesManual(int nManualPruneHeight) { CValidationState state; const CChainParams& chainparams = Params(); - if (!FlushStateToDisk(chainparams, state, FlushStateMode::NONE, nManualPruneHeight)) { + if (!::ChainstateActive().FlushStateToDisk( + chainparams, state, FlushStateMode::NONE, nManualPruneHeight)) { LogPrintf("%s: failed to flush state (%s)\n", __func__, FormatStateMessage(state)); } } @@ -3769,7 +3623,7 @@ static void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfte // To avoid excessive prune events negating the benefit of high dbcache // values, we should not prune too rapidly. // So when pruning in IBD, increase the buffer a bit to avoid a re-prune too soon. - if (IsInitialBlockDownload()) { + if (::ChainstateActive().IsInitialBlockDownload()) { // Since this is only relevant during IBD, we use a fixed 10% nBuffer += nPruneTarget / 10; } @@ -3898,7 +3752,7 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { - if (!g_chainstate.LoadBlockIndex(chainparams.GetConsensus(), *pblocktree)) + if (!::ChainstateActive().LoadBlockIndex(chainparams.GetConsensus(), *pblocktree)) return false; // Load block file info @@ -3963,7 +3817,7 @@ bool LoadChainTip(const CChainParams& chainparams) } ::ChainActive().SetTip(pindex); - g_chainstate.PruneBlockIndexCandidates(); + ::ChainstateActive().PruneBlockIndexCandidates(); LogPrintf("Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n", ::ChainActive().Tip()->GetBlockHash().ToString(), ::ChainActive().Height(), @@ -4036,7 +3890,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, // check level 3: check for inconsistencies during memory-only disconnect of tip blocks if (nCheckLevel >= 3 && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) { assert(coins.GetBestBlock() == pindex->GetBlockHash()); - DisconnectResult res = g_chainstate.DisconnectBlock(block, pindex, coins); + DisconnectResult res = ::ChainstateActive().DisconnectBlock(block, pindex, coins); if (res == DISCONNECT_FAILED) { return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); } @@ -4071,7 +3925,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, CBlock block; if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus())) return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); - if (!g_chainstate.ConnectBlock(block, state, pindex, coins, chainparams)) + if (!::ChainstateActive().ConnectBlock(block, state, pindex, coins, chainparams)) return error("VerifyDB(): *** found unconnectable block at %d, hash=%s (%s)", pindex->nHeight, pindex->GetBlockHash().ToString(), FormatStateMessage(state)); } } @@ -4170,7 +4024,7 @@ bool CChainState::ReplayBlocks(const CChainParams& params, CCoinsView* view) } bool ReplayBlocks(const CChainParams& params, CCoinsView* view) { - return g_chainstate.ReplayBlocks(params, view); + return ::ChainstateActive().ReplayBlocks(params, view); } //! Helper for CChainState::RewindBlockIndex @@ -4303,7 +4157,7 @@ bool CChainState::RewindBlockIndex(const CChainParams& params) } bool RewindBlockIndex(const CChainParams& params) { - if (!g_chainstate.RewindBlockIndex(params)) { + if (!::ChainstateActive().RewindBlockIndex(params)) { return false; } @@ -4313,7 +4167,7 @@ bool RewindBlockIndex(const CChainParams& params) { // and skip it here, we're about to -reindex-chainstate anyway, so // it'll get called a bunch real soon. CValidationState state; - if (!FlushStateToDisk(params, state, FlushStateMode::ALWAYS)) { + if (!::ChainstateActive().FlushStateToDisk(params, state, FlushStateMode::ALWAYS)) { LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", FormatStateMessage(state)); return false; } @@ -4354,7 +4208,7 @@ void UnloadBlockIndex() mapBlockIndex.clear(); fHavePruned = false; - g_chainstate.UnloadBlockIndex(); + ::ChainstateActive().UnloadBlockIndex(); } bool LoadBlockIndex(const CChainParams& chainparams) @@ -4406,7 +4260,7 @@ bool CChainState::LoadGenesisBlock(const CChainParams& chainparams) bool LoadGenesisBlock(const CChainParams& chainparams) { - return g_chainstate.LoadGenesisBlock(chainparams); + return ::ChainstateActive().LoadGenesisBlock(chainparams); } bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFilePos *dbp) @@ -4471,7 +4325,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFi CBlockIndex* pindex = LookupBlockIndex(hash); if (!pindex || (pindex->nStatus & BLOCK_HAVE_DATA) == 0) { CValidationState state; - if (g_chainstate.AcceptBlock(pblock, state, chainparams, nullptr, true, dbp, nullptr)) { + if (::ChainstateActive().AcceptBlock(pblock, state, chainparams, nullptr, true, dbp, nullptr)) { nLoaded++; } if (state.IsError()) { @@ -4508,7 +4362,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, FlatFi head.ToString()); LOCK(cs_main); CValidationState dummy; - if (g_chainstate.AcceptBlock(pblockrecursive, dummy, chainparams, nullptr, true, &it->second, nullptr)) + if (::ChainstateActive().AcceptBlock(pblockrecursive, dummy, chainparams, nullptr, true, &it->second, nullptr)) { nLoaded++; queue.push_back(pblockrecursive->GetHash()); diff --git a/src/validation.h b/src/validation.h index ad978f0e05..963439d35b 100644 --- a/src/validation.h +++ b/src/validation.h @@ -31,6 +31,7 @@ #include <utility> #include <vector> +class CChainState; class CBlockIndex; class CBlockTreeDB; class CBlockUndo; @@ -44,6 +45,7 @@ class CTxMemPool; class CValidationState; struct ChainTxData; +struct DisconnectedBlockTransactions; struct PrecomputedTransactionData; struct LockPoints; @@ -247,8 +249,6 @@ bool LoadChainTip(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_m void UnloadBlockIndex(); /** Run an instance of the script checking thread */ void ThreadScriptCheck(int worker_num); -/** Check whether we are doing an initial block download (synchronizing from disk or network) */ -bool IsInitialBlockDownload(); /** Retrieve a transaction (from memory pool, or from disk, if possible) */ bool GetTransaction(const uint256& hash, CTransactionRef& tx, const Consensus::Params& params, uint256& hashBlock, const CBlockIndex* const blockIndex = nullptr); /** @@ -276,10 +276,6 @@ void PruneOneBlockFile(const int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main); */ void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune); -/** Flush all state, indexes and buffers to disk. */ -void FlushStateToDisk(); -/** Prune block files and flush state to disk. */ -void PruneAndFlush(); /** Prune block files up to a given height */ void PruneBlockFilesManual(int nManualPruneHeight); @@ -422,6 +418,186 @@ inline CBlockIndex* LookupBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIR /** Find the last common block between the parameter chain and a locator. */ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) EXCLUSIVE_LOCKS_REQUIRED(cs_main); +enum DisconnectResult +{ + DISCONNECT_OK, // All good. + DISCONNECT_UNCLEAN, // Rolled back, but UTXO set was inconsistent with block. + DISCONNECT_FAILED // Something else went wrong. +}; + +class ConnectTrace; + +/** @see CChainState::FlushStateToDisk */ +enum class FlushStateMode { + NONE, + IF_NEEDED, + PERIODIC, + ALWAYS +}; + +struct CBlockIndexWorkComparator +{ + bool operator()(const CBlockIndex *pa, const CBlockIndex *pb) const; +}; + +/** + * CChainState stores and provides an API to update our local knowledge of the + * current best chain and header tree. + * + * It generally provides access to the current block tree, as well as functions + * to provide new data, which it will appropriately validate and incorporate in + * its state as necessary. + * + * Eventually, the API here is targeted at being exposed externally as a + * consumable libconsensus library, so any functions added must only call + * other class member functions, pure functions in other parts of the consensus + * library, callbacks via the validation interface, or read/write-to-disk + * functions (eventually this will also be via callbacks). + */ +class CChainState { +private: + /** + * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for itself and all ancestors) and + * as good as our current tip or better. Entries may be failed, though, and pruning nodes may be + * missing the data for the block. + */ + std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates; + + /** + * Every received block is assigned a unique and increasing identifier, so we + * know which one to give priority in case of a fork. + */ + CCriticalSection cs_nBlockSequenceId; + /** Blocks loaded from disk are assigned id 0, so start the counter at 1. */ + int32_t nBlockSequenceId = 1; + /** Decreasing counter (used by subsequent preciousblock calls). */ + int32_t nBlockReverseSequenceId = -1; + /** chainwork for the last block that preciousblock has been applied to. */ + arith_uint256 nLastPreciousChainwork = 0; + + /** In order to efficiently track invalidity of headers, we keep the set of + * blocks which we tried to connect and found to be invalid here (ie which + * were set to BLOCK_FAILED_VALID since the last restart). We can then + * walk this set and check if a new header is a descendant of something in + * this set, preventing us from having to walk mapBlockIndex when we try + * to connect a bad block and fail. + * + * While this is more complicated than marking everything which descends + * from an invalid block as invalid at the time we discover it to be + * invalid, doing so would require walking all of mapBlockIndex to find all + * descendants. Since this case should be very rare, keeping track of all + * BLOCK_FAILED_VALID blocks in a set should be just fine and work just as + * well. + * + * Because we already walk mapBlockIndex in height-order at startup, we go + * ahead and mark descendants of invalid blocks as FAILED_CHILD at that time, + * instead of putting things in this set. + */ + std::set<CBlockIndex*> m_failed_blocks; + + /** + * the ChainState CriticalSection + * A lock that must be held when modifying this ChainState - held in ActivateBestChain() + */ + CCriticalSection m_cs_chainstate; + + /** + * Whether this chainstate is undergoing initial block download. + * + * Mutable because we need to be able to mark IsInitialBlockDownload() + * const, which latches this for caching purposes. + */ + mutable std::atomic<bool> m_cached_finished_ibd{false}; + +public: + //! The current chain of blockheaders we consult and build on. + //! @see CChain, CBlockIndex. + CChain m_chain; + BlockMap mapBlockIndex GUARDED_BY(cs_main); + std::multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked; + CBlockIndex *pindexBestInvalid = nullptr; + + bool LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + + /** + * Update the on-disk chain state. + * The caches and indexes are flushed depending on the mode we're called with + * if they're too large, if it's been a while since the last write, + * or always and in all cases if we're in prune mode and are deleting files. + * + * If FlushStateMode::NONE is used, then FlushStateToDisk(...) won't do anything + * besides checking if we need to prune. + */ + bool FlushStateToDisk( + const CChainParams& chainparams, + CValidationState &state, + FlushStateMode mode, + int nManualPruneHeight = 0); + + //! Unconditionally flush all changes to disk. + void ForceFlushStateToDisk(); + + //! Prune blockfiles from the disk if necessary and then flush chainstate changes + //! if we pruned. + void PruneAndFlush(); + + bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock) LOCKS_EXCLUDED(cs_main); + + /** + * If a block header hasn't already been seen, call CheckBlockHeader on it, ensure + * that it doesn't descend from an invalid block, and then add it to mapBlockIndex. + */ + bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + + // Block (dis)connection on a given view: + DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view); + bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, + CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + + // Block disconnection on our pcoinsTip: + bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions* disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + + // Manual block validity manipulation: + bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main); + bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main); + void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + + bool ReplayBlocks(const CChainParams& params, CCoinsView* view); + bool RewindBlockIndex(const CChainParams& params) LOCKS_EXCLUDED(cs_main); + bool LoadGenesisBlock(const CChainParams& chainparams); + + void PruneBlockIndexCandidates(); + + void UnloadBlockIndex(); + + /** Check whether we are doing an initial block download (synchronizing from disk or network) */ + bool IsInitialBlockDownload() const; + +private: + bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + + CBlockIndex* AddToBlockIndex(const CBlockHeader& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + /** Create a new block index entry for a given block hash */ + CBlockIndex* InsertBlockIndex(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + /** + * Make various assertions about the state of the block index. + * + * By default this only executes fully when using the Regtest chain; see: fCheckBlockIndex. + */ + void CheckBlockIndex(const Consensus::Params& consensusParams); + + void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main); + void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + + bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main); + + //! Mark a block as not having block data + void EraseBlockData(CBlockIndex* index) EXCLUSIVE_LOCKS_REQUIRED(cs_main); +}; + /** Mark a block as precious and reorganize. * * May not be called in a @@ -435,6 +611,9 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C /** Remove invalidity status from a block and its descendants. */ void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); +/** @returns the most-work valid chainstate. */ +CChainState& ChainstateActive(); + /** @returns the most-work chain. */ CChain& ChainActive(); diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 5d0ee1d1fc..59a620ab95 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -8,8 +8,6 @@ #include <primitives/block.h> #include <scheduler.h> #include <txmempool.h> -#include <util/system.h> -#include <validation.h> #include <list> #include <atomic> diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 8633d8701b..b5f90deabd 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -5,11 +5,7 @@ #include <wallet/db.h> -#include <addrman.h> -#include <hash.h> -#include <protocol.h> #include <util/strencodings.h> -#include <wallet/walletutil.h> #include <stdint.h> diff --git a/src/wallet/feebumper.cpp b/src/wallet/feebumper.cpp index 15ddd5cb97..46cf6b7616 100644 --- a/src/wallet/feebumper.cpp +++ b/src/wallet/feebumper.cpp @@ -10,14 +10,10 @@ #include <wallet/wallet.h> #include <policy/fees.h> #include <policy/policy.h> -#include <policy/rbf.h> -#include <validation.h> //for mempool access -#include <txmempool.h> #include <util/moneystr.h> #include <util/rbf.h> #include <util/system.h> #include <util/validation.h> -#include <net.h> //! Check whether transaction has descendant in wallet or mempool, or has been //! mined, or conflicts with a mined transaction. Return a feebumper::Result. diff --git a/src/wallet/fees.cpp b/src/wallet/fees.cpp index 59d05a771a..ad69e84358 100644 --- a/src/wallet/fees.cpp +++ b/src/wallet/fees.cpp @@ -5,9 +5,7 @@ #include <wallet/fees.h> -#include <policy/policy.h> #include <util/system.h> -#include <validation.h> #include <wallet/coincontrol.h> #include <wallet/wallet.h> diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index 0b8afd5a5d..00d2a59a66 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -3,18 +3,13 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <chainparams.h> #include <init.h> #include <interfaces/chain.h> #include <net.h> -#include <scheduler.h> #include <outputtype.h> -#include <util/error.h> #include <util/system.h> #include <util/moneystr.h> -#include <validation.h> #include <walletinitinterface.h> -#include <wallet/rpcwallet.h> #include <wallet/wallet.h> #include <wallet/walletutil.h> diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index ee1b792f9b..3112dca9f5 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -16,7 +16,6 @@ #include <util/bip32.h> #include <util/system.h> #include <util/time.h> -#include <validation.h> #include <wallet/wallet.h> #include <wallet/rpcwallet.h> @@ -1166,8 +1165,7 @@ static UniValue ProcessImportDescriptor(ImportData& import_data, std::map<CKeyID const UniValue& priv_keys = data.exists("keys") ? data["keys"].get_array() : UniValue(); - // Expand all descriptors to get public keys and scripts. - // TODO: get private keys from descriptors too + // Expand all descriptors to get public keys and scripts, and private keys if available. for (int i = range_start; i <= range_end; ++i) { FlatSigningProvider out_keys; std::vector<CScript> scripts_temp; @@ -1181,7 +1179,10 @@ static UniValue ProcessImportDescriptor(ImportData& import_data, std::map<CKeyID import_data.import_scripts.emplace(x.second); } + parsed_desc->ExpandPrivate(i, keys, out_keys); + std::copy(out_keys.pubkeys.begin(), out_keys.pubkeys.end(), std::inserter(pubkey_map, pubkey_map.end())); + std::copy(out_keys.keys.begin(), out_keys.keys.end(), std::inserter(privkey_map, privkey_map.end())); import_data.key_origins.insert(out_keys.origins.begin(), out_keys.origins.end()); } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 71d62a47dc..29880002b3 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4,33 +4,27 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <amount.h> -#include <chain.h> #include <consensus/validation.h> #include <core_io.h> #include <init.h> #include <interfaces/chain.h> #include <key_io.h> -#include <net.h> #include <node/transaction.h> #include <outputtype.h> #include <policy/feerate.h> #include <policy/fees.h> -#include <policy/policy.h> #include <policy/rbf.h> #include <rpc/rawtransaction_util.h> #include <rpc/server.h> #include <rpc/util.h> #include <script/descriptor.h> #include <script/sign.h> -#include <shutdown.h> -#include <timedata.h> #include <util/bip32.h> #include <util/fees.h> #include <util/moneystr.h> #include <util/system.h> #include <util/url.h> #include <util/validation.h> -#include <validation.h> #include <wallet/coincontrol.h> #include <wallet/feebumper.h> #include <wallet/psbtwallet.h> @@ -2124,6 +2118,10 @@ static UniValue encryptwallet(const JSONRPCRequest& request) auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); + if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { + throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: wallet does not contain private keys, nothing to encrypt."); + } + if (pwallet->IsCrypted()) { throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called."); } diff --git a/src/wallet/test/init_tests.cpp b/src/wallet/test/init_tests.cpp index 9e5208b453..67e2847963 100644 --- a/src/wallet/test/init_tests.cpp +++ b/src/wallet/test/init_tests.cpp @@ -7,11 +7,6 @@ #include <test/setup_common.h> #include <wallet/test/init_test_fixture.h> -#include <init.h> -#include <walletinitinterface.h> -#include <wallet/wallet.h> - - BOOST_FIXTURE_TEST_SUITE(init_tests, InitWalletDirTestingSetup) BOOST_AUTO_TEST_CASE(walletinit_verify_walletdir_default) diff --git a/src/wallet/test/psbt_wallet_tests.cpp b/src/wallet/test/psbt_wallet_tests.cpp index 4753c7f313..cdf7113203 100644 --- a/src/wallet/test/psbt_wallet_tests.cpp +++ b/src/wallet/test/psbt_wallet_tests.cpp @@ -7,7 +7,6 @@ #include <util/bip32.h> #include <util/strencodings.h> #include <wallet/psbtwallet.h> -#include <wallet/rpcwallet.h> #include <wallet/wallet.h> #include <univalue.h> diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp index e352c81519..7db0bc4249 100644 --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -4,9 +4,7 @@ #include <wallet/test/wallet_test_fixture.h> -#include <rpc/server.h> #include <wallet/db.h> -#include <wallet/rpcwallet.h> WalletTestingSetup::WalletTestingSetup(const std::string& chainName) : TestingSetup(chainName), diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e86147b5d0..bde52d7791 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -14,17 +14,12 @@ #include <key.h> #include <key_io.h> #include <keystore.h> -#include <net.h> #include <policy/fees.h> #include <policy/policy.h> -#include <policy/rbf.h> #include <primitives/block.h> #include <primitives/transaction.h> #include <script/descriptor.h> #include <script/script.h> -#include <shutdown.h> -#include <timedata.h> -#include <txmempool.h> #include <util/bip32.h> #include <util/error.h> #include <util/fees.h> diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp index c6132a2686..440c32c367 100644 --- a/src/wallet/wallettool.cpp +++ b/src/wallet/wallettool.cpp @@ -2,7 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <base58.h> #include <fs.h> #include <util/system.h> #include <wallet/wallet.h> diff --git a/src/warnings.cpp b/src/warnings.cpp index 8ac9ee09db..5542412a7f 100644 --- a/src/warnings.cpp +++ b/src/warnings.cpp @@ -4,7 +4,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <sync.h> -#include <clientversion.h> #include <util/system.h> #include <warnings.h> diff --git a/src/zmq/zmqabstractnotifier.cpp b/src/zmq/zmqabstractnotifier.cpp index 6a9661e3e8..a5f3be8f5b 100644 --- a/src/zmq/zmqabstractnotifier.cpp +++ b/src/zmq/zmqabstractnotifier.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <zmq/zmqabstractnotifier.h> -#include <util/system.h> const int CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM; diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 6826cf62d6..de59b71b8f 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -7,7 +7,6 @@ #include <version.h> #include <validation.h> -#include <streams.h> #include <util/system.h> void zmqError(const char *str) diff --git a/test/functional/wallet_createwallet.py b/test/functional/wallet_createwallet.py index fc7969ad19..c17949a2f6 100755 --- a/test/functional/wallet_createwallet.py +++ b/test/functional/wallet_createwallet.py @@ -92,7 +92,7 @@ class CreateWalletTest(BitcoinTestFramework): assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getnewaddress) assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getrawchangeaddress) # Encrypt the wallet - w5.encryptwallet('pass') + assert_raises_rpc_error(-16, "Error: wallet does not contain private keys, nothing to encrypt.", w5.encryptwallet, 'pass') assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getnewaddress) assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getrawchangeaddress) diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py index 7d652a7825..e19c7919a9 100755 --- a/test/functional/wallet_importmulti.py +++ b/test/functional/wallet_importmulti.py @@ -571,6 +571,7 @@ class ImportMultiTest(BitcoinTestFramework): # Test ranged descriptor fails if range is not specified xpriv = "tprv8ZgxMBicQKsPeuVhWwi6wuMQGfPKi9Li5GtX35jVNknACgqe3CY4g5xgkfDDJcmtF7o1QnxWDRYw4H5P26PXq7sbcUkEqeR4fg3Kxp2tigg" addresses = ["2N7yv4p8G8yEaPddJxY41kPihnWvs39qCMf", "2MsHxyb2JS3pAySeNUsJ7mNnurtpeenDzLA"] # hdkeypath=m/0'/0'/0' and 1' + addresses += ["bcrt1qrd3n235cj2czsfmsuvqqpr3lu6lg0ju7scl8gn", "bcrt1qfqeppuvj0ww98r6qghmdkj70tv8qpchehegrg8"] # wpkh subscripts corresponding to the above addresses desc = "sh(wpkh(" + xpriv + "/0'/0'/*'" + "))" self.log.info("Ranged descriptor import should fail without a specified range") self.test_importmulti({"desc": descsum_create(desc), @@ -579,17 +580,17 @@ class ImportMultiTest(BitcoinTestFramework): error_code=-8, error_message='Descriptor is ranged, please specify the range') - # Test importing of a ranged descriptor without keys + # Test importing of a ranged descriptor with xpriv self.log.info("Should import the ranged descriptor with specified range as solvable") self.test_importmulti({"desc": descsum_create(desc), "timestamp": "now", "range": 1}, - success=True, - warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."]) + success=True) for address in addresses: test_address(self.nodes[1], - key.p2sh_p2wpkh_addr, - solvable=True) + address, + solvable=True, + ismine=True) self.test_importmulti({"desc": descsum_create(desc), "timestamp": "now", "range": -1}, success=False, error_code=-8, error_message='End of range is too high') @@ -606,6 +607,23 @@ class ImportMultiTest(BitcoinTestFramework): self.test_importmulti({"desc": descsum_create(desc), "timestamp": "now", "range": [0, 1000001]}, success=False, error_code=-8, error_message='Range is too large') + # Test importing a descriptor containing a WIF private key + wif_priv = "cTe1f5rdT8A8DFgVWTjyPwACsDPJM9ff4QngFxUixCSvvbg1x6sh" + address = "2MuhcG52uHPknxDgmGPsV18jSHFBnnRgjPg" + desc = "sh(wpkh(" + wif_priv + "))" + self.log.info("Should import a descriptor with a WIF private key as spendable") + self.test_importmulti({"desc": descsum_create(desc), + "timestamp": "now"}, + success=True) + test_address(self.nodes[1], + address, + solvable=True, + ismine=True) + + # dump the private key to ensure it matches what was imported + privkey = self.nodes[1].dumpprivkey(address) + assert_equal(privkey, wif_priv) + # Test importing of a P2PKH address via descriptor key = get_key(self.nodes[0]) self.log.info("Should import a p2pkh address from descriptor") diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh index e1a99abc49..2701015c79 100755 --- a/test/lint/lint-circular-dependencies.sh +++ b/test/lint/lint-circular-dependencies.sh @@ -12,7 +12,6 @@ EXPECTED_CIRCULAR_DEPENDENCIES=( "chainparamsbase -> util/system -> chainparamsbase" "index/txindex -> validation -> index/txindex" "policy/fees -> txmempool -> policy/fees" - "policy/policy -> policy/settings -> policy/policy" "qt/addresstablemodel -> qt/walletmodel -> qt/addresstablemodel" "qt/bantablemodel -> qt/clientmodel -> qt/bantablemodel" "qt/bitcoingui -> qt/utilitydialog -> qt/bitcoingui" @@ -25,18 +24,12 @@ EXPECTED_CIRCULAR_DEPENDENCIES=( "qt/transactiontablemodel -> qt/walletmodel -> qt/transactiontablemodel" "qt/walletmodel -> qt/walletmodeltransaction -> qt/walletmodel" "txmempool -> validation -> txmempool" - "validation -> validationinterface -> validation" "wallet/coincontrol -> wallet/wallet -> wallet/coincontrol" "wallet/fees -> wallet/wallet -> wallet/fees" "wallet/wallet -> wallet/walletdb -> wallet/wallet" "policy/fees -> txmempool -> validation -> policy/fees" - "policy/rbf -> txmempool -> validation -> policy/rbf" - "qt/addressbookpage -> qt/bitcoingui -> qt/walletview -> qt/addressbookpage" "qt/guiutil -> qt/walletmodel -> qt/optionsmodel -> qt/guiutil" "txmempool -> validation -> validationinterface -> txmempool" - "qt/addressbookpage -> qt/bitcoingui -> qt/walletview -> qt/receivecoinsdialog -> qt/addressbookpage" - "qt/addressbookpage -> qt/bitcoingui -> qt/walletview -> qt/signverifymessagedialog -> qt/addressbookpage" - "qt/addressbookpage -> qt/bitcoingui -> qt/walletview -> qt/sendcoinsdialog -> qt/sendcoinsentry -> qt/addressbookpage" ) EXIT_CODE=0 |