diff --git a/.gitignore b/.gitignore index 80fa9c28fd6a..fd2d88159663 100644 --- a/.gitignore +++ b/.gitignore @@ -124,6 +124,7 @@ share/BitcoindComparisonTool.jar /doc/doxygen/ libdashconsensus.pc +contrib/devtools/split-debug.sh src/qt/dash-qt.bash qa/pull-tester/tests-config.sh diff --git a/.travis.yml b/.travis.yml index ec8b746721b7..459e31475748 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,7 +49,7 @@ env: # No wallet - HOST=x86_64-unknown-linux-gnu PPA="ppa:bitcoin/bitcoin" PACKAGES="python3" DEP_OPTS="NO_WALLET=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" # Cross-Mac - - HOST=x86_64-apple-darwin11 PPA="ppa:bitcoin/bitcoin" PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python3-dev" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" OSX_SDK=10.9 GOAL="deploy" + - HOST=x86_64-apple-darwin11 PPA="ppa:bitcoin/bitcoin" PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python3-dev" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" OSX_SDK=10.11 GOAL="deploy" before_install: - git clone https://github.com/dashpay/dash_hash diff --git a/README.md b/README.md index f8c7114ef784..9f9b40845f37 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ https://www.dash.org What is Dash? ---------------- -Dash is an experimental new digital currency that enables anonymous, instant +Dash is an experimental digital currency that enables anonymous, instant payments to anyone, anywhere in the world. Dash uses peer-to-peer technology to operate with no central authority: managing transactions and issuing money are carried out collectively by the network. Dash Core is the name of the open diff --git a/build-aux/m4/ax_pthread.m4 b/build-aux/m4/ax_pthread.m4 index d218d1af7381..4c4051ea376f 100644 --- a/build-aux/m4/ax_pthread.m4 +++ b/build-aux/m4/ax_pthread.m4 @@ -82,7 +82,7 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 22 +#serial 23 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ @@ -100,22 +100,22 @@ ax_pthread_ok=no # etcetera environment variables, and if threads linking works using # them: if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then - ax_pthread_save_CC="$CC" - ax_pthread_save_CFLAGS="$CFLAGS" - ax_pthread_save_LIBS="$LIBS" - AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) - AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) - AC_MSG_RESULT([$ax_pthread_ok]) - if test "x$ax_pthread_ok" = "xno"; then - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" - fi - CC="$ax_pthread_save_CC" - CFLAGS="$ax_pthread_save_CFLAGS" - LIBS="$ax_pthread_save_LIBS" + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) + AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" fi # We must check for the threads library under a number of different @@ -152,50 +152,50 @@ ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread -- case $host_os in - freebsd*) + freebsd*) - # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) - # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) - ax_pthread_flags="-kthread lthread $ax_pthread_flags" - ;; + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; - hpux*) + hpux*) - # From the cc(1) man page: "[-mt] Sets various -D flags to enable - # multi-threading and also sets -lpthread." + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." - ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" - ;; + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; - openedition*) + openedition*) - # IBM z/OS requires a feature-test macro to be defined in order to - # enable POSIX threads at all, so give the user a hint if this is - # not set. (We don't define these ourselves, as they can affect - # other portions of the system API in unpredictable ways.) + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) - AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], - [ -# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) - AX_PTHREAD_ZOS_MISSING -# endif - ], - [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) - ;; + AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], + [ +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + ], + [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) + ;; - solaris*) + solaris*) - # On Solaris (at least, for some versions), libc contains stubbed - # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (N.B.: The stubs are missing - # pthread_cleanup_push, or rather a function called by this macro, - # so we could check for that, but who knows whether they'll stub - # that too in a future libc.) So we'll check first for the - # standard Solaris way of linking pthreads (-mt -lpthread). + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). - ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" - ;; + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ;; esac # GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) @@ -208,17 +208,17 @@ AS_IF([test "x$GCC" = "xyes"], # correctly enabled case $host_os in - darwin* | hpux* | linux* | osf* | solaris*) - ax_pthread_check_macro="_REENTRANT" - ;; + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; - aix* | freebsd*) - ax_pthread_check_macro="_THREAD_SAFE" - ;; + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; - *) - ax_pthread_check_macro="--" - ;; + *) + ax_pthread_check_macro="--" + ;; esac AS_IF([test "x$ax_pthread_check_macro" = "x--"], [ax_pthread_check_cond=0], @@ -231,13 +231,13 @@ AC_CACHE_CHECK([whether $CC is Clang], [ax_cv_PTHREAD_CLANG=no # Note that Autoconf sets GCC=yes for Clang as well as GCC if test "x$GCC" = "xyes"; then - AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], - [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ -# if defined(__clang__) && defined(__llvm__) - AX_PTHREAD_CC_IS_CLANG -# endif - ], - [ax_cv_PTHREAD_CLANG=yes]) + AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], + [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + ], + [ax_cv_PTHREAD_CLANG=yes]) fi ]) ax_pthread_clang="$ax_cv_PTHREAD_CLANG" @@ -249,222 +249,222 @@ ax_pthread_clang_warning=no if test "x$ax_pthread_clang" = "xyes"; then - # Clang takes -pthread; it has never supported any other flag - - # (Note 1: This will need to be revisited if a system that Clang - # supports has POSIX threads in a separate library. This tends not - # to be the way of modern systems, but it's conceivable.) - - # (Note 2: On some systems, notably Darwin, -pthread is not needed - # to get POSIX threads support; the API is always present and - # active. We could reasonably leave PTHREAD_CFLAGS empty. But - # -pthread does define _REENTRANT, and while the Darwin headers - # ignore this macro, third-party headers might not.) - - PTHREAD_CFLAGS="-pthread" - PTHREAD_LIBS= - - ax_pthread_ok=yes - - # However, older versions of Clang make a point of warning the user - # that, in an invocation where only linking and no compilation is - # taking place, the -pthread option has no effect ("argument unused - # during compilation"). They expect -pthread to be passed in only - # when source code is being compiled. - # - # Problem is, this is at odds with the way Automake and most other - # C build frameworks function, which is that the same flags used in - # compilation (CFLAGS) are also used in linking. Many systems - # supported by AX_PTHREAD require exactly this for POSIX threads - # support, and in fact it is often not straightforward to specify a - # flag that is used only in the compilation phase and not in - # linking. Such a scenario is extremely rare in practice. - # - # Even though use of the -pthread flag in linking would only print - # a warning, this can be a nuisance for well-run software projects - # that build with -Werror. So if the active version of Clang has - # this misfeature, we search for an option to squash it. - - AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], - [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], - [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown - # Create an alternate version of $ac_link that compiles and - # links in two steps (.c -> .o, .o -> exe) instead of one - # (.c -> exe), because the warning occurs only in the second - # step - ax_pthread_save_ac_link="$ac_link" - ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' - ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` - ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" - ax_pthread_save_CFLAGS="$CFLAGS" - for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do - AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) - CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" - ac_link="$ax_pthread_save_ac_link" - AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], - [ac_link="$ax_pthread_2step_ac_link" - AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], - [break]) - ]) - done - ac_link="$ax_pthread_save_ac_link" - CFLAGS="$ax_pthread_save_CFLAGS" - AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) - ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" - ]) - - case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in - no | unknown) ;; - *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; - esac + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [ac_link="$ax_pthread_2step_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [break]) + ]) + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + ]) + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac fi # $ax_pthread_clang = yes if test "x$ax_pthread_ok" = "xno"; then for ax_pthread_try_flag in $ax_pthread_flags; do - case $ax_pthread_try_flag in - none) - AC_MSG_CHECKING([whether pthreads work without any flags]) - ;; - - -mt,pthread) - AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) - PTHREAD_CFLAGS="-mt" - PTHREAD_LIBS="-lpthread" - ;; - - -*) - AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) - PTHREAD_CFLAGS="$ax_pthread_try_flag" - ;; - - pthread-config) - AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) - AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) - PTHREAD_CFLAGS="`pthread-config --cflags`" - PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" - ;; - - *) - AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) - PTHREAD_LIBS="-l$ax_pthread_try_flag" - ;; - esac - - ax_pthread_save_CFLAGS="$CFLAGS" - ax_pthread_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - - # Check for various functions. We must include pthread.h, - # since some functions may be macros. (On the Sequent, we - # need a special flag -Kthread to make this header compile.) - # We check for pthread_join because it is in -lpthread on IRIX - # while pthread_create is in libc. We check for pthread_attr_init - # due to DEC craziness with -lpthreads. We check for - # pthread_cleanup_push because it is one of the few pthread - # functions on Solaris that doesn't have a non-functional libc stub. - # We try pthread_create on general principles. - - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include -# if $ax_pthread_check_cond -# error "$ax_pthread_check_macro must be defined" -# endif - static void routine(void *a) { a = 0; } - static void *start_routine(void *a) { return a; }], - [pthread_t th; pthread_attr_t attr; - pthread_create(&th, 0, start_routine, 0); - pthread_join(th, 0); - pthread_attr_init(&attr); - pthread_cleanup_push(routine, 0); - pthread_cleanup_pop(0) /* ; */])], - [ax_pthread_ok=yes], - []) - - CFLAGS="$ax_pthread_save_CFLAGS" - LIBS="$ax_pthread_save_LIBS" - - AC_MSG_RESULT([$ax_pthread_ok]) - AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) - - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" + case $ax_pthread_try_flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -mt,pthread) + AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void routine(void *a) { a = 0; } + static void *start_routine(void *a) { return a; }], + [pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */])], + [ax_pthread_ok=yes], + []) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + AC_MSG_RESULT([$ax_pthread_ok]) + AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$ax_pthread_ok" = "xyes"; then - ax_pthread_save_CFLAGS="$CFLAGS" - ax_pthread_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - - # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. - AC_CACHE_CHECK([for joinable pthread attribute], - [ax_cv_PTHREAD_JOINABLE_ATTR], - [ax_cv_PTHREAD_JOINABLE_ATTR=unknown - for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], - [int attr = $ax_pthread_attr; return attr /* ; */])], - [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], - []) - done - ]) - AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ - test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ - test "x$ax_pthread_joinable_attr_defined" != "xyes"], - [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], - [$ax_cv_PTHREAD_JOINABLE_ATTR], - [Define to necessary symbol if this constant - uses a non-standard name on your system.]) - ax_pthread_joinable_attr_defined=yes - ]) - - AC_CACHE_CHECK([whether more special flags are required for pthreads], - [ax_cv_PTHREAD_SPECIAL_FLAGS], - [ax_cv_PTHREAD_SPECIAL_FLAGS=no - case $host_os in - solaris*) - ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" - ;; - esac - ]) - AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ - test "x$ax_pthread_special_flags_added" != "xyes"], - [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" - ax_pthread_special_flags_added=yes]) - - AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], - [ax_cv_PTHREAD_PRIO_INHERIT], - [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[int i = PTHREAD_PRIO_INHERIT;]])], - [ax_cv_PTHREAD_PRIO_INHERIT=yes], - [ax_cv_PTHREAD_PRIO_INHERIT=no]) - ]) - AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ - test "x$ax_pthread_prio_inherit_defined" != "xyes"], - [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) - ax_pthread_prio_inherit_defined=yes - ]) - - CFLAGS="$ax_pthread_save_CFLAGS" - LIBS="$ax_pthread_save_LIBS" - - # More AIX lossage: compile with *_r variant - if test "x$GCC" != "xyes"; then - case $host_os in - aix*) - AS_CASE(["x/$CC"], - [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], - [#handle absolute path differently from PATH based program lookup - AS_CASE(["x$CC"], - [x/*], - [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], - [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) - ;; - esac - fi + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_CACHE_CHECK([for joinable pthread attribute], + [ax_cv_PTHREAD_JOINABLE_ATTR], + [ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $ax_pthread_attr; return attr /* ; */])], + [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], + []) + done + ]) + AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"], + [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], + [$ax_cv_PTHREAD_JOINABLE_ATTR], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + ax_pthread_joinable_attr_defined=yes + ]) + + AC_CACHE_CHECK([whether more special flags are required for pthreads], + [ax_cv_PTHREAD_SPECIAL_FLAGS], + [ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + ]) + AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"], + [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes]) + + AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + [ax_cv_PTHREAD_PRIO_INHERIT], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) + ]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) + ax_pthread_prio_inherit_defined=yes + ]) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + AS_CASE(["x/$CC"], + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + ;; + esac + fi fi test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" @@ -475,11 +475,11 @@ AC_SUBST([PTHREAD_CC]) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test "x$ax_pthread_ok" = "xyes"; then - ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) - : + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) + : else - ax_pthread_ok=no - $2 + ax_pthread_ok=no + $2 fi AC_LANG_POP ])dnl AX_PTHREAD diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index b09a5fb7112d..20f51163a6e6 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -346,8 +346,9 @@ AC_DEFUN([_BITCOIN_QT_FIND_STATIC_PLUGINS],[ QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible" fi fi - m4_ifdef([PKG_CHECK_MODULES],[ if test x$use_pkgconfig = xyes; then + : dnl + m4_ifdef([PKG_CHECK_MODULES],[ PKG_CHECK_MODULES([QTPLATFORM], [Qt5PlatformSupport], [QT_LIBS="$QTPLATFORM_LIBS $QT_LIBS"]) if test x$TARGET_OS = xlinux; then PKG_CHECK_MODULES([X11XCB], [x11-xcb], [QT_LIBS="$X11XCB_LIBS $QT_LIBS"]) @@ -357,8 +358,23 @@ AC_DEFUN([_BITCOIN_QT_FIND_STATIC_PLUGINS],[ elif test x$TARGET_OS = xdarwin; then PKG_CHECK_MODULES([QTPRINT], [Qt5PrintSupport], [QT_LIBS="$QTPRINT_LIBS $QT_LIBS"]) fi - fi ]) + else + if test x$TARGET_OS = xwindows; then + AC_CACHE_CHECK(for Qt >= 5.6, bitcoin_cv_need_platformsupport,[AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[#include ]],[[ + #if QT_VERSION < 0x050600 + choke; + #endif + ]])], + [bitcoin_cv_need_platformsupport=yes], + [bitcoin_cv_need_platformsupport=no]) + ]) + if test x$bitcoin_cv_need_platformsupport = xyes; then + BITCOIN_QT_CHECK(AC_CHECK_LIB([${QT_LIB_PREFIX}PlatformSupport],[main],,BITCOIN_QT_FAIL(lib$QT_LIB_PREFIXPlatformSupport not found))) + fi + fi + fi else if test x$qt_plugin_path != x; then QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible" diff --git a/configure.ac b/configure.ac index c8cf51610eaf..d57d3fc27825 100644 --- a/configure.ac +++ b/configure.ac @@ -88,9 +88,6 @@ AC_PATH_TOOL(OBJCOPY, objcopy) AC_ARG_VAR(PYTHONPATH, Augments the default search path for python module files) -dnl pkg-config check. -PKG_PROG_PKG_CONFIG - # Enable wallet AC_ARG_ENABLE([wallet], [AS_HELP_STRING([--disable-wallet], @@ -385,6 +382,16 @@ case $host in ;; esac +if test x$use_pkgconfig = xyes; then + m4_ifndef([PKG_PROG_PKG_CONFIG], [AC_MSG_ERROR(PKG_PROG_PKG_CONFIG macro not found. Please install pkg-config and re-run autogen.sh.)]) + m4_ifdef([PKG_PROG_PKG_CONFIG], [ + PKG_PROG_PKG_CONFIG + if test x"$PKG_CONFIG" = "x"; then + AC_MSG_ERROR(pkg-config not found.) + fi + ]) +fi + if test x$use_comparison_tool != xno; then AC_SUBST(JAVA_COMPARISON_TOOL, $use_comparison_tool) fi @@ -593,7 +600,7 @@ BITCOIN_QT_INIT dnl sets $bitcoin_enable_qt, $bitcoin_enable_qt_test, $bitcoin_enable_qt_dbus BITCOIN_QT_CONFIGURE([$use_pkgconfig], [qt5]) -if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests = xnononono; then +if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnonononono; then use_boost=no else use_boost=yes @@ -762,12 +769,7 @@ fi fi if test x$use_pkgconfig = xyes; then - - if test x"$PKG_CONFIG" = "x"; then - AC_MSG_ERROR(pkg-config not found.) - fi - - : #NOP + : dnl m4_ifdef( [PKG_CHECK_MODULES], [ @@ -1068,6 +1070,13 @@ AC_SUBST(TESTDEFS) AC_SUBST(LEVELDB_TARGET_FLAGS) AC_SUBST(MINIUPNPC_CPPFLAGS) AC_SUBST(MINIUPNPC_LIBS) +AC_SUBST(CRYPTO_LIBS) +AC_SUBST(SSL_LIBS) +AC_SUBST(EVENT_LIBS) +AC_SUBST(EVENT_PTHREADS_LIBS) +AC_SUBST(ZMQ_LIBS) +AC_SUBST(PROTOBUF_LIBS) +AC_SUBST(QR_LIBS) AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py]) AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh]) AC_CONFIG_FILES([qa/pull-tester/tests_config.py],[chmod +x qa/pull-tester/tests_config.py]) diff --git a/contrib/dash-cli.bash-completion b/contrib/dash-cli.bash-completion new file mode 100644 index 000000000000..97a2531bb518 --- /dev/null +++ b/contrib/dash-cli.bash-completion @@ -0,0 +1,154 @@ +# bash programmable completion for dash-cli(1) +# Copyright (c) 2012-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# call $dash-cli for RPC +_dash_rpc() { + # determine already specified args necessary for RPC + local rpcargs=() + for i in ${COMP_LINE}; do + case "$i" in + -conf=*|-datadir=*|-regtest|-rpc*|-testnet) + rpcargs=( "${rpcargs[@]}" "$i" ) + ;; + esac + done + $dash_cli "${rpcargs[@]}" "$@" +} + +# Add wallet accounts to COMPREPLY +_dash_accounts() { + local accounts + accounts=$(_dash_rpc listaccounts | awk -F '"' '{ print $2 }') + COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "$accounts" -- "$cur" ) ) +} + +_dash_cli() { + local cur prev words=() cword + local dash_cli + + # save and use original argument to invoke dash-cli for -help, help and RPC + # as dash-cli might not be in $PATH + dash_cli="$1" + + COMPREPLY=() + _get_comp_words_by_ref -n = cur prev words cword + + if ((cword > 5)); then + case ${words[cword-5]} in + sendtoaddress) + COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) + return 0 + ;; + esac + fi + + if ((cword > 4)); then + case ${words[cword-4]} in + importaddress|listtransactions|setban) + COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) + return 0 + ;; + signrawtransaction) + COMPREPLY=( $( compgen -W "ALL NONE SINGLE ALL|ANYONECANPAY NONE|ANYONECANPAY SINGLE|ANYONECANPAY" -- "$cur" ) ) + return 0 + ;; + esac + fi + + if ((cword > 3)); then + case ${words[cword-3]} in + addmultisigaddress) + _dash_accounts + return 0 + ;; + getbalance|gettxout|importaddress|importpubkey|importprivkey|listreceivedbyaccount|listreceivedbyaddress|listsinceblock) + COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) + return 0 + ;; + esac + fi + + if ((cword > 2)); then + case ${words[cword-2]} in + addnode) + COMPREPLY=( $( compgen -W "add remove onetry" -- "$cur" ) ) + return 0 + ;; + setban) + COMPREPLY=( $( compgen -W "add remove" -- "$cur" ) ) + return 0 + ;; + fundrawtransaction|getblock|getblockheader|getmempoolancestors|getmempooldescendants|getrawtransaction|gettransaction|listaccounts|listreceivedbyaccount|listreceivedbyaddress|sendrawtransaction) + COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) + return 0 + ;; + move|setaccount) + _dash_accounts + return 0 + ;; + esac + fi + + case "$prev" in + backupwallet|dumpwallet|importwallet) + _filedir + return 0 + ;; + getaddednodeinfo|getrawmempool|lockunspent|setgenerate) + COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) + return 0 + ;; + getaccountaddress|getaddressesbyaccount|getbalance|getnewaddress|getreceivedbyaccount|listtransactions|move|sendfrom|sendmany) + _dash_accounts + return 0 + ;; + esac + + case "$cur" in + -conf=*) + cur="${cur#*=}" + _filedir + return 0 + ;; + -datadir=*) + cur="${cur#*=}" + _filedir -d + return 0 + ;; + -*=*) # prevent nonsense completions + return 0 + ;; + *) + local helpopts commands + + # only parse -help if senseful + if [[ -z "$cur" || "$cur" =~ ^- ]]; then + helpopts=$($dash_cli -help 2>&1 | awk '$1 ~ /^-/ { sub(/=.*/, "="); print $1 }' ) + fi + + # only parse help if senseful + if [[ -z "$cur" || "$cur" =~ ^[a-z] ]]; then + commands=$(_dash_rpc help 2>/dev/null | awk '$1 ~ /^[a-z]/ { print $1; }') + fi + + COMPREPLY=( $( compgen -W "$helpopts $commands" -- "$cur" ) ) + + # Prevent space if an argument is desired + if [[ $COMPREPLY == *= ]]; then + compopt -o nospace + fi + return 0 + ;; + esac +} && +complete -F _dash_cli dash-cli + +# Local variables: +# mode: shell-script +# sh-basic-offset: 4 +# sh-indent-comment: t +# indent-tabs-mode: nil +# End: +# ex: ts=4 sw=4 et filetype=sh diff --git a/contrib/dash-tx.bash-completion b/contrib/dash-tx.bash-completion new file mode 100644 index 000000000000..3cda7036090e --- /dev/null +++ b/contrib/dash-tx.bash-completion @@ -0,0 +1,57 @@ +# bash programmable completion for dash-tx(1) +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +_dash_tx() { + local cur prev words=() cword + local dash_tx + + # save and use original argument to invoke dash-tx for -help + # it might not be in $PATH + dash_tx="$1" + + COMPREPLY=() + _get_comp_words_by_ref -n =: cur prev words cword + + case "$cur" in + load=*:*) + cur="${cur#load=*:}" + _filedir + return 0 + ;; + *=*) # prevent attempts to complete other arguments + return 0 + ;; + esac + + if [[ "$cword" == 1 || ( "$prev" != "-create" && "$prev" == -* ) ]]; then + # only options (or an uncompletable hex-string) allowed + # parse dash-tx -help for options + local helpopts + helpopts=$($dash_tx -help | sed -e '/^ -/ p' -e d ) + COMPREPLY=( $( compgen -W "$helpopts" -- "$cur" ) ) + else + # only commands are allowed + # parse -help for commands + local helpcmds + helpcmds=$($dash_tx -help | sed -e '1,/Commands:/d' -e 's/=.*/=/' -e '/^ [a-z]/ p' -e d ) + COMPREPLY=( $( compgen -W "$helpcmds" -- "$cur" ) ) + fi + + # Prevent space if an argument is desired + if [[ $COMPREPLY == *= ]]; then + compopt -o nospace + fi + + return 0 +} && +complete -F _dash_tx dash-tx + +# Local variables: +# mode: shell-script +# sh-basic-offset: 4 +# sh-indent-comment: t +# indent-tabs-mode: nil +# End: +# ex: ts=4 sw=4 et filetype=sh diff --git a/contrib/dashd.bash-completion b/contrib/dashd.bash-completion index 18880e8090f9..18e25097faa1 100644 --- a/contrib/dashd.bash-completion +++ b/contrib/dashd.bash-completion @@ -1,102 +1,21 @@ -# bash programmable completion for dashd(1) and dash-cli(1) -# Copyright (c) 2012,2014 Christian von Roques +# bash programmable completion for dashd(1) and dash-qt(1) +# Copyright (c) 2012-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -have dashd && { - -# call $dashd for RPC -_dash_rpc() { - # determine already specified args necessary for RPC - local rpcargs=() - for i in ${COMP_LINE}; do - case "$i" in - -conf=*|-proxy*|-rpc*) - rpcargs=( "${rpcargs[@]}" "$i" ) - ;; - esac - done - $dashd "${rpcargs[@]}" "$@" -} - -# Add dash accounts to COMPREPLY -_dash_accounts() { - local accounts - accounts=$(_dash_rpc listaccounts | awk '/".*"/ { a=$1; gsub(/"/, "", a); print a}') - COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "$accounts" -- "$cur" ) ) -} - _dashd() { local cur prev words=() cword local dashd - # save and use original argument to invoke dashd - # dashd might not be in $PATH + # save and use original argument to invoke dashd for -help + # it might not be in $PATH dashd="$1" COMPREPLY=() _get_comp_words_by_ref -n = cur prev words cword - if ((cword > 4)); then - case ${words[cword-4]} in - listtransactions) - COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) - return 0 - ;; - signrawtransaction) - COMPREPLY=( $( compgen -W "ALL NONE SINGLE ALL|ANYONECANPAY NONE|ANYONECANPAY SINGLE|ANYONECANPAY" -- "$cur" ) ) - return 0 - ;; - esac - fi - - if ((cword > 3)); then - case ${words[cword-3]} in - addmultisigaddress) - _dash_accounts - return 0 - ;; - getbalance|gettxout|importaddress|importprivkey|listreceivedbyaccount|listreceivedbyaddress|listsinceblock) - COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) - return 0 - ;; - esac - fi - - if ((cword > 2)); then - case ${words[cword-2]} in - addnode) - COMPREPLY=( $( compgen -W "add remove onetry" -- "$cur" ) ) - return 0 - ;; - getblock|getrawtransaction|gettransaction|listaccounts|listreceivedbyaccount|listreceivedbyaddress|sendrawtransaction) - COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) - return 0 - ;; - move|setaccount) - _dash_accounts - return 0 - ;; - esac - fi - - case "$prev" in - backupwallet|dumpwallet|importwallet) - _filedir - return 0 - ;; - getmempool|lockunspent|setgenerate) - COMPREPLY=( $( compgen -W "true false" -- "$cur" ) ) - return 0 - ;; - getaccountaddress|getaddressesbyaccount|getbalance|getnewaddress|getreceivedbyaccount|listtransactions|move|sendfrom|sendmany) - _dash_accounts - return 0 - ;; - esac - case "$cur" in - -conf=*|-pid=*|-loadblock=*|-wallet=*) + -conf=*|-pid=*|-loadblock=*|-rootcertificates=*|-rpccookiefile=*|-wallet=*) cur="${cur#*=}" _filedir return 0 @@ -110,20 +29,14 @@ _dashd() { return 0 ;; *) - local helpopts commands - # only parse --help if senseful + # only parse -help if senseful if [[ -z "$cur" || "$cur" =~ ^- ]]; then - helpopts=$($dashd --help 2>&1 | awk '$1 ~ /^-/ { sub(/=.*/, "="); print $1 }' ) + local helpopts + helpopts=$($dashd -help 2>&1 | awk '$1 ~ /^-/ { sub(/=.*/, "="); print $1 }' ) + COMPREPLY=( $( compgen -W "$helpopts" -- "$cur" ) ) fi - # only parse help if senseful - if [[ -z "$cur" || "$cur" =~ ^[a-z] ]]; then - commands=$(_dash_rpc help 2>/dev/null | awk '$1 ~ /^[a-z]/ { print $1; }') - fi - - COMPREPLY=( $( compgen -W "$helpopts $commands" -- "$cur" ) ) - # Prevent space if an argument is desired if [[ $COMPREPLY == *= ]]; then compopt -o nospace @@ -131,10 +44,8 @@ _dashd() { return 0 ;; esac -} - -complete -F _dashd dashd dash-cli -} +} && +complete -F _dashd dashd dash-qt # Local variables: # mode: shell-script diff --git a/contrib/debian/dash-tx.bash-completion b/contrib/debian/dash-tx.bash-completion new file mode 100644 index 000000000000..605234a39be6 --- /dev/null +++ b/contrib/debian/dash-tx.bash-completion @@ -0,0 +1 @@ +contrib/dash-tx.bash-completion dash-tx diff --git a/contrib/debian/dashd.bash-completion b/contrib/debian/dashd.bash-completion index d92f33da7bf3..e2f51e6f6533 100644 --- a/contrib/debian/dashd.bash-completion +++ b/contrib/debian/dashd.bash-completion @@ -1 +1,2 @@ contrib/dashd.bash-completion dashd +contrib/dash-cli.bash-completion dash-cli diff --git a/contrib/devtools/check-doc.py b/contrib/devtools/check-doc.py index 8c73cf1e8a73..fa1e137587a6 100755 --- a/contrib/devtools/check-doc.py +++ b/contrib/devtools/check-doc.py @@ -21,7 +21,7 @@ REGEX_ARG = re.compile(r'(?:map(?:Multi)?Args(?:\.count\(|\[)|Get(?:Bool)?Arg\()\"(\-[^\"]+?)\"') REGEX_DOC = re.compile(r'HelpMessageOpt\(\"(\-[^\"=]+?)(?:=|\")') # list unsupported, deprecated and duplicate args as they need no documentation -SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay']) +SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay', '-blockminsize']) def main(): used = check_output(CMD_GREP_ARGS, shell=True) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index ce4baee31ead..2c26d4fd60d4 100755 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -33,12 +33,6 @@ remotes: files: [] script: | - #unlock sudo - echo "ubuntu" | sudo -S true - - sudo mkdir -p /usr/include/i386-linux-gnu/ - sudo ln -s /usr/include/x86_64-linux-gnu/asm /usr/include/i386-linux-gnu/asm - WRAP_DIR=$HOME/wrapped HOSTS="i686-pc-linux-gnu x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu" CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests" @@ -84,22 +78,58 @@ script: | done } - export PATH=${WRAP_DIR}:${PATH} - # Faketime for depends so intermediate results are comparable + export PATH_orig=${PATH} create_global_faketime_wrappers "2000-01-01 12:00:00" create_per-host_faketime_wrappers "2000-01-01 12:00:00" + export PATH=${WRAP_DIR}:${PATH} + + EXTRA_INCLUDES_BASE=$WRAP_DIR/extra_includes + mkdir -p $EXTRA_INCLUDES_BASE + + # x86 needs /usr/include/i386-linux-gnu/asm pointed to /usr/include/x86_64-linux-gnu/asm, + # but we can't write there. Instead, create a link here and force it to be included in the + # search paths by wrapping gcc/g++. + + mkdir -p $EXTRA_INCLUDES_BASE/i686-pc-linux-gnu + rm -f $WRAP_DIR/extra_includes/i686-pc-linux-gnu/asm + ln -s /usr/include/x86_64-linux-gnu/asm $EXTRA_INCLUDES_BASE/i686-pc-linux-gnu/asm + + for prog in gcc g++; do + rm -f ${WRAP_DIR}/${prog} + cat << EOF > ${WRAP_DIR}/${prog} + #!/bin/bash + REAL="`which -a ${prog} | grep -v ${WRAP_DIR}/${prog} | head -1`" + for var in "\$@" + do + if [ "\$var" = "-m32" ]; then + export C_INCLUDE_PATH="$EXTRA_INCLUDES_BASE/i686-pc-linux-gnu" + export CPLUS_INCLUDE_PATH="$EXTRA_INCLUDES_BASE/i686-pc-linux-gnu" + break + fi + done + \$REAL \$@ + EOF + chmod +x ${WRAP_DIR}/${prog} + done cd dash BASEPREFIX=`pwd`/depends # Build dependencies for each host for i in $HOSTS; do + EXTRA_INCLUDES="$EXTRA_INCLUDES_BASE/$i" + if [ -d "$EXTRA_INCLUDES" ]; then + export HOST_ID_SALT="$EXTRA_INCLUDES" + fi make ${MAKEOPTS} -C ${BASEPREFIX} HOST="${i}" + unset HOST_ID_SALT done # Faketime for binaries + export PATH=${PATH_orig} create_global_faketime_wrappers "${REFERENCE_DATETIME}" create_per-host_faketime_wrappers "${REFERENCE_DATETIME}" + export PATH=${WRAP_DIR}:${PATH} # Create the release tarball using (arbitrarily) the first host ./autogen.sh diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 29b8772c519b..9abc4776fbbd 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -31,7 +31,7 @@ remotes: - "url": "https://github.com/dashpay/dash.git" "dir": "dash" files: -- "MacOSX10.9.sdk.tar.gz" +- "MacOSX10.11.sdk.tar.gz" script: | WRAP_DIR=$HOME/wrapped HOSTS="x86_64-apple-darwin11" @@ -77,17 +77,17 @@ script: | done } - export PATH=${WRAP_DIR}:${PATH} - # Faketime for depends so intermediate results are comparable + export PATH_orig=${PATH} create_global_faketime_wrappers "2000-01-01 12:00:00" create_per-host_faketime_wrappers "2000-01-01 12:00:00" + export PATH=${WRAP_DIR}:${PATH} cd dash BASEPREFIX=`pwd`/depends mkdir -p ${BASEPREFIX}/SDKs - tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/MacOSX10.9.sdk.tar.gz + tar -C ${BASEPREFIX}/SDKs -xf ${BUILD_DIR}/MacOSX10.11.sdk.tar.gz # Build dependencies for each host for i in $HOSTS; do @@ -95,8 +95,10 @@ script: | done # Faketime for binaries + export PATH=${PATH_orig} create_global_faketime_wrappers "${REFERENCE_DATETIME}" create_per-host_faketime_wrappers "${REFERENCE_DATETIME}" + export PATH=${WRAP_DIR}:${PATH} # Create the release tarball using (arbitrarily) the first host ./autogen.sh diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 299de65a8978..d91fbf9acb6e 100755 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -94,12 +94,12 @@ script: | done } - export PATH=${WRAP_DIR}:${PATH} - # Faketime for depends so intermediate results are comparable + export PATH_orig=${PATH} create_global_faketime_wrappers "2000-01-01 12:00:00" create_per-host_faketime_wrappers "2000-01-01 12:00:00" create_per-host_linker_wrapper "2000-01-01 12:00:00" + export PATH=${WRAP_DIR}:${PATH} cd dash BASEPREFIX=`pwd`/depends @@ -109,9 +109,11 @@ script: | done # Faketime for binaries + export PATH=${PATH_orig} create_global_faketime_wrappers "${REFERENCE_DATETIME}" create_per-host_faketime_wrappers "${REFERENCE_DATETIME}" create_per-host_linker_wrapper "${REFERENCE_DATETIME}" + export PATH=${WRAP_DIR}:${PATH} # Create the release tarball using (arbitrarily) the first host ./autogen.sh diff --git a/contrib/verify-commits/README.md b/contrib/verify-commits/README.md new file mode 100644 index 000000000000..e9e3f65da292 --- /dev/null +++ b/contrib/verify-commits/README.md @@ -0,0 +1,26 @@ +Tooling for verification of PGP signed commits +---------------------------------------------- + +This is an incomplete work in progress, but currently includes a pre-push hook +script (`pre-push-hook.sh`) for maintainers to ensure that their own commits +are PGP signed (nearly always merge commits), as well as a script to verify +commits against a trusted keys list. + + +Using verify-commits.sh safely +------------------------------ + +Remember that you can't use an untrusted script to verify itself. This means +that checking out code, then running `verify-commits.sh` against `HEAD` is +_not_ safe, because the version of `verify-commits.sh` that you just ran could +be backdoored. Instead, you need to use a trusted version of verify-commits +prior to checkout to make sure you're checking out only code signed by trusted +keys: + + git fetch origin && \ + ./contrib/verify-commits/verify-commits.sh origin/master && \ + git checkout origin/master + +Note that the above isn't a good UI/UX yet, and needs significant improvements +to make it more convenient and reduce the chance of errors; pull-reqs +improving this process would be much appreciated. diff --git a/contrib/verify-commits/allow-revsig-commits b/contrib/verify-commits/allow-revsig-commits index 31aeb8f3d38b..e69de29bb2d1 100644 --- a/contrib/verify-commits/allow-revsig-commits +++ b/contrib/verify-commits/allow-revsig-commits @@ -1,2 +0,0 @@ -586a29253dabec3ca0f1ccba9091daabd16b8411 -eddaba7b5692288087a926da5733e86b47274e4e diff --git a/contrib/verify-commits/gpg.sh b/contrib/verify-commits/gpg.sh index 0218b82e11dd..375d71172570 100755 --- a/contrib/verify-commits/gpg.sh +++ b/contrib/verify-commits/gpg.sh @@ -1,8 +1,9 @@ #!/bin/sh -INPUT=$(/dev/null); do case "$LINE" in "[GNUPG:] VALIDSIG "*) @@ -13,10 +14,9 @@ for LINE in $(echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null); do "[GNUPG:] REVKEYSIG "*) [ "$BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG" != 1 ] && exit 1 while read KEY; do - case "$LINE" in "[GNUPG:] REVKEYSIG ${KEY:24:40} "*) + case "$LINE" in "[GNUPG:] REVKEYSIG ${KEY#????????????????????????} "*) REVSIG=true - GOODREVSIG="[GNUPG:] GOODSIG ${KEY:24:40} " - ;; + GOODREVSIG="[GNUPG:] GOODSIG ${KEY#????????????????????????} " esac done < ./contrib/verify-commits/trusted-keys ;; diff --git a/contrib/verify-commits/trusted-git-root b/contrib/verify-commits/trusted-git-root index 838b8d1ea84b..c60f8ab695e9 100644 --- a/contrib/verify-commits/trusted-git-root +++ b/contrib/verify-commits/trusted-git-root @@ -1 +1 @@ -165e323d851cc87213c7673c6f278e87a6f2e752 +82bcf405f6db1d55b684a1f63a4aabad376cdad7 diff --git a/contrib/verify-commits/trusted-keys b/contrib/verify-commits/trusted-keys index a0d0f82db3f4..5b64a44abfdf 100644 --- a/contrib/verify-commits/trusted-keys +++ b/contrib/verify-commits/trusted-keys @@ -1,7 +1,3 @@ 71A3B16735405025D447E8F274810B012346C9A6 -1F4410F6A89268CE3197A84C57896D2FF8F0B657 -01CDF4627A3B88AAE4A571C87588242FBE38D3A8 -AF8BE07C7049F3A26B239D5325B3083201782B2F -81291FA67D2C379A006A053FEAB5AF94D9E9ABE7 3F1888C6DCA92A6499C4911FDBA1A67379A1A931 32EE5C4C3FA15CCADB46ABE529D4BCB6416F53EC diff --git a/contrib/verify-commits/verify-commits.sh b/contrib/verify-commits/verify-commits.sh index 9ba781008a65..5219331e2e5b 100755 --- a/contrib/verify-commits/verify-commits.sh +++ b/contrib/verify-commits/verify-commits.sh @@ -1,25 +1,19 @@ #!/bin/sh +# Not technically POSIX-compliant due to use of "local", but almost every +# shell anyone uses today supports it, so its probably fine DIR=$(dirname "$0") - -echo "Please verify all commits in the following list are not evil:" -git log "$DIR" +[ "/${DIR#/}" != "$DIR" ] && DIR=$(dirname "$(pwd)/$0") VERIFIED_ROOT=$(cat "${DIR}/trusted-git-root") - -IS_REVSIG_ALLOWED () { - while read LINE; do - [ "$LINE" = "$1" ] && return 0 - done < "${DIR}/allow-revsig-commits" - return 1 -} +REVSIG_ALLOWED=$(cat "${DIR}/allow-revsig-commits") HAVE_FAILED=false IS_SIGNED () { if [ $1 = $VERIFIED_ROOT ]; then return 0; fi - if IS_REVSIG_ALLOWED "$1"; then + if [ "${REVSIG_ALLOWED#*$1}" != "$REVSIG_ALLOWED" ]; then export BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG=1 else export BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG=0 @@ -27,7 +21,8 @@ IS_SIGNED () { if ! git -c "gpg.program=${DIR}/gpg.sh" verify-commit $1 > /dev/null 2>&1; then return 1; fi - local PARENTS=$(git show -s --format=format:%P $1) + local PARENTS + PARENTS=$(git show -s --format=format:%P $1) for PARENT in $PARENTS; do if IS_SIGNED $PARENT > /dev/null; then return 0; diff --git a/depends/.gitignore b/depends/.gitignore index 1f163897b9ef..3cb4b9ac1555 100644 --- a/depends/.gitignore +++ b/depends/.gitignore @@ -7,3 +7,4 @@ x86_64* i686* mips* arm* +aarch64* diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk index dbe6d00795e0..985649619ffe 100644 --- a/depends/hosts/darwin.mk +++ b/depends/hosts/darwin.mk @@ -1,7 +1,7 @@ OSX_MIN_VERSION=10.7 -OSX_SDK_VERSION=10.9 +OSX_SDK_VERSION=10.11 OSX_SDK=$(SDK_PATH)/MacOSX$(OSX_SDK_VERSION).sdk -LD64_VERSION=241.9 +LD64_VERSION=253.9 darwin_CC=clang -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) darwin_CXX=clang++ -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(OSX_SDK) -mlinker-version=$(LD64_VERSION) -stdlib=libc++ diff --git a/depends/packages/native_cctools.mk b/depends/packages/native_cctools.mk index b5603a8d48c6..797480c25eb2 100644 --- a/depends/packages/native_cctools.mk +++ b/depends/packages/native_cctools.mk @@ -1,14 +1,14 @@ package=native_cctools -$(package)_version=ee31ae567931c426136c94aad457c7b51d844beb +$(package)_version=807d6fd1be5d2224872e381870c0a75387fe05e6 $(package)_download_path=https://github.com/theuni/cctools-port/archive $(package)_file_name=$($(package)_version).tar.gz -$(package)_sha256_hash=ef107e6ab1b3994cb22e14f4f5c59ea0c0b5a988e6b21d42ed9616b018bbcbf9 +$(package)_sha256_hash=a09c9ba4684670a0375e42d9d67e7f12c1f62581a27f28f7c825d6d7032ccc6a $(package)_build_subdir=cctools -$(package)_clang_version=3.3 +$(package)_clang_version=3.7.1 $(package)_clang_download_path=http://llvm.org/releases/$($(package)_clang_version) -$(package)_clang_download_file=clang+llvm-$($(package)_clang_version)-amd64-Ubuntu-12.04.2.tar.gz -$(package)_clang_file_name=clang-llvm-$($(package)_clang_version)-amd64-Ubuntu-12.04.2.tar.gz -$(package)_clang_sha256_hash=60d8f69f032d62ef61bf527857ebb933741ec3352d4d328c5516aa520662dab7 +$(package)_clang_download_file=clang+llvm-$($(package)_clang_version)-x86_64-linux-gnu-ubuntu-14.04.tar.xz +$(package)_clang_file_name=clang-llvm-$($(package)_clang_version)-x86_64-linux-gnu-ubuntu-14.04.tar.xz +$(package)_clang_sha256_hash=99b28a6b48e793705228a390471991386daa33a9717cd9ca007fcdde69608fd9 $(package)_extra_sources=$($(package)_clang_file_name) define $(package)_fetch_cmds @@ -23,6 +23,7 @@ define $(package)_extract_cmds $(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \ mkdir -p toolchain/bin toolchain/lib/clang/3.5/include && \ tar --strip-components=1 -C toolchain -xf $($(package)_source_dir)/$($(package)_clang_file_name) && \ + rm -f toolchain/lib/libc++abi.so* && \ echo "#!/bin/sh" > toolchain/bin/$(host)-dsymutil && \ echo "exit 0" >> toolchain/bin/$(host)-dsymutil && \ chmod +x toolchain/bin/$(host)-dsymutil && \ @@ -30,7 +31,7 @@ define $(package)_extract_cmds endef define $(package)_set_vars -$(package)_config_opts=--target=$(host) --disable-libuuid +$(package)_config_opts=--target=$(host) --disable-lto-support $(package)_ldflags+=-Wl,-rpath=\\$$$$$$$$\$$$$$$$$ORIGIN/../lib $(package)_cc=$($(package)_extract_dir)/toolchain/bin/clang $(package)_cxx=$($(package)_extract_dir)/toolchain/bin/clang++ @@ -53,10 +54,11 @@ define $(package)_stage_cmds cd $($(package)_extract_dir)/toolchain && \ mkdir -p $($(package)_staging_prefix_dir)/lib/clang/$($(package)_clang_version)/include && \ mkdir -p $($(package)_staging_prefix_dir)/bin $($(package)_staging_prefix_dir)/include && \ - cp -P bin/clang bin/clang++ $($(package)_staging_prefix_dir)/bin/ &&\ + cp bin/clang $($(package)_staging_prefix_dir)/bin/ &&\ + cp -P bin/clang++ $($(package)_staging_prefix_dir)/bin/ &&\ cp lib/libLTO.so $($(package)_staging_prefix_dir)/lib/ && \ cp -rf lib/clang/$($(package)_clang_version)/include/* $($(package)_staging_prefix_dir)/lib/clang/$($(package)_clang_version)/include/ && \ - cp bin/$(host)-dsymutil $($(package)_staging_prefix_dir)/bin && \ + cp bin/llvm-dsymutil $($(package)_staging_prefix_dir)/bin/$(host)-dsymutil && \ if `test -d include/c++/`; then cp -rf include/c++/ $($(package)_staging_prefix_dir)/include/; fi && \ if `test -d lib/c++/`; then cp -rf lib/c++/ $($(package)_staging_prefix_dir)/lib/; fi endef diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk index fe6eb97dead0..5ee9f17a6323 100644 --- a/depends/packages/openssl.mk +++ b/depends/packages/openssl.mk @@ -6,9 +6,42 @@ $(package)_sha256_hash=8f9faeaebad088e772f4ef5e38252d472be4d878c6b3a2718c10a4fce define $(package)_set_vars $(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)" -$(package)_config_opts=--prefix=$(host_prefix) --openssldir=$(host_prefix)/etc/openssl no-zlib no-shared no-dso -$(package)_config_opts+=no-krb5 no-capieng no-dtls1 no-gost no-gmp no-heartbeats no-jpake no-md2 -$(package)_config_opts+=no-rc5 no-rdrand no-rfc3779 no-rsax no-sctp no-sha0 no-static_engine no-ssl2 no-ssl3 +$(package)_config_opts=--prefix=$(host_prefix) --openssldir=$(host_prefix)/etc/openssl +$(package)_config_opts+=no-camellia +$(package)_config_opts+=no-capieng +$(package)_config_opts+=no-cast +$(package)_config_opts+=no-comp +$(package)_config_opts+=no-dso +$(package)_config_opts+=no-dtls1 +$(package)_config_opts+=no-ec_nistp_64_gcc_128 +$(package)_config_opts+=no-gost +$(package)_config_opts+=no-gmp +$(package)_config_opts+=no-heartbeats +$(package)_config_opts+=no-idea +$(package)_config_opts+=no-jpake +$(package)_config_opts+=no-krb5 +$(package)_config_opts+=no-libunbound +$(package)_config_opts+=no-md2 +$(package)_config_opts+=no-mdc2 +$(package)_config_opts+=no-rc4 +$(package)_config_opts+=no-rc5 +$(package)_config_opts+=no-rdrand +$(package)_config_opts+=no-rfc3779 +$(package)_config_opts+=no-rsax +$(package)_config_opts+=no-sctp +$(package)_config_opts+=no-seed +$(package)_config_opts+=no-sha0 +$(package)_config_opts+=no-shared +$(package)_config_opts+=no-ssl-trace +$(package)_config_opts+=no-ssl2 +$(package)_config_opts+=no-ssl3 +$(package)_config_opts+=no-static_engine +$(package)_config_opts+=no-store +$(package)_config_opts+=no-unit-test +$(package)_config_opts+=no-weak-ssl-ciphers +$(package)_config_opts+=no-whirlpool +$(package)_config_opts+=no-zlib +$(package)_config_opts+=no-zlib-dynamic $(package)_config_opts+=$($(package)_cflags) $($(package)_cppflags) $(package)_config_opts_linux=-fPIC -Wa,--noexecstack $(package)_config_opts_x86_64_linux=linux-x86_64 diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index b7a2413750d0..d41d0b9ea5b1 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -1,20 +1,21 @@ PACKAGE=qt -$(package)_version=5.5.0 -$(package)_download_path=http://download.qt.io/archive/qt/5.5/$($(package)_version)/submodules +$(package)_version=5.6.1 +$(package)_download_path=http://download.qt.io/official_releases/qt/5.6/$($(package)_version)/submodules $(package)_suffix=opensource-src-$($(package)_version).tar.gz $(package)_file_name=qtbase-$($(package)_suffix) -$(package)_sha256_hash=7e82b1318f88e56a2a9376e069aa608d4fd96b48cb0e1b880ae658b0a1af0561 +$(package)_sha256_hash=0ac67cf8d66d52b995f96c31c4b48117a1afb3db99eaa93e20ccd8f7f55f7fde $(package)_dependencies=openssl -$(package)_linux_dependencies=freetype fontconfig dbus libxcb libX11 xproto libXext +$(package)_linux_dependencies=freetype fontconfig libxcb libX11 xproto libXext $(package)_build_subdir=qtbase $(package)_qt_libs=corelib network widgets gui plugins testlib -$(package)_patches=mac-qmake.conf fix-xcb-include-order.patch mingw-uuidof.patch pidlist_absolute.patch +$(package)_patches=mac-qmake.conf mingw-uuidof.patch pidlist_absolute.patch fix-xcb-include-order.patch fix_qt_pkgconfig.patch $(package)_qttranslations_file_name=qttranslations-$($(package)_suffix) -$(package)_qttranslations_sha256_hash=c4bd6db6e426965c6f8824c54e81f68bbd61e2bae1bcadc328c6e81c45902a0d +$(package)_qttranslations_sha256_hash=dcc1534d247babca1840cb6d0a000671801a341ea352d0535474f86adadaf028 + $(package)_qttools_file_name=qttools-$($(package)_suffix) -$(package)_qttools_sha256_hash=d9e06bd19ecc86afba5e95d45a906d1bc1ad579aa70001e36143c1aaf695bdd6 +$(package)_qttools_sha256_hash=e0f845de28c31230dfa428f0190ccb3b91d1fc02481b1f064698ae4ef8376aa1 $(package)_extra_sources = $($(package)_qttranslations_file_name) $(package)_extra_sources += $($(package)_qttools_file_name) @@ -22,21 +23,34 @@ $(package)_extra_sources += $($(package)_qttools_file_name) define $(package)_set_vars $(package)_config_opts_release = -release $(package)_config_opts_debug = -debug -$(package)_config_opts += -opensource -confirm-license +$(package)_config_opts += -bindir $(build_prefix)/bin +$(package)_config_opts += -c++11 +$(package)_config_opts += -confirm-license +$(package)_config_opts += -dbus-runtime +$(package)_config_opts += -hostprefix $(build_prefix) +$(package)_config_opts += -no-alsa $(package)_config_opts += -no-audio-backend +$(package)_config_opts += -no-cups +$(package)_config_opts += -no-egl +$(package)_config_opts += -no-eglfs +$(package)_config_opts += -no-feature-style-windowsmobile +$(package)_config_opts += -no-feature-style-windowsce +$(package)_config_opts += -no-freetype +$(package)_config_opts += -no-gif $(package)_config_opts += -no-glib +$(package)_config_opts += -no-gstreamer $(package)_config_opts += -no-icu -$(package)_config_opts += -no-cups $(package)_config_opts += -no-iconv -$(package)_config_opts += -no-gif -$(package)_config_opts += -no-freetype +$(package)_config_opts += -no-kms +$(package)_config_opts += -no-linuxfb +$(package)_config_opts += -no-libudev +$(package)_config_opts += -no-mitshm +$(package)_config_opts += -no-mtdev $(package)_config_opts += -no-nis -$(package)_config_opts += -pch +$(package)_config_opts += -no-pulseaudio +$(package)_config_opts += -no-openvg +$(package)_config_opts += -no-reduce-relocations $(package)_config_opts += -no-qml-debug -$(package)_config_opts += -nomake examples -$(package)_config_opts += -nomake tests -$(package)_config_opts += -no-feature-style-windowsmobile -$(package)_config_opts += -no-feature-style-windowsce $(package)_config_opts += -no-sql-db2 $(package)_config_opts += -no-sql-ibase $(package)_config_opts += -no-sql-oci @@ -46,36 +60,25 @@ $(package)_config_opts += -no-sql-odbc $(package)_config_opts += -no-sql-psql $(package)_config_opts += -no-sql-sqlite $(package)_config_opts += -no-sql-sqlite2 -$(package)_config_opts += -prefix $(host_prefix) -$(package)_config_opts += -hostprefix $(build_prefix) -$(package)_config_opts += -bindir $(build_prefix)/bin -$(package)_config_opts += -c++11 +$(package)_config_opts += -no-use-gold-linker +$(package)_config_opts += -no-xinput2 +$(package)_config_opts += -no-xrender +$(package)_config_opts += -nomake examples +$(package)_config_opts += -nomake tests +$(package)_config_opts += -opensource $(package)_config_opts += -openssl-linked -$(package)_config_opts += -v -$(package)_config_opts += -static -$(package)_config_opts += -silent +$(package)_config_opts += -optimized-qmake +$(package)_config_opts += -pch $(package)_config_opts += -pkg-config +$(package)_config_opts += -prefix $(host_prefix) $(package)_config_opts += -qt-libpng $(package)_config_opts += -qt-libjpeg -$(package)_config_opts += -qt-zlib $(package)_config_opts += -qt-pcre -$(package)_config_opts += -no-pulseaudio -$(package)_config_opts += -no-openvg -$(package)_config_opts += -no-xrender -$(package)_config_opts += -no-alsa -$(package)_config_opts += -no-mtdev -$(package)_config_opts += -no-gstreamer -$(package)_config_opts += -no-mitshm -$(package)_config_opts += -no-kms -$(package)_config_opts += -no-reduce-relocations -$(package)_config_opts += -no-egl -$(package)_config_opts += -no-eglfs -$(package)_config_opts += -no-linuxfb -$(package)_config_opts += -no-xinput2 -$(package)_config_opts += -no-libudev -$(package)_config_opts += -no-use-gold-linker +$(package)_config_opts += -qt-zlib $(package)_config_opts += -reduce-exports -$(package)_config_opts += -optimized-qmake +$(package)_config_opts += -static +$(package)_config_opts += -silent +$(package)_config_opts += -v ifneq ($(build_os),darwin) $(package)_config_opts_darwin = -xplatform macx-clang-linux @@ -119,19 +122,22 @@ define $(package)_extract_cmds tar --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttools_file_name) -C qttools endef + define $(package)_preprocess_cmds sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \ sed -i.old "s/src_plugins.depends = src_sql src_xml src_network/src_plugins.depends = src_xml src_network/" qtbase/src/src.pro && \ sed -i.old "s|X11/extensions/XIproto.h|X11/X.h|" qtbase/src/plugins/platforms/xcb/qxcbxsettings.cpp && \ sed -i.old 's/if \[ "$$$$XPLATFORM_MAC" = "yes" \]; then xspecvals=$$$$(macSDKify/if \[ "$$$$BUILD_ON_MAC" = "yes" \]; then xspecvals=$$$$(macSDKify/' qtbase/configure && \ + sed -i.old 's/CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, 0)/CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, kCGMouseButtonLeft)/' qtbase/src/plugins/platforms/cocoa/qcocoacursor.mm && \ mkdir -p qtbase/mkspecs/macx-clang-linux &&\ cp -f qtbase/mkspecs/macx-clang/Info.plist.lib qtbase/mkspecs/macx-clang-linux/ &&\ cp -f qtbase/mkspecs/macx-clang/Info.plist.app qtbase/mkspecs/macx-clang-linux/ &&\ cp -f qtbase/mkspecs/macx-clang/qplatformdefs.h qtbase/mkspecs/macx-clang-linux/ &&\ cp -f $($(package)_patch_dir)/mac-qmake.conf qtbase/mkspecs/macx-clang-linux/qmake.conf && \ - patch -p1 < $($(package)_patch_dir)/fix-xcb-include-order.patch && \ patch -p1 < $($(package)_patch_dir)/mingw-uuidof.patch && \ patch -p1 < $($(package)_patch_dir)/pidlist_absolute.patch && \ + patch -p1 < $($(package)_patch_dir)/fix-xcb-include-order.patch && \ + patch -p1 < $($(package)_patch_dir)/fix_qt_pkgconfig.patch && \ echo "QMAKE_CFLAGS += $($(package)_cflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ echo "QMAKE_CXXFLAGS += $($(package)_cxxflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ echo "QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ diff --git a/depends/patches/qt/fix-xcb-include-order.patch b/depends/patches/qt/fix-xcb-include-order.patch index ae469ea94bff..c7dbebedce83 100644 --- a/depends/patches/qt/fix-xcb-include-order.patch +++ b/depends/patches/qt/fix-xcb-include-order.patch @@ -1,15 +1,15 @@ --- old/qtbase/src/plugins/platforms/xcb/xcb_qpa_lib.pro 2015-03-17 02:06:42.705930685 +0000 +++ new/qtbase/src/plugins/platforms/xcb/xcb_qpa_lib.pro 2015-03-17 02:08:41.281926351 +0000 -@@ -94,8 +94,6 @@ - +@@ -74,8 +74,6 @@ + DEFINES += $$QMAKE_DEFINES_XCB LIBS += $$QMAKE_LIBS_XCB -QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XCB -QMAKE_CFLAGS += $$QMAKE_CFLAGS_XCB - + CONFIG += qpa/genericunixfontdatabase - -@@ -104,7 +102,8 @@ + +@@ -87,7 +85,8 @@ contains(QT_CONFIG, xcb-qt) { DEFINES += XCB_USE_RENDER XCB_DIR = ../../../3rdparty/xcb @@ -18,28 +18,32 @@ + QMAKE_CXXFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/sysinclude $$QMAKE_CFLAGS_XCB LIBS += -lxcb -L$$OUT_PWD/xcb-static -lxcb-static } else { - LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms + LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms -lxcb-xinerama --- old/qtbase/src/plugins/platforms/xcb/xcb-static/xcb-static.pro 2015-03-17 02:07:04.641929383 +0000 +++ new/qtbase/src/plugins/platforms/xcb/xcb-static/xcb-static.pro 2015-03-17 02:10:15.485922059 +0000 -@@ -8,7 +8,8 @@ - +@@ -9,7 +9,8 @@ + XCB_DIR = ../../../../3rdparty/xcb - + -INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/include/xcb $$XCB_DIR/sysinclude +QMAKE_CFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/include/xcb -I$$XCB_DIR/sysinclude +QMAKE_CXXFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/include/xcb -I$$XCB_DIR/sysinclude - + QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XCB QMAKE_CFLAGS += $$QMAKE_CFLAGS_XCB --- old/qtbase/src/plugins/platforms/xcb/xcb-plugin.pro 2015-07-24 16:02:59.530038830 -0400 +++ new/qtbase/src/plugins/platforms/xcb/xcb-plugin.pro 2015-07-24 16:01:22.106037459 -0400 -@@ -11,3 +11,9 @@ +@@ -6,6 +6,13 @@ qxcbmain.cpp OTHER_FILES += xcb.json README - + +contains(QT_CONFIG, xcb-qt) { + DEFINES += XCB_USE_RENDER + XCB_DIR = ../../../3rdparty/xcb + QMAKE_CFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/sysinclude $$QMAKE_CFLAGS_XCB + QMAKE_CXXFLAGS += -I$$XCB_DIR/include -I$$XCB_DIR/sysinclude $$QMAKE_CFLAGS_XCB +} ++ + PLUGIN_TYPE = platforms + PLUGIN_CLASS_NAME = QXcbIntegrationPlugin + !equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = - diff --git a/depends/patches/qt/fix_qt_pkgconfig.patch b/depends/patches/qt/fix_qt_pkgconfig.patch new file mode 100644 index 000000000000..3772db4f8b80 --- /dev/null +++ b/depends/patches/qt/fix_qt_pkgconfig.patch @@ -0,0 +1,11 @@ +--- old/qtbase/mkspecs/features/qt_module.prf 2016-03-17 02:06:42.705930685 +0000 ++++ new/qtbase/mkspecs/features/qt_module.prf 2016-03-17 02:06:42.705930685 +0000 +@@ -244,7 +244,7 @@ + load(qt_targets) + + # this builds on top of qt_common +-!internal_module:!lib_bundle:if(unix|mingw) { ++unix|mingw { + CONFIG += create_pc + QMAKE_PKGCONFIG_DESTDIR = pkgconfig + host_build: \ diff --git a/doc/README_osx.txt b/doc/README_osx.md similarity index 81% rename from doc/README_osx.txt rename to doc/README_osx.md index c13efaa145c8..aed3cd97e1ec 100644 --- a/doc/README_osx.txt +++ b/doc/README_osx.md @@ -1,21 +1,19 @@ Deterministic OS X Dmg Notes. Working OS X DMGs are created in Linux by combining a recent clang, -the Apple's binutils (ld, ar, etc), and DMG authoring tools. +the Apple binutils (ld, ar, etc) and DMG authoring tools. Apple uses clang extensively for development and has upstreamed the necessary functionality so that a vanilla clang can take advantage. It supports the use of -F, -target, -mmacosx-version-min, and --sysroot, which are all necessary -when building for OS X. A pre-compiled version of 3.2 is used because it was not -available in the Precise repositories at the time this work was started. In the -future, it can be switched to use system packages instead. +when building for OS X. Apple's version of binutils (called cctools) contains lots of functionality missing in the FSF's binutils. In addition to extra linker options for frameworks and sysroots, several other tools are needed as well such as install_name_tool, lipo, and nmedit. These do not build under linux, so they have been patched to do so. The work here was used as a starting point: -https://github.com/mingwandroid/toolchain4 +[mingwandroid/toolchain4](https://github.com/mingwandroid/toolchain4). In order to build a working toolchain, the following source packages are needed from Apple: cctools, dyld, and ld64. @@ -29,16 +27,19 @@ originally done in toolchain4. To complicate things further, all builds must target an Apple SDK. These SDKs are free to download, but not redistributable. -To obtain it, register for a developer account, then download the Xcode 6.1.1 dmg: -https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/xcode_6.1.1/xcode_6.1.1.dmg +To obtain it, register for a developer account, then download the [Xcode 7.3.1 dmg](https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/Xcode_7.3.1/Xcode_7.3.1.dmg). This file is several gigabytes in size, but only a single directory inside is -needed: Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk +needed: +``` +Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk +``` Unfortunately, the usual linux tools (7zip, hpmount, loopback mount) are incapable of opening this file. To create a tarball suitable for Gitian input, mount the dmg in OS X, then create it with: - $ tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.9.sdk.tar.gz MacOSX10.9.sdk - +``` + $ tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.11.sdk.tar.gz MacOSX10.11.sdk +``` The Gitian descriptors build 2 sets of files: Linux tools, then Apple binaries which are created using these tools. The build process has been designed to @@ -48,15 +49,14 @@ fully deterministic and may be freely redistributed. genisoimage is used to create the initial DMG. It is not deterministic as-is, so it has been patched. A system genisoimage will work fine, but it will not be deterministic because the file-order will change between invocations. -The patch can be seen here: -https://raw.githubusercontent.com/theuni/osx-cross-depends/master/patches/cdrtools/genisoimage.diff +The patch can be seen here: [theuni/osx-cross-depends](https://raw.githubusercontent.com/theuni/osx-cross-depends/master/patches/cdrtools/genisoimage.diff). No effort was made to fix this cleanly, so it likely leaks memory badly. But it's only used for a single invocation, so that's no real concern. genisoimage cannot compress DMGs, so afterwards, the 'dmg' tool from the libdmg-hfsplus project is used to compress it. There are several bugs in this tool and its maintainer has seemingly abandoned the project. It has been forked -and is available (with fixes) here: https://github.com/theuni/libdmg-hfsplus . +and is available (with fixes) here: [theuni/libdmg-hfsplus](https://github.com/theuni/libdmg-hfsplus). The 'dmg' tool has the ability to create DMGs from scratch as well, but this functionality is broken. Only the compression feature is currently used. @@ -77,6 +77,6 @@ build process to remain somewhat deterministic. Here's how it works: that have been previously (deterministically) built in order to create a final dmg. - The Apple keyholder uses this unsigned app to create a detached signature, - using the script that is also included there. + using the script that is also included there. Detached signatures are available from this [repository](https://github.com/bitcoin-core/bitcoin-detached-sigs). - Builders feed the unsigned app + detached signature back into Gitian. It uses the pre-built tools to recombine the pieces into a deterministic dmg. diff --git a/doc/bips.md b/doc/bips.md index b4b62e781ec6..eae067ccfcdb 100644 --- a/doc/bips.md +++ b/doc/bips.md @@ -17,11 +17,11 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.13.0**): * [`BIP 61`](https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki): The 'reject' protocol message (and the protocol version bump to 70002) was added in **v0.9.0** ([PR #3185](https://github.com/bitcoin/bitcoin/pull/3185)). * [`BIP 65`](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki): The CHECKLOCKTIMEVERIFY softfork was merged in **v0.12.0** ([PR #6351](https://github.com/bitcoin/bitcoin/pull/6351)), and backported to **v0.11.2** and **v0.10.4**. Mempool-only CLTV was added in [PR #6124](https://github.com/bitcoin/bitcoin/pull/6124). * [`BIP 66`](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki): The strict DER rules and associated version 3 blocks have been implemented since **v0.10.0** ([PR #5713](https://github.com/bitcoin/bitcoin/pull/5713)). -* [`BIP 68`](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki): Sequence locks have been implemented as of **v0.12.1** ([PR #7184](https://github.com/bitcoin/bitcoin/pull/7184)). +* [`BIP 68`](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki): Sequence locks have been implemented as of **v0.12.1** ([PR #7184](https://github.com/bitcoin/bitcoin/pull/7184)), and have been activated since *block 419328*. * [`BIP 70`](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki) [`71`](https://github.com/bitcoin/bips/blob/master/bip-0071.mediawiki) [`72`](https://github.com/bitcoin/bips/blob/master/bip-0072.mediawiki): Payment Protocol support has been available in Bitcoin Core GUI since **v0.9.0** ([PR #5216](https://github.com/bitcoin/bitcoin/pull/5216)). * [`BIP 111`](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki): `NODE_BLOOM` service bit added, and enforced for all peer versions as of **v0.13.0** ([PR #6579](https://github.com/bitcoin/bitcoin/pull/6579) and [PR #6641](https://github.com/bitcoin/bitcoin/pull/6641)). -* [`BIP 112`](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki): The CHECKSEQUENCEVERIFY opcode has been implemented since **v0.12.1** ([PR #7524](https://github.com/bitcoin/bitcoin/pull/7524)). -* [`BIP 113`](https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki): Median time past lock-time calculations have been implemented since **v0.12.1** ([PR #6566](https://github.com/bitcoin/bitcoin/pull/6566)). +* [`BIP 112`](https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki): The CHECKSEQUENCEVERIFY opcode has been implemented since **v0.12.1** ([PR #7524](https://github.com/bitcoin/bitcoin/pull/7524)) and has been activated since *block 419328*. +* [`BIP 113`](https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki): Median time past lock-time calculations have been implemented since **v0.12.1** ([PR #6566](https://github.com/bitcoin/bitcoin/pull/6566)) and have been activated since *block 419328*. * [`BIP 125`](https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki): Opt-in full replace-by-fee signaling honoured in mempool and mining as of **v0.12.0** ([PR 6871](https://github.com/bitcoin/bitcoin/pull/6871)). * [`BIP 130`](https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki): direct headers announcement is negotiated with peer versions `>=70012` as of **v0.12.0** ([PR 6494](https://github.com/bitcoin/bitcoin/pull/6494)). * [`BIP 133`](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki): feefilter messages are respected and sent for peer versions `>=70013` as of **v0.13.0** ([PR 7542](https://github.com/bitcoin/bitcoin/pull/7542)). diff --git a/doc/build-osx.md b/doc/build-osx.md index 94d442f174f0..e6b52c6e5573 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -5,11 +5,13 @@ The built-in one is located in `/Applications/Utilities/Terminal.app`. Preparation ----------- -Download and install [Xcode](https://developer.apple.com/xcode/download). +Install the OS X command line tools: -Once installed, run `xcode-select --install` to install the OS X command line tools. +`xcode-select --install` -Install [Homebrew](http://brew.sh). +When the popup appears, click `Install`. + +Then install [Homebrew](http://brew.sh). Dependencies ---------------------- diff --git a/doc/release-notes/bitcoin/release-notes-0.12.0.md b/doc/release-notes/bitcoin/release-notes-0.12.0.md index 85c020a9cd0b..cf74a1797520 100644 --- a/doc/release-notes/bitcoin/release-notes-0.12.0.md +++ b/doc/release-notes/bitcoin/release-notes-0.12.0.md @@ -104,9 +104,6 @@ announcing their headers directly, instead of just announcing the hash. In a reorganization, all new headers are sent, instead of just the new tip. This can often prevent an extra roundtrip before the actual block is downloaded. -With this change, pruning nodes are now able to relay new blocks to compatible -peers. - Memory pool limiting -------------------- @@ -188,6 +185,14 @@ the OP_RETURN. The limit on OP_RETURN output size is now applied to the entire serialized scriptPubKey, 83 bytes by default. (the previous 80 byte default plus three bytes overhead) +Relay: New and only new blocks relayed when pruning +--------------------------------------------------- + +When running in pruned mode, the client will now relay new blocks. When +responding to the `getblocks` message, only hashes of blocks that are on disk +and are likely to remain there for some reasonable time window (1 hour) will be +returned (previously all relevant hashes were returned). + Relay and Mining: Priority transactions --------------------------------------- @@ -887,5 +892,3 @@ Thanks to everyone who directly contributed to this release: - zathras-crypto As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/). - - diff --git a/doc/release-process.md b/doc/release-process.md index 6d76e1f6b394..bc8dacc64011 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -1,7 +1,7 @@ Release Process ==================== -* Update translations, see [translation_process.md](https://github.com/dashpay/dash/blob/master/doc/translation_process.md#syncing-with-transifex) +* Update translations, see [translation_process.md](https://github.com/dashpay/dash/blob/master/doc/translation_process.md#synchronising-translations). * Update hardcoded [seeds](/contrib/seeds) * * * @@ -53,7 +53,7 @@ Check out the source code in the following directory hierarchy. git pull popd - Ensure gitian-builder is up-to-date to take advantage of new caching features (`e9741525c` or later is recommended). + Ensure gitian-builder is up-to-date: pushd ./gitian-builder git pull @@ -64,13 +64,7 @@ Check out the source code in the following directory hierarchy. wget -P inputs https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch wget -P inputs http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz - Register and download the Apple SDK: see [OS X readme](README_osx.txt) for details. - - https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/xcode_6.1.1/xcode_6.1.1.dmg - - Using a Mac, create a tarball for the 10.9 SDK and copy it to the inputs directory: - - tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.9.sdk.tar.gz MacOSX10.9.sdk + Create the OS X SDK tarball, see the [OS X readme](README_osx.md) for details, and copy it into the inputs directory. ### Optional: Seed the Gitian sources cache and offline git repositories diff --git a/doc/tor.md b/doc/tor.md index 1b8855502d1c..05e3f9e02387 100644 --- a/doc/tor.md +++ b/doc/tor.md @@ -122,12 +122,22 @@ Starting with Tor version 0.2.7.1 it is possible, through Tor's control socket API, to create and destroy 'ephemeral' hidden services programmatically. Dash Core has been updated to make use of this. -This means that if Tor is running (and proper authorization is available), -Dash Core automatically creates a hidden service to listen on, without -manual configuration. This will positively affect the number of available -.onion nodes. +This means that if Tor is running (and proper authentication has been configured), +Dash Core automatically creates a hidden service to listen on. This will positively +affect the number of available .onion nodes. This new feature is enabled by default if Dash Core is listening, and a connection to Tor can be made. It can be configured with the `-listenonion`, `-torcontrol` and `-torpassword` settings. To show verbose debugging information, pass `-debug=tor`. + +Connecting to Tor's control socket API requires one of two authentication methods to be +configured. For cookie authentication the user running dashd must have write access +to the `CookieAuthFile` specified in Tor configuration. In some cases this is +preconfigured and the creation of a hidden service is automatic. If permission problems +are seen with `-debug=tor` they can be resolved by adding both the user running tor and +the user running dashd to the same group and setting permissions appropriately. On +Debian-based systems the user running dashd can be added to the debian-tor group, +which has the appropriate permissions. An alternative authentication method is the use +of the `-torpassword` flag and a `hash-password` which can be enabled and specified in +Tor configuration. \ No newline at end of file diff --git a/qa/README.md b/qa/README.md index c299561b3838..3f1cb9c8fc40 100644 --- a/qa/README.md +++ b/qa/README.md @@ -16,6 +16,12 @@ The python3-zmq library is required. On Ubuntu or Debian it can be installed via sudo apt-get install python3-zmq ``` +OS X +------ +``` +pip3 install pyzmq +``` + Running tests ============= @@ -36,7 +42,7 @@ Run all possible tests with qa/pull-tester/rpc-tests.py -extended By default, tests will be run in parallel if you want to specify how many -tests should be run in parallel, append `-paralell=n` (default n=4). +tests should be run in parallel, append `-parallel=n` (default n=4). If you want to create a basic coverage report for the rpc test suite, append `--coverage`. diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py index ab8cea220d53..92ded914725b 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/qa/pull-tester/rpc-tests.py @@ -110,6 +110,8 @@ #Tests testScripts = [ + # longest test should go first, to favor running tests in parallel + 'p2p-fullblocktest.py', # NOTE: needs dash_hash to pass 'walletbackup.py', 'bip68-112-113-p2p.py', 'wallet.py', @@ -139,7 +141,6 @@ 'timestampindex.py', 'spentindex.py', 'decodescript.py', - 'p2p-fullblocktest.py', # NOTE: needs dash_hash to pass 'blockchain.py', 'disablewallet.py', 'sendheaders.py', # NOTE: needs dash_hash to pass @@ -206,7 +207,7 @@ def runtests(): if coverage: flags.append(coverage.flag) - if len(test_list) > 1: + if len(test_list) > 1 and run_parallel > 1: # Populate cache subprocess.check_output([RPC_TESTS_DIR + 'create_cache.py'] + flags) @@ -270,7 +271,7 @@ def get_next(self): log_stdout, log_stderr)) if not self.jobs: - raise IndexError('%s from empty list' % __name__) + raise IndexError('pop from empty list') while True: # Return first proc that finishes time.sleep(.5) diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py index 4ceb5b0867d3..ae3e1fa99470 100755 --- a/qa/rpc-tests/fundrawtransaction.py +++ b/qa/rpc-tests/fundrawtransaction.py @@ -6,7 +6,14 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -# Create one-input, one-output, no-fee transaction: + +def get_unspent(listunspent, amount): + for utx in listunspent: + if utx['amount'] == amount: + return utx + raise AssertionError('Could not find unspent with amount={}'.format(amount)) + + class RawTransactionsTest(BitcoinTestFramework): def __init__(self): @@ -71,7 +78,7 @@ def run_test(self): rawtxfund = self.nodes[2].fundrawtransaction(rawtx) fee = rawtxfund['fee'] dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) - assert(len(dec_tx['vin']) > 0) #test if we have enought inputs + assert(len(dec_tx['vin']) > 0) #test that we have enough inputs ############################## # simple test with two coins # @@ -123,14 +130,7 @@ def run_test(self): ######################################################################### # test a fundrawtransaction with a VIN greater than the required amount # ######################################################################### - utx = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 50: - utx = aUtx - break - - assert(utx!=False) + utx = get_unspent(self.nodes[2].listunspent(), 50) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] outputs = { self.nodes[0].getnewaddress() : 10 } @@ -151,14 +151,7 @@ def run_test(self): ##################################################################### # test a fundrawtransaction with which will not get a change output # ##################################################################### - utx = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 50: - utx = aUtx - break - - assert(utx!=False) + utx = get_unspent(self.nodes[2].listunspent(), 50) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] outputs = { self.nodes[0].getnewaddress() : Decimal(50) - fee - feeTolerance } @@ -180,14 +173,7 @@ def run_test(self): #################################################### # test a fundrawtransaction with an invalid option # #################################################### - utx = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 50: - utx = aUtx - break - - assert_equal(utx!=False, True) + utx = get_unspent(self.nodes[2].listunspent(), 50) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] outputs = { self.nodes[0].getnewaddress() : Decimal(40) } @@ -205,14 +191,7 @@ def run_test(self): ############################################################ # test a fundrawtransaction with an invalid change address # ############################################################ - utx = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 50: - utx = aUtx - break - - assert_equal(utx!=False, True) + utx = get_unspent(self.nodes[2].listunspent(), 50) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] outputs = { self.nodes[0].getnewaddress() : Decimal(40) } @@ -227,18 +206,10 @@ def run_test(self): assert("changeAddress must be a valid dash address" in e.error['message']) - ############################################################ # test a fundrawtransaction with a provided change address # ############################################################ - utx = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 50: - utx = aUtx - break - - assert_equal(utx!=False, True) + utx = get_unspent(self.nodes[2].listunspent(), 50) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] outputs = { self.nodes[0].getnewaddress() : Decimal(40) } @@ -247,24 +218,22 @@ def run_test(self): assert_equal(utx['txid'], dec_tx['vin'][0]['txid']) change = self.nodes[2].getnewaddress() + try: + rawtxfund = self.nodes[2].fundrawtransaction(rawtx, {'changeAddress': change, 'changePosition': 2}) + except JSONRPCException as e: + assert('changePosition out of bounds' == e.error['message']) + else: + assert(False) rawtxfund = self.nodes[2].fundrawtransaction(rawtx, {'changeAddress': change, 'changePosition': 0}) dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex']) out = dec_tx['vout'][0]; assert_equal(change, out['scriptPubKey']['addresses'][0]) - ######################################################################### # test a fundrawtransaction with a VIN smaller than the required amount # ######################################################################### - utx = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 10: - utx = aUtx - break - - assert(utx!=False) + utx = get_unspent(self.nodes[2].listunspent(), 10) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] outputs = { self.nodes[0].getnewaddress() : 10 } @@ -299,17 +268,8 @@ def run_test(self): ########################################### # test a fundrawtransaction with two VINs # ########################################### - utx = False - utx2 = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 10: - utx = aUtx - if aUtx['amount'] == 50: - utx2 = aUtx - - - assert(utx!=False) + utx = get_unspent(self.nodes[2].listunspent(), 10) + utx2 = get_unspent(self.nodes[2].listunspent(), 50) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ] outputs = { self.nodes[0].getnewaddress() : 60 } @@ -341,17 +301,8 @@ def run_test(self): ######################################################### # test a fundrawtransaction with two VINs and two vOUTs # ######################################################### - utx = False - utx2 = False - listunspent = self.nodes[2].listunspent() - for aUtx in listunspent: - if aUtx['amount'] == 10: - utx = aUtx - if aUtx['amount'] == 50: - utx2 = aUtx - - - assert(utx!=False) + utx = get_unspent(self.nodes[2].listunspent(), 10) + utx2 = get_unspent(self.nodes[2].listunspent(), 50) inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ] outputs = { self.nodes[0].getnewaddress() : 60, self.nodes[0].getnewaddress() : 10 } diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py index d225e29b500f..7cbe69c29b2b 100755 --- a/qa/rpc-tests/pruning.py +++ b/qa/rpc-tests/pruning.py @@ -151,14 +151,14 @@ def reorg_test(self): print("Reconnect nodes") connect_nodes(self.nodes[0], 1) connect_nodes(self.nodes[2], 1) - sync_blocks(self.nodes[0:3]) + sync_blocks(self.nodes[0:3], timeout=120) print("Verify height on node 2:",self.nodes[2].getblockcount()) print("Usage possibly still high bc of stale blocks in block files:", calc_usage(self.prunedir)) print("Mine 220 more blocks so we have requisite history (some blocks will be big and cause pruning of previous chain)") self.nodes[0].generate(220) #node 0 has many large tx's in its mempool from the disconnects - sync_blocks(self.nodes[0:3]) + sync_blocks(self.nodes[0:3], timeout=300) usage = calc_usage(self.prunedir) print("Usage should be below target:", usage) diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py index cec626b0db52..ab5cb845706f 100755 --- a/qa/rpc-tests/rawtransactions.py +++ b/qa/rpc-tests/rawtransactions.py @@ -143,6 +143,20 @@ def run_test(self): rawtx = self.nodes[0].createrawtransaction(inputs, outputs) decrawtx= self.nodes[0].decoderawtransaction(rawtx) assert_equal(decrawtx['vin'][0]['sequence'], 1000) + + inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : -1}] + outputs = { self.nodes[0].getnewaddress() : 1 } + assert_raises(JSONRPCException, self.nodes[0].createrawtransaction, inputs, outputs) + + inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967296}] + outputs = { self.nodes[0].getnewaddress() : 1 } + assert_raises(JSONRPCException, self.nodes[0].createrawtransaction, inputs, outputs) + + inputs = [ {'txid' : "1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000", 'vout' : 1, 'sequence' : 4294967294}] + outputs = { self.nodes[0].getnewaddress() : 1 } + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + decrawtx= self.nodes[0].decoderawtransaction(rawtx) + assert_equal(decrawtx['vin'][0]['sequence'], 4294967294) if __name__ == '__main__': RawTransactionsTest().main() diff --git a/qa/rpc-tests/sendheaders.py b/qa/rpc-tests/sendheaders.py index 6ab17d59b387..c3f3180b6bca 100755 --- a/qa/rpc-tests/sendheaders.py +++ b/qa/rpc-tests/sendheaders.py @@ -63,6 +63,21 @@ Expect: getdata request for 14 more blocks. f. Announce 1 more header that builds on that fork. Expect: no response. + +Part 5: Test handling of headers that don't connect. +a. Repeat 10 times: + 1. Announce a header that doesn't connect. + Expect: getheaders message + 2. Send headers chain. + Expect: getdata for the missing blocks, tip update. +b. Then send 9 more headers that don't connect. + Expect: getheaders message each time. +c. Announce a header that does connect. + Expect: no response. +d. Announce 49 headers that don't connect. + Expect: getheaders message each time. +e. Announce one more that doesn't connect. + Expect: disconnect. ''' class BaseNode(NodeConnCB): @@ -77,6 +92,8 @@ def __init__(self): self.last_getdata = None self.sleep_time = 0.05 self.block_announced = False + self.last_getheaders = None + self.disconnected = False def clear_last_announcement(self): with mininode_lock: @@ -127,6 +144,12 @@ def on_getdata(self, conn, message): def on_pong(self, conn, message): self.last_pong = message + def on_getheaders(self, conn, message): + self.last_getheaders = message + + def on_close(self, conn): + self.disconnected = True + # Test whether the last announcement we received had the # right header or the right inv # inv and headers should be lists of block hashes @@ -178,6 +201,11 @@ def wait_for_block(self, blockhash, timeout=60): self.sync(test_function, timeout) return + def wait_for_getheaders(self, timeout=60): + test_function = lambda: self.last_getheaders != None + self.sync(test_function, timeout) + return + def wait_for_getdata(self, hash_list, timeout=60): if hash_list == []: return @@ -186,6 +214,11 @@ def wait_for_getdata(self, hash_list, timeout=60): self.sync(test_function, timeout) return + def wait_for_disconnect(self, timeout=60): + test_function = lambda: self.disconnected + self.sync(test_function, timeout) + return + def send_header_for_blocks(self, new_blocks): headers_message = msg_headers() headers_message.headers = [ CBlockHeader(b) for b in new_blocks ] @@ -510,6 +543,78 @@ def run_test(self): print("Part 4: success!") + # Now deliver all those blocks we announced. + [ test_node.send_message(msg_block(x)) for x in blocks ] + + print("Part 5: Testing handling of unconnecting headers") + # First we test that receipt of an unconnecting header doesn't prevent + # chain sync. + for i in range(10): + test_node.last_getdata = None + blocks = [] + # Create two more blocks. + for j in range(2): + blocks.append(create_block(tip, create_coinbase(height), block_time)) + blocks[-1].solve() + tip = blocks[-1].sha256 + block_time += 1 + height += 1 + # Send the header of the second block -> this won't connect. + with mininode_lock: + test_node.last_getheaders = None + test_node.send_header_for_blocks([blocks[1]]) + test_node.wait_for_getheaders(timeout=1) + test_node.send_header_for_blocks(blocks) + test_node.wait_for_getdata([x.sha256 for x in blocks]) + [ test_node.send_message(msg_block(x)) for x in blocks ] + test_node.sync_with_ping() + assert_equal(int(self.nodes[0].getbestblockhash(), 16), blocks[1].sha256) + + blocks = [] + # Now we test that if we repeatedly don't send connecting headers, we + # don't go into an infinite loop trying to get them to connect. + MAX_UNCONNECTING_HEADERS = 10 + for j in range(MAX_UNCONNECTING_HEADERS+1): + blocks.append(create_block(tip, create_coinbase(height), block_time)) + blocks[-1].solve() + tip = blocks[-1].sha256 + block_time += 1 + height += 1 + + for i in range(1, MAX_UNCONNECTING_HEADERS): + # Send a header that doesn't connect, check that we get a getheaders. + with mininode_lock: + test_node.last_getheaders = None + test_node.send_header_for_blocks([blocks[i]]) + test_node.wait_for_getheaders(timeout=1) + + # Next header will connect, should re-set our count: + test_node.send_header_for_blocks([blocks[0]]) + + # Remove the first two entries (blocks[1] would connect): + blocks = blocks[2:] + + # Now try to see how many unconnecting headers we can send + # before we get disconnected. Should be 5*MAX_UNCONNECTING_HEADERS + for i in range(5*MAX_UNCONNECTING_HEADERS - 1): + # Send a header that doesn't connect, check that we get a getheaders. + with mininode_lock: + test_node.last_getheaders = None + test_node.send_header_for_blocks([blocks[i%len(blocks)]]) + test_node.wait_for_getheaders(timeout=1) + + # Eventually this stops working. + with mininode_lock: + self.last_getheaders = None + test_node.send_header_for_blocks([blocks[-1]]) + + # Should get disconnected + test_node.wait_for_disconnect() + with mininode_lock: + self.last_getheaders = True + + print("Part 5: success!") + # Finally, check that the inv node never received a getdata request, # throughout the test assert_equal(inv_node.last_getdata, None) diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 822c10ac1a06..c1735dc76696 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -1319,7 +1319,7 @@ def got_data(self): def send_message(self, message, pushbuf=False): if self.state != "connected" and not pushbuf: - return + raise IOError('Not connected, no pushbuf') self.show_debug_msg("Send %s" % repr(message)) command = message.command data = message.serialize() diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py index 89396863c0cc..d268063ad81e 100644 --- a/qa/rpc-tests/test_framework/util.py +++ b/qa/rpc-tests/test_framework/util.py @@ -170,17 +170,22 @@ def initialize_datadir(dirname, n): datadir = os.path.join(dirname, "node"+str(n)) if not os.path.isdir(datadir): os.makedirs(datadir) + rpc_u, rpc_p = rpc_auth_pair(n) with open(os.path.join(datadir, "dash.conf"), 'w') as f: f.write("regtest=1\n") - f.write("rpcuser=rt\n") - f.write("rpcpassword=rt\n") + f.write("rpcuser=" + rpc_u + "\n") + f.write("rpcpassword=" + rpc_p + "\n") f.write("port="+str(p2p_port(n))+"\n") f.write("rpcport="+str(rpc_port(n))+"\n") f.write("listenonion=0\n") return datadir +def rpc_auth_pair(n): + return 'rpcuser💻' + str(n), 'rpcpass🔑' + str(n) + def rpc_url(i, rpchost=None): - return "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i)) + rpc_u, rpc_p = rpc_auth_pair(i) + return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, rpchost or '127.0.0.1', rpc_port(i)) def wait_for_bitcoind_start(process, url, i): ''' diff --git a/share/setup.nsi.in b/share/setup.nsi.in index e8becf25231c..05cec6aca2cc 100644 --- a/share/setup.nsi.in +++ b/share/setup.nsi.in @@ -92,6 +92,7 @@ Section -post SEC0001 !insertmacro MUI_STARTMENU_WRITE_BEGIN Application CreateDirectory $SMPROGRAMS\$StartMenuGroup CreateShortcut "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@ + CreateShortcut "$SMPROGRAMS\$StartMenuGroup\@PACKAGE_NAME@ (testnet, @WINDOWS_BITS@-bit).lnk" "$INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@" "-testnet" "$INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@" 1 CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe !insertmacro MUI_STARTMENU_WRITE_END WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)" @@ -139,6 +140,7 @@ Section -un.post UNSEC0001 DeleteRegKey HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" + Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\@PACKAGE_NAME@ (testnet, @WINDOWS_BITS@-bit).lnk" Delete /REBOOTOK "$SMSTARTUP\Dash.lnk" Delete /REBOOTOK $INSTDIR\uninstall.exe Delete /REBOOTOK $INSTDIR\debug.log diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index dbdf3fcea4b2..be3bef111429 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -169,6 +169,7 @@ BITCOIN_QT_H = \ RES_ICONS = \ qt/res/icons/bitcoin.ico \ + qt/res/icons/bitcoin_testnet.ico \ qt/res/icons/bitcoin.png \ qt/res/icons/chevron.png \ qt/res/icons/warning.png \ diff --git a/src/chainparams.cpp b/src/chainparams.cpp index c289f4f26c4f..68c6499ce235 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -19,14 +19,6 @@ #include "chainparamsseeds.h" -std::string CDNSSeedData::getHost(uint64_t requiredServiceBits) const { - //use default host for non-filter-capable seeds or if we use the default service bits (NODE_NETWORK) - if (!supportsServiceBitsFiltering || requiredServiceBits == NODE_NETWORK) - return host; - - return strprintf("x%x.%s", requiredServiceBits, host); -} - static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) { CMutableTransaction txNew; diff --git a/src/chainparams.h b/src/chainparams.h index ed1d1abca9c1..fdad53d9d78a 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -13,11 +13,9 @@ #include -class CDNSSeedData { -public: +struct CDNSSeedData { std::string name, host; bool supportsServiceBitsFiltering; - std::string getHost(uint64_t requiredServiceBits) const; CDNSSeedData(const std::string &strName, const std::string &strHost, bool supportsServiceBitsFilteringIn = false) : name(strName), host(strHost), supportsServiceBitsFiltering(supportsServiceBitsFilteringIn) {} }; diff --git a/src/init.cpp b/src/init.cpp index a442b241fe79..c9d87fa358a2 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -563,7 +563,6 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-mempoolreplacement", strprintf(_("Enable transaction replacement in the memory pool (default: %u)"), DEFAULT_ENABLE_REPLACEMENT)); strUsage += HelpMessageGroup(_("Block creation options:")); - strUsage += HelpMessageOpt("-blockminsize=", strprintf(_("Set minimum block size in bytes (default: %u)"), DEFAULT_BLOCK_MIN_SIZE)); strUsage += HelpMessageOpt("-blockmaxsize=", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE)); strUsage += HelpMessageOpt("-blockprioritysize=", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE)); if (showDebug) @@ -590,11 +589,20 @@ std::string HelpMessage(HelpMessageMode mode) std::string LicenseInfo() { + const std::string URL_SOURCE_CODE = ""; + const std::string URL_WEBSITE = ""; // todo: remove urls from translations on next change return CopyrightHolders(_("Copyright (C)"), 2014, COPYRIGHT_YEAR) + "\n" + "\n" + - _("This is experimental software.") + "\n" + + strprintf(_("Please contribute if you find %s useful. " + "Visit %s for further information about the software."), + PACKAGE_NAME, URL_WEBSITE) + + "\n" + + strprintf(_("The source code is available from %s."), + URL_SOURCE_CODE) + + "\n" + "\n" + + _("This is experimental software.") + "\n" + _("Distributed under the MIT software license, see the accompanying file COPYING or .") + "\n" + "\n" + _("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.") + @@ -1036,6 +1044,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (GetBoolArg("-whitelistalwaysrelay", false)) InitWarning(_("Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.")); + if (mapArgs.count("-blockminsize")) + InitWarning("Unsupported argument -blockminsize ignored."); + // Checkmempool and checkblockindex default to true in regtest mode int ratio = std::min(std::max(GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000); if (ratio != 0) { diff --git a/src/miner.cpp b/src/miner.cpp index ba50a96acc20..1f72ff66110a 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -28,6 +28,7 @@ #include "masternode-sync.h" #include "validationinterface.h" +#include #include #include #include @@ -81,11 +82,6 @@ BlockAssembler::BlockAssembler(const CChainParams& _chainparams) nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE); // Limit to between 1K and MAX_BLOCK_SIZE-1K for sanity: nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MaxBlockSize(fDIP0001ActiveAtTip)-1000), nBlockMaxSize)); - - // Minimum block size you want to create; block will be filled with free transactions - // until there are no more or the block reaches this size: - nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE); - nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize); } void BlockAssembler::resetBlock() @@ -137,7 +133,7 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn) : pblock->GetBlockTime(); addPriorityTxs(); - addScoreTxs(); + addPackageTxs(); nLastBlockTx = nBlockTx; nLastBlockSize = nBlockSize; @@ -192,7 +188,38 @@ bool BlockAssembler::isStillDependent(CTxMemPool::txiter iter) return false; } +void BlockAssembler::onlyUnconfirmed(CTxMemPool::setEntries& testSet) +{ + for (CTxMemPool::setEntries::iterator iit = testSet.begin(); iit != testSet.end(); ) { + // Only test txs not already in the block + if (inBlock.count(*iit)) { + testSet.erase(iit++); + } + else { + iit++; + } + } +} +bool BlockAssembler::TestPackage(uint64_t packageSize, unsigned int packageSigOps) +{ + if (nBlockSize + packageSize >= nBlockMaxSize) + return false; + if (nBlockSigOps + packageSigOps >= MaxBlockSigOps(fDIP0001ActiveAtTip)) + return false; + return true; +} + +// Perform transaction-level checks before adding to block: +// - transaction finality (locktime) +bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package) +{ + BOOST_FOREACH (const CTxMemPool::txiter it, package) { + if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff)) + return false; + } + return true; +} bool BlockAssembler::TestForBlock(CTxMemPool::txiter iter) { @@ -257,59 +284,175 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter) } } -void BlockAssembler::addScoreTxs() +void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, + indexed_modified_transaction_set &mapModifiedTx) +{ + BOOST_FOREACH(const CTxMemPool::txiter it, alreadyAdded) { + CTxMemPool::setEntries descendants; + mempool.CalculateDescendants(it, descendants); + // Insert all descendants (not yet in block) into the modified set + BOOST_FOREACH(CTxMemPool::txiter desc, descendants) { + if (alreadyAdded.count(desc)) + continue; + modtxiter mit = mapModifiedTx.find(desc); + if (mit == mapModifiedTx.end()) { + CTxMemPoolModifiedEntry modEntry(desc); + modEntry.nSizeWithAncestors -= it->GetTxSize(); + modEntry.nModFeesWithAncestors -= it->GetModifiedFee(); + modEntry.nSigOpCountWithAncestors -= it->GetSigOpCount(); + mapModifiedTx.insert(modEntry); + } else { + mapModifiedTx.modify(mit, update_for_parent_inclusion(it)); + } + } + } +} + +// Skip entries in mapTx that are already in a block or are present +// in mapModifiedTx (which implies that the mapTx ancestor state is +// stale due to ancestor inclusion in the block) +// Also skip transactions that we've already failed to add. This can happen if +// we consider a transaction in mapModifiedTx and it fails: we can then +// potentially consider it again while walking mapTx. It's currently +// guaranteed to fail again, but as a belt-and-suspenders check we put it in +// failedTx and avoid re-evaluation, since the re-evaluation would be using +// cached size/sigops/fee values that are not actually correct. +bool BlockAssembler::SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx) +{ + assert (it != mempool.mapTx.end()); + if (mapModifiedTx.count(it) || inBlock.count(it) || failedTx.count(it)) + return true; + return false; +} + +void BlockAssembler::SortForBlock(const CTxMemPool::setEntries& package, CTxMemPool::txiter entry, std::vector& sortedEntries) +{ + // Sort package by ancestor count + // If a transaction A depends on transaction B, then A's ancestor count + // must be greater than B's. So this is sufficient to validly order the + // transactions for block inclusion. + sortedEntries.clear(); + sortedEntries.insert(sortedEntries.begin(), package.begin(), package.end()); + std::sort(sortedEntries.begin(), sortedEntries.end(), CompareTxIterByAncestorCount()); +} + +// This transaction selection algorithm orders the mempool based +// on feerate of a transaction including all unconfirmed ancestors. +// Since we don't remove transactions from the mempool as we select them +// for block inclusion, we need an alternate method of updating the feerate +// of a transaction with its not-yet-selected ancestors as we go. +// This is accomplished by walking the in-mempool descendants of selected +// transactions and storing a temporary modified state in mapModifiedTxs. +// Each time through the loop, we compare the best transaction in +// mapModifiedTxs with the next transaction in the mempool to decide what +// transaction package to work on next. +void BlockAssembler::addPackageTxs() { - std::priority_queue, ScoreCompare> clearedTxs; - CTxMemPool::setEntries waitSet; - CTxMemPool::indexed_transaction_set::index::type::iterator mi = mempool.mapTx.get().begin(); + // mapModifiedTx will store sorted packages after they are modified + // because some of their txs are already in the block + indexed_modified_transaction_set mapModifiedTx; + // Keep track of entries that failed inclusion, to avoid duplicate work + CTxMemPool::setEntries failedTx; + + // Start by adding all descendants of previously added txs to mapModifiedTx + // and modifying them for their already included ancestors + UpdatePackagesForAdded(inBlock, mapModifiedTx); + + CTxMemPool::indexed_transaction_set::index::type::iterator mi = mempool.mapTx.get().begin(); CTxMemPool::txiter iter; - while (!blockFinished && (mi != mempool.mapTx.get().end() || !clearedTxs.empty())) + while (mi != mempool.mapTx.get().end() || !mapModifiedTx.empty()) { - // If no txs that were previously postponed are available to try - // again, then try the next highest score tx - if (clearedTxs.empty()) { + // First try to find a new transaction in mapTx to evaluate. + if (mi != mempool.mapTx.get().end() && + SkipMapTxEntry(mempool.mapTx.project<0>(mi), mapModifiedTx, failedTx)) { + ++mi; + continue; + } + + // Now that mi is not stale, determine which transaction to evaluate: + // the next entry from mapTx, or the best from mapModifiedTx? + bool fUsingModified = false; + + modtxscoreiter modit = mapModifiedTx.get().begin(); + if (mi == mempool.mapTx.get().end()) { + // We're out of entries in mapTx; use the entry from mapModifiedTx + iter = modit->iter; + fUsingModified = true; + } else { + // Try to compare the mapTx entry to the mapModifiedTx entry iter = mempool.mapTx.project<0>(mi); - mi++; + if (modit != mapModifiedTx.get().end() && + CompareModifiedEntry()(*modit, CTxMemPoolModifiedEntry(iter))) { + // The best entry in mapModifiedTx has higher score + // than the one from mapTx. + // Switch which transaction (package) to consider + iter = modit->iter; + fUsingModified = true; + } else { + // Either no entry in mapModifiedTx, or it's worse than mapTx. + // Increment mi for the next loop iteration. + ++mi; + } } - // If a previously postponed tx is available to try again, then it - // has higher score than all untried so far txs - else { - iter = clearedTxs.top(); - clearedTxs.pop(); + + // We skip mapTx entries that are inBlock, and mapModifiedTx shouldn't + // contain anything that is inBlock. + assert(!inBlock.count(iter)); + + uint64_t packageSize = iter->GetSizeWithAncestors(); + CAmount packageFees = iter->GetModFeesWithAncestors(); + unsigned int packageSigOps = iter->GetSigOpCountWithAncestors(); + if (fUsingModified) { + packageSize = modit->nSizeWithAncestors; + packageFees = modit->nModFeesWithAncestors; + packageSigOps = modit->nSigOpCountWithAncestors; } - // If tx already in block, skip (added by addPriorityTxs) - if (inBlock.count(iter)) { - continue; + if (packageFees < ::minRelayTxFee.GetFee(packageSize)) { + // Everything else we might consider has a lower fee rate + return; } - // If tx is dependent on other mempool txs which haven't yet been included - // then put it in the waitSet - if (isStillDependent(iter)) { - waitSet.insert(iter); + if (!TestPackage(packageSize, packageSigOps)) { + if (fUsingModified) { + // Since we always look at the best entry in mapModifiedTx, + // we must erase failed entries so that we can consider the + // next best entry on the next loop iteration + mapModifiedTx.get().erase(modit); + failedTx.insert(iter); + } continue; } - // If the fee rate is below the min fee rate for mining, then we're done - // adding txs based on score (fee rate) - if (iter->GetModifiedFee() < ::minRelayTxFee.GetFee(iter->GetTxSize()) && nBlockSize >= nBlockMinSize) { - return; - } + CTxMemPool::setEntries ancestors; + uint64_t nNoLimit = std::numeric_limits::max(); + std::string dummy; + mempool.CalculateMemPoolAncestors(*iter, ancestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false); - // If this tx fits in the block add it, otherwise keep looping - if (TestForBlock(iter)) { - AddToBlock(iter); + onlyUnconfirmed(ancestors); + ancestors.insert(iter); - // This tx was successfully added, so - // add transactions that depend on this one to the priority queue to try again - BOOST_FOREACH(CTxMemPool::txiter child, mempool.GetMemPoolChildren(iter)) - { - if (waitSet.count(child)) { - clearedTxs.push(child); - waitSet.erase(child); - } + // Test if all tx's are Final + if (!TestPackageTransactions(ancestors)) { + if (fUsingModified) { + mapModifiedTx.get().erase(modit); + failedTx.insert(iter); } + continue; } + + // Package can be added. Sort the entries in a valid order. + vector sortedEntries; + SortForBlock(ancestors, iter, sortedEntries); + + for (size_t i=0; i= nBlockPrioritySize || !AllowFree(actualPriority)) { - return; + break; } // This tx was successfully added, so diff --git a/src/miner.h b/src/miner.h index 183c9a1ec9aa..4c8d6ef5b13e 100644 --- a/src/miner.h +++ b/src/miner.h @@ -11,6 +11,8 @@ #include #include +#include "boost/multi_index_container.hpp" +#include "boost/multi_index/ordered_index.hpp" class CBlockIndex; class CChainParams; @@ -30,6 +32,104 @@ struct CBlockTemplate std::vector vTxSigOps; }; +// Container for tracking updates to ancestor feerate as we include (parent) +// transactions in a block +struct CTxMemPoolModifiedEntry { + CTxMemPoolModifiedEntry(CTxMemPool::txiter entry) + { + iter = entry; + nSizeWithAncestors = entry->GetSizeWithAncestors(); + nModFeesWithAncestors = entry->GetModFeesWithAncestors(); + nSigOpCountWithAncestors = entry->GetSigOpCountWithAncestors(); + } + + CTxMemPool::txiter iter; + uint64_t nSizeWithAncestors; + CAmount nModFeesWithAncestors; + unsigned int nSigOpCountWithAncestors; +}; + +/** Comparator for CTxMemPool::txiter objects. + * It simply compares the internal memory address of the CTxMemPoolEntry object + * pointed to. This means it has no meaning, and is only useful for using them + * as key in other indexes. + */ +struct CompareCTxMemPoolIter { + bool operator()(const CTxMemPool::txiter& a, const CTxMemPool::txiter& b) const + { + return &(*a) < &(*b); + } +}; + +struct modifiedentry_iter { + typedef CTxMemPool::txiter result_type; + result_type operator() (const CTxMemPoolModifiedEntry &entry) const + { + return entry.iter; + } +}; + +// This matches the calculation in CompareTxMemPoolEntryByAncestorFee, +// except operating on CTxMemPoolModifiedEntry. +// TODO: refactor to avoid duplication of this logic. +struct CompareModifiedEntry { + bool operator()(const CTxMemPoolModifiedEntry &a, const CTxMemPoolModifiedEntry &b) + { + double f1 = (double)a.nModFeesWithAncestors * b.nSizeWithAncestors; + double f2 = (double)b.nModFeesWithAncestors * a.nSizeWithAncestors; + if (f1 == f2) { + return CTxMemPool::CompareIteratorByHash()(a.iter, b.iter); + } + return f1 > f2; + } +}; + +// A comparator that sorts transactions based on number of ancestors. +// This is sufficient to sort an ancestor package in an order that is valid +// to appear in a block. +struct CompareTxIterByAncestorCount { + bool operator()(const CTxMemPool::txiter &a, const CTxMemPool::txiter &b) + { + if (a->GetCountWithAncestors() != b->GetCountWithAncestors()) + return a->GetCountWithAncestors() < b->GetCountWithAncestors(); + return CTxMemPool::CompareIteratorByHash()(a, b); + } +}; + +typedef boost::multi_index_container< + CTxMemPoolModifiedEntry, + boost::multi_index::indexed_by< + boost::multi_index::ordered_unique< + modifiedentry_iter, + CompareCTxMemPoolIter + >, + // sorted by modified ancestor fee rate + boost::multi_index::ordered_non_unique< + // Reuse same tag from CTxMemPool's similar index + boost::multi_index::tag, + boost::multi_index::identity, + CompareModifiedEntry + > + > +> indexed_modified_transaction_set; + +typedef indexed_modified_transaction_set::nth_index<0>::type::iterator modtxiter; +typedef indexed_modified_transaction_set::index::type::iterator modtxscoreiter; + +struct update_for_parent_inclusion +{ + update_for_parent_inclusion(CTxMemPool::txiter it) : iter(it) {} + + void operator() (CTxMemPoolModifiedEntry &e) + { + e.nModFeesWithAncestors -= iter->GetFee(); + e.nSizeWithAncestors -= iter->GetTxSize(); + e.nSigOpCountWithAncestors -= iter->GetSigOpCount(); + } + + CTxMemPool::txiter iter; +}; + /** Generate a new block, without valid proof-of-work */ class BlockAssembler { @@ -40,7 +140,7 @@ class BlockAssembler CBlock* pblock; // Configuration parameters for the block size - unsigned int nBlockMaxSize, nBlockMinSize; + unsigned int nBlockMaxSize; // Information on the current status of the block uint64_t nBlockSize; @@ -54,7 +154,7 @@ class BlockAssembler int64_t nLockTimeCutoff; const CChainParams& chainparams; - // Variables used for addScoreTxs and addPriorityTxs + // Variables used for addPriorityTxs int lastFewTxs; bool blockFinished; @@ -71,16 +171,35 @@ class BlockAssembler void AddToBlock(CTxMemPool::txiter iter); // Methods for how to add transactions to a block. - /** Add transactions based on modified feerate */ - void addScoreTxs(); /** Add transactions based on tx "priority" */ void addPriorityTxs(); + /** Add transactions based on feerate including unconfirmed ancestors */ + void addPackageTxs(); - // helper function for addScoreTxs and addPriorityTxs + // helper function for addPriorityTxs /** Test if tx will still "fit" in the block */ bool TestForBlock(CTxMemPool::txiter iter); /** Test if tx still has unconfirmed parents not yet in block */ bool isStillDependent(CTxMemPool::txiter iter); + + // helper functions for addPackageTxs() + /** Remove confirmed (inBlock) entries from given set */ + void onlyUnconfirmed(CTxMemPool::setEntries& testSet); + /** Test if a new package would "fit" in the block */ + bool TestPackage(uint64_t packageSize, unsigned int packageSigOps); + /** Perform checks on each transaction in a package: + * locktime + * These checks should always succeed, and they're here + * only as an extra check in case of suboptimal node configuration */ + bool TestPackageTransactions(const CTxMemPool::setEntries& package); + /** Return true if given transaction from mapTx has already been evaluated, + * or if the transaction's cached data in mapTx is incorrect. */ + bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx); + /** Sort the package in an order that is valid to appear in a block */ + void SortForBlock(const CTxMemPool::setEntries& package, CTxMemPool::txiter entry, std::vector& sortedEntries); + /** Add descendants of given transactions to mapModifiedTx with ancestor + * state updated assuming given transactions are inBlock. */ + void UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx); }; /** Modify the extranonce in a block */ diff --git a/src/net.cpp b/src/net.cpp index f009ada74809..51310ce7ae19 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1502,6 +1502,18 @@ void MapPort(bool) +static std::string GetDNSHost(const CDNSSeedData& data, ServiceFlags* requiredServiceBits) +{ + //use default host for non-filter-capable seeds or if we use the default service bits (NODE_NETWORK) + if (!data.supportsServiceBitsFiltering || *requiredServiceBits == NODE_NETWORK) { + *requiredServiceBits = NODE_NETWORK; + return data.host; + } + + return strprintf("x%x.%s", *requiredServiceBits, data.host); +} + + void CConnman::ThreadDNSAddressSeed() { // goal: only query DNS seeds if address need is acute @@ -1529,7 +1541,7 @@ void CConnman::ThreadDNSAddressSeed() std::vector vIPs; std::vector vAdd; ServiceFlags requiredServiceBits = nRelevantServices; - if (LookupHost(seed.getHost(requiredServiceBits).c_str(), vIPs, 0, true)) + if (LookupHost(GetDNSHost(seed, &requiredServiceBits).c_str(), vIPs, 0, true)) { BOOST_FOREACH(const CNetAddr& ip, vIPs) { diff --git a/src/net_processing.cpp b/src/net_processing.cpp index ff2bfe60d7f7..1936f012f2f9 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -52,12 +52,22 @@ int64_t nTimeBestReceived = 0; // Used only to inform the wallet of when we last extern FeeFilterRounder filterRounder; +struct IteratorComparator +{ + template + bool operator()(const I& a, const I& b) + { + return &(*a) < &(*b); + } +}; + struct COrphanTx { CTransaction tx; NodeId fromPeer; + int64_t nTimeExpire; }; map mapOrphanTransactions GUARDED_BY(cs_main); -map > mapOrphanTransactionsByPrev GUARDED_BY(cs_main);; +map::iterator, IteratorComparator>> mapOrphanTransactionsByPrev GUARDED_BY(cs_main); void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main); // Internal stuff @@ -156,6 +166,8 @@ struct CNodeState { CBlockIndex *pindexLastCommonBlock; //! The best header we have sent our peer. CBlockIndex *pindexBestHeaderSent; + //! Length of current-streak of unconnecting headers announcements + int nUnconnectingHeaders; //! Whether we've started headers synchronization with this peer. bool fSyncStarted; //! When to potentially disconnect peer for stalling headers download @@ -180,6 +192,7 @@ struct CNodeState { hashLastUnknownBlock.SetNull(); pindexLastCommonBlock = NULL; pindexBestHeaderSent = NULL; + nUnconnectingHeaders = 0; fSyncStarted = false; nHeadersSyncTimeout = 0; nStallingSince = 0; @@ -510,6 +523,21 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals) // mapOrphanTransactions // +// TODO This is a temporary solution while backporting Bitcoin 0.13 changes into Dash +// See caller of this method +void LoopMapOrphanTransactionsByPrev(const CTransaction &tx, std::vector &vOrphanErase) +{ + for (size_t j = 0; j < tx.vin.size(); j++) { + auto itByPrev = mapOrphanTransactionsByPrev.find(tx.vin[j].prevout); + if (itByPrev == mapOrphanTransactionsByPrev.end()) continue; + for (auto mi = itByPrev->second.begin(); mi != itByPrev->second.end(); ++mi) { + const CTransaction& orphanTx = (*mi)->second.tx; + const uint256& orphanHash = orphanTx.GetHash(); + vOrphanErase.push_back(orphanHash); + } + } +} + bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { uint256 hash = tx.GetHash(); @@ -521,40 +549,42 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(c // large transaction with a missing parent then we assume // it will rebroadcast it later, after the parent transaction(s) // have been mined or received. - // 10,000 orphans, each of which is at most 5,000 bytes big is - // at most 500 megabytes of orphans: + // 100 orphans, each of which is at most 99,999 bytes big is + // at most 10 megabytes of orphans and somewhat more byprev index (in the worst case): unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION); - if (sz > 5000) + if (sz > MAX_STANDARD_TX_SIZE) { LogPrint("mempool", "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString()); return false; } - mapOrphanTransactions[hash].tx = tx; - mapOrphanTransactions[hash].fromPeer = peer; - BOOST_FOREACH(const CTxIn& txin, tx.vin) - mapOrphanTransactionsByPrev[txin.prevout.hash].insert(hash); + auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME}); + assert(ret.second); + BOOST_FOREACH(const CTxIn& txin, tx.vin) { + mapOrphanTransactionsByPrev[txin.prevout].insert(ret.first); + } - LogPrint("mempool", "stored orphan tx %s (mapsz %u prevsz %u)\n", hash.ToString(), + LogPrint("mempool", "stored orphan tx %s (mapsz %u outsz %u)\n", hash.ToString(), mapOrphanTransactions.size(), mapOrphanTransactionsByPrev.size()); return true; } -void static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) +int EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { map::iterator it = mapOrphanTransactions.find(hash); if (it == mapOrphanTransactions.end()) - return; + return 0; BOOST_FOREACH(const CTxIn& txin, it->second.tx.vin) { - map >::iterator itPrev = mapOrphanTransactionsByPrev.find(txin.prevout.hash); + auto itPrev = mapOrphanTransactionsByPrev.find(txin.prevout); if (itPrev == mapOrphanTransactionsByPrev.end()) continue; - itPrev->second.erase(hash); + itPrev->second.erase(it); if (itPrev->second.empty()) mapOrphanTransactionsByPrev.erase(itPrev); } mapOrphanTransactions.erase(it); + return 1; } void EraseOrphansFor(NodeId peer) @@ -566,8 +596,7 @@ void EraseOrphansFor(NodeId peer) map::iterator maybeErase = iter++; // increment to avoid iterator becoming invalid if (maybeErase->second.fromPeer == peer) { - EraseOrphanTx(maybeErase->second.tx.GetHash()); - ++nErased; + nErased += EraseOrphanTx(maybeErase->second.tx.GetHash()); } } if (nErased > 0) LogPrint("mempool", "Erased %d orphan tx from peer %d\n", nErased, peer); @@ -577,6 +606,26 @@ void EraseOrphansFor(NodeId peer) unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { unsigned int nEvicted = 0; + static int64_t nNextSweep; + int64_t nNow = GetTime(); + if (nNextSweep <= nNow) { + // Sweep out expired orphan pool entries: + int nErased = 0; + int64_t nMinExpTime = nNow + ORPHAN_TX_EXPIRE_TIME - ORPHAN_TX_EXPIRE_INTERVAL; + map::iterator iter = mapOrphanTransactions.begin(); + while (iter != mapOrphanTransactions.end()) + { + map::iterator maybeErase = iter++; + if (maybeErase->second.nTimeExpire <= nNow) { + nErased += EraseOrphanTx(maybeErase->second.tx.GetHash()); + } else { + nMinExpTime = std::min(maybeErase->second.nTimeExpire, nMinExpTime); + } + } + // Sweep again 5 minutes after the next entry that expires in order to batch the linear scan. + nNextSweep = nMinExpTime + ORPHAN_TX_EXPIRE_INTERVAL; + if (nErased > 0) LogPrint("mempool", "Erased %d orphan tx due to expiration\n", nErased); + } while (mapOrphanTransactions.size() > nMaxOrphans) { // Evict a random orphan: @@ -1532,7 +1581,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return true; } - vector vWorkQueue; + deque vWorkQueue; vector vEraseQueue; CTransaction tx; CTxLockRequest txLockRequest; @@ -1614,7 +1663,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, mempool.check(pcoinsTip); connman.RelayTransaction(tx); - vWorkQueue.push_back(inv.hash); + for (unsigned int i = 0; i < tx.vout.size(); i++) { + vWorkQueue.emplace_back(inv.hash, i); + } pfrom->nLastTXTime = GetTime(); @@ -1625,18 +1676,18 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Recursively process any orphan transactions that depended on this one set setMisbehaving; - for (unsigned int i = 0; i < vWorkQueue.size(); i++) - { - map >::iterator itByPrev = mapOrphanTransactionsByPrev.find(vWorkQueue[i]); + while (!vWorkQueue.empty()) { + auto itByPrev = mapOrphanTransactionsByPrev.find(vWorkQueue.front()); + vWorkQueue.pop_front(); if (itByPrev == mapOrphanTransactionsByPrev.end()) continue; - for (set::iterator mi = itByPrev->second.begin(); + for (auto mi = itByPrev->second.begin(); mi != itByPrev->second.end(); ++mi) { - const uint256& orphanHash = *mi; - const CTransaction& orphanTx = mapOrphanTransactions[orphanHash].tx; - NodeId fromPeer = mapOrphanTransactions[orphanHash].fromPeer; + const CTransaction& orphanTx = (*mi)->second.tx; + const uint256& orphanHash = orphanTx.GetHash(); + NodeId fromPeer = (*mi)->second.fromPeer; bool fMissingInputs2 = false; // Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan // resolution (that is, feeding people an invalid transaction based on LegitTxX in order to get @@ -1650,7 +1701,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, { LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString()); connman.RelayTransaction(orphanTx); - vWorkQueue.push_back(orphanHash); + for (unsigned int i = 0; i < orphanTx.vout.size(); i++) { + vWorkQueue.emplace_back(orphanHash, i); + } vEraseQueue.push_back(orphanHash); } else if (!fMissingInputs2) @@ -1679,13 +1732,29 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } else if (fMissingInputs) { - AddOrphanTx(tx, pfrom->GetId()); + bool fRejectedParents = false; // It may be the case that the orphans parents have all been rejected + BOOST_FOREACH(const CTxIn& txin, tx.vin) { + if (recentRejects->contains(txin.prevout.hash)) { + fRejectedParents = true; + break; + } + } + if (!fRejectedParents) { + BOOST_FOREACH(const CTxIn& txin, tx.vin) { + CInv inv(MSG_TX, txin.prevout.hash); + pfrom->AddInventoryKnown(inv); + if (!AlreadyHave(inv)) pfrom->AskFor(inv); + } + AddOrphanTx(tx, pfrom->GetId()); - // DoS prevention: do not allow mapOrphanTransactions to grow unbounded - unsigned int nMaxOrphanTx = (unsigned int)std::max((int64_t)0, GetArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS)); - unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTx); - if (nEvicted > 0) - LogPrint("mempool", "mapOrphan overflow, removed %u tx\n", nEvicted); + // DoS prevention: do not allow mapOrphanTransactions to grow unbounded + unsigned int nMaxOrphanTx = (unsigned int)std::max((int64_t)0, GetArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS)); + unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTx); + if (nEvicted > 0) + LogPrint("mempool", "mapOrphan overflow, removed %u tx\n", nEvicted); + } else { + LogPrint("mempool", "not keeping orphan with rejected parents %s\n",tx.GetHash().ToString()); + } } else { assert(recentRejects); recentRejects->insert(tx.GetHash()); @@ -1757,6 +1826,35 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CBlockIndex *pindexLast = NULL; { LOCK(cs_main); + CNodeState *nodestate = State(pfrom->GetId()); + + // If this looks like it could be a block announcement (nCount < + // MAX_BLOCKS_TO_ANNOUNCE), use special logic for handling headers that + // don't connect: + // - Send a getheaders message in response to try to connect the chain. + // - The peer can send up to MAX_UNCONNECTING_HEADERS in a row that + // don't connect before giving DoS points + // - Once a headers message is received that is valid and does connect, + // nUnconnectingHeaders gets reset back to 0. + if (nCount > 0 && mapBlockIndex.find(headers[0].hashPrevBlock) == mapBlockIndex.end() && nCount < MAX_BLOCKS_TO_ANNOUNCE) { + nodestate->nUnconnectingHeaders++; + connman.PushMessage(pfrom, NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()); + LogPrint("net", "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n", + headers[0].GetHash().ToString(), + headers[0].hashPrevBlock.ToString(), + pindexBestHeader->nHeight, + pfrom->id, nodestate->nUnconnectingHeaders); + // Set hashLastUnknownBlock for this peer, so that if we + // eventually get the headers - even from a different peer - + // we can use this peer to download. + UpdateBlockAvailability(pfrom->GetId(), headers.back().GetHash()); + + if (nodestate->nUnconnectingHeaders % MAX_UNCONNECTING_HEADERS == 0) { + Misbehaving(pfrom->GetId(), 20); + } + return true; + } + uint256 hashLastBlock; for (const CBlockHeader& header : headers) { if (!hashLastBlock.IsNull() && header.hashPrevBlock != hashLastBlock) { @@ -1781,6 +1879,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, { LOCK(cs_main); + CNodeState *nodestate = State(pfrom->GetId()); + if (nodestate->nUnconnectingHeaders > 0) { + LogPrint("net", "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom->id, nodestate->nUnconnectingHeaders); + } + nodestate->nUnconnectingHeaders = 0; + if (pindexLast) UpdateBlockAvailability(pfrom->GetId(), pindexLast->GetBlockHash()); @@ -1807,7 +1911,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } bool fCanDirectFetch = CanDirectFetch(chainparams.GetConsensus()); - CNodeState *nodestate = State(pfrom->GetId()); // If this set of headers is valid and ends in a block with at least as // much work as our tip, download as much as possible. if (fCanDirectFetch && pindexLast->IsValid(BLOCK_VALID_TREE) && chainActive.Tip()->nChainWork <= pindexLast->nChainWork) { diff --git a/src/net_processing.h b/src/net_processing.h index 13fceb55c3f7..9ff1ab8da8f2 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -9,6 +9,13 @@ #include "net.h" #include "validationinterface.h" +/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */ +static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100; +/** Expiration time for orphan transactions in seconds */ +static const int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60; +/** Minimum time between orphan transactions expire time checks in seconds */ +static const int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60; + /** Headers download timeout expressed in microseconds * Timeout = base + per_header * (expected number of headers) */ static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_BASE = 15 * 60 * 1000000; // 15 minutes diff --git a/src/policy/policy.h b/src/policy/policy.h index 69383c2e39a6..8da0f3884287 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -14,9 +14,8 @@ class CCoinsViewCache; -/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/ +/** Default for -blockmaxsize, which controls the maximum size of block the mining code will create **/ static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; -static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0; /** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 10000; // was 50000 in 0.12.0 and it is 0 in Bitcoin since 0.12 /** The maximum size for transactions we're willing to relay/mine */ diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 5d98dc7a9385..48f38f0fd144 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -282,11 +282,6 @@ bool ClientModel::isReleaseVersion() const return CLIENT_VERSION_IS_RELEASE; } -QString ClientModel::clientName() const -{ - return QString::fromStdString(CLIENT_NAME); -} - QString ClientModel::formatClientStartupTime() const { return QDateTime::fromTime_t(nClientStartupTime).toString(); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 457bdc8c3726..c29bace26d26 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -82,7 +82,6 @@ class ClientModel : public QObject QString formatFullVersion() const; QString formatSubVersion() const; bool isReleaseVersion() const; - QString clientName() const; QString formatClientStartupTime() const; QString dataDir() const; diff --git a/src/qt/dash.cpp b/src/qt/dash.cpp index df351750de39..bd37cf4468d8 100644 --- a/src/qt/dash.cpp +++ b/src/qt/dash.cpp @@ -577,6 +577,9 @@ int main(int argc, char *argv[]) // Generate high-dpi pixmaps QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #endif +#if QT_VERSION >= 0x050600 + QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif #ifdef Q_OS_MAC QApplication::setAttribute(Qt::AA_DontShowIconsInMenus); #endif diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index 40a4f85cfffe..cd60a440aae5 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -41,36 +41,13 @@ - - - Client name - - - - - - - IBeamCursor - - - N/A - - - Qt::PlainText - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - Client version - + IBeamCursor @@ -86,7 +63,7 @@ - + User Agent @@ -96,7 +73,7 @@ - + IBeamCursor @@ -112,7 +89,7 @@ - + Using BerkeleyDB version @@ -122,7 +99,7 @@ - + IBeamCursor @@ -138,14 +115,14 @@ - + Datadir - + IBeamCursor @@ -164,14 +141,14 @@ - + Startup time - + IBeamCursor @@ -187,7 +164,7 @@ - + @@ -200,14 +177,14 @@ - + Name - + IBeamCursor @@ -223,14 +200,14 @@ - + Number of connections - + IBeamCursor @@ -246,21 +223,21 @@ - + Number of Masternodes - + N/A - + @@ -273,14 +250,14 @@ - + Current number of blocks - + IBeamCursor @@ -296,14 +273,14 @@ - + Last block time - + IBeamCursor @@ -319,7 +296,7 @@ - + @@ -332,14 +309,14 @@ - + Current number of transactions - + IBeamCursor @@ -355,14 +332,14 @@ - + Memory usage - + IBeamCursor @@ -378,7 +355,7 @@ - + 3 @@ -418,7 +395,7 @@ - + Qt::Vertical diff --git a/src/qt/forms/receiverequestdialog.ui b/src/qt/forms/receiverequestdialog.ui index 1e484dd9a0f5..4163f4189c5e 100644 --- a/src/qt/forms/receiverequestdialog.ui +++ b/src/qt/forms/receiverequestdialog.ui @@ -22,7 +22,7 @@ 300 - 300 + 320 diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h index b20de4c58f25..d1d6ae3c4221 100644 --- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -44,7 +44,7 @@ static const int TOOLTIP_WRAP_THRESHOLD = 80; static const int MAX_URI_LENGTH = 255; /* QRCodeDialog -- size of exported QR Code image */ -#define EXPORT_IMAGE_SIZE 256 +#define QR_IMAGE_SIZE 300 /* Number of frames in spinner animation */ #define SPINNER_FRAMES 36 diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index de8b20f00370..5ceb1505f0d9 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -109,6 +109,23 @@ QFont fixedPitchFont() #endif } +// Just some dummy data to generate an convincing random-looking (but consistent) address +static const uint8_t dummydata[] = {0xeb,0x15,0x23,0x1d,0xfc,0xeb,0x60,0x92,0x58,0x86,0xb6,0x7d,0x06,0x52,0x99,0x92,0x59,0x15,0xae,0xb1,0x72,0xc0,0x66,0x47}; + +// Generate a dummy address with invalid CRC, starting with the network prefix. +static std::string DummyAddress(const CChainParams ¶ms) +{ + std::vector sourcedata = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS); + sourcedata.insert(sourcedata.end(), dummydata, dummydata + sizeof(dummydata)); + for(int i=0; i<256; ++i) { // Try every trailing byte + std::string s = EncodeBase58(begin_ptr(sourcedata), end_ptr(sourcedata)); + if (!CBitcoinAddress(s).IsValid()) + return s; + sourcedata[sourcedata.size()-1] += 1; + } + return ""; +} + void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent) { parent->setFocusProxy(widget); @@ -117,7 +134,8 @@ void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent) #if QT_VERSION >= 0x040700 // We don't want translators to use own addresses in translations // and this is the only place, where this address is supplied. - widget->setPlaceholderText(QObject::tr("Enter a Dash address (e.g. %1)").arg("XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg")); + widget->setPlaceholderText(QObject::tr("Enter a Dash address (e.g. %1)").arg( + QString::fromStdString(DummyAddress(Params())))); #endif widget->setValidator(new BitcoinAddressEntryValidator(parent)); widget->setCheckValidator(new BitcoinAddressCheckValidator(parent)); diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index 5163cbaf1156..be4ae56c4025 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -45,7 +45,7 @@ QImage QRImageWidget::exportImage() { if(!pixmap()) return QImage(); - return pixmap()->toImage().scaled(EXPORT_IMAGE_SIZE, EXPORT_IMAGE_SIZE); + return pixmap()->toImage(); } void QRImageWidget::mousePressEvent(QMouseEvent *event) @@ -167,20 +167,32 @@ void ReceiveRequestDialog::update() ui->lblQRCode->setText(tr("Error encoding URI into QR Code.")); return; } - QImage myImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32); - myImage.fill(0xffffff); + QImage qrImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32); + qrImage.fill(0xffffff); unsigned char *p = code->data; for (int y = 0; y < code->width; y++) { for (int x = 0; x < code->width; x++) { - myImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff)); + qrImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff)); p++; } } QRcode_free(code); - ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(300, 300)); + QImage qrAddrImage = QImage(QR_IMAGE_SIZE, QR_IMAGE_SIZE+20, QImage::Format_RGB32); + qrAddrImage.fill(0xffffff); + QPainter painter(&qrAddrImage); + painter.drawImage(0, 0, qrImage.scaled(QR_IMAGE_SIZE, QR_IMAGE_SIZE)); + QFont font = GUIUtil::fixedPitchFont(); + font.setPixelSize(12); + painter.setFont(font); + QRect paddedRect = qrAddrImage.rect(); + paddedRect.setHeight(QR_IMAGE_SIZE+12); + painter.drawText(paddedRect, Qt::AlignBottom|Qt::AlignCenter, info.address); + painter.end(); + + ui->lblQRCode->setPixmap(QPixmap::fromImage(qrAddrImage)); ui->btnSaveAs->setEnabled(true); } } diff --git a/src/qt/receiverequestdialog.h b/src/qt/receiverequestdialog.h index 4cab4caff1ac..676745a858f6 100644 --- a/src/qt/receiverequestdialog.h +++ b/src/qt/receiverequestdialog.h @@ -10,6 +10,7 @@ #include #include #include +#include class OptionsModel; diff --git a/src/qt/res/dash-qt-res.rc b/src/qt/res/dash-qt-res.rc index 5922a9bd55e5..70220d93ef55 100644 --- a/src/qt/res/dash-qt-res.rc +++ b/src/qt/res/dash-qt-res.rc @@ -1,4 +1,5 @@ IDI_ICON1 ICON DISCARDABLE "icons/bitcoin.ico" +IDI_ICON2 ICON DISCARDABLE "icons/bitcoin_testnet.ico" #include // needed for VERSIONINFO #include "../../clientversion.h" // holds the needed client version information diff --git a/src/qt/res/icons/drkblue/bitcoin_testnet.ico b/src/qt/res/icons/bitcoin_testnet.ico similarity index 100% rename from src/qt/res/icons/drkblue/bitcoin_testnet.ico rename to src/qt/res/icons/bitcoin_testnet.ico diff --git a/src/qt/res/icons/drkblue/bitcoin_testnet.png b/src/qt/res/icons/bitcoin_testnet.png similarity index 100% rename from src/qt/res/icons/drkblue/bitcoin_testnet.png rename to src/qt/res/icons/bitcoin_testnet.png diff --git a/src/qt/res/icons/drkblue/bitcoin.png b/src/qt/res/icons/drkblue/bitcoin.png deleted file mode 100644 index a8c0425d20c8..000000000000 Binary files a/src/qt/res/icons/drkblue/bitcoin.png and /dev/null differ diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index be86e3bd3c71..12039b4e612c 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -481,7 +481,6 @@ void RPCConsole::setClientModel(ClientModel *model) // Provide initial values ui->clientVersion->setText(model->formatFullVersion()); ui->clientUserAgent->setText(model->formatSubVersion()); - ui->clientName->setText(model->clientName()); ui->dataDir->setText(model->dataDir()); ui->startupTime->setText(model->formatClientStartupTime()); ui->networkName->setText(QString::fromStdString(Params().NetworkIDString())); diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 6e39bdb25d19..44a1b74f2676 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -404,6 +404,8 @@ void TransactionView::contextualMenu(const QPoint &point) { QModelIndex index = transactionView->indexAt(point); QModelIndexList selection = transactionView->selectionModel()->selectedRows(0); + if (selection.empty()) + return; // check if transaction can be abandoned, disable context menu action in case it doesn't uint256 hash; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index f1675b19b3e2..cf7307861281 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1000,6 +1000,15 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse return rv; } +void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const std::string &name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) +{ + // Deployments with timeout value of 0 are hidden. + // A timeout value of 0 guarantees a softfork will never be activated. + // This is used when softfork codes are merged without specifying the deployment schedule. + if (consensusParams.vDeployments[id].nTimeout > 0) + bip9_softforks.push_back(Pair(name, BIP9SoftForkDesc(consensusParams, id))); +} + UniValue getblockchaininfo(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -1033,8 +1042,8 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) " ],\n" " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n" " \"xxxx\" : { (string) name of the softfork\n" - " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"lockedin\", \"active\", \"failed\"\n" - " \"bit\": xx, (numeric) the bit, 0-28, in the block version field used to signal this soft fork\n" + " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" + " \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n" " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" " \"timeout\": xx (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" " }\n" @@ -1065,8 +1074,8 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); - bip9_softforks.push_back(Pair("csv", BIP9SoftForkDesc(consensusParams, Consensus::DEPLOYMENT_CSV))); - bip9_softforks.push_back(Pair("dip0001", BIP9SoftForkDesc(consensusParams, Consensus::DEPLOYMENT_DIP0001))); + BIP9SoftForkDescPushBack(bip9_softforks, "csv", consensusParams, Consensus::DEPLOYMENT_CSV); + BIP9SoftForkDescPushBack(bip9_softforks, "dip0001", consensusParams, Consensus::DEPLOYMENT_DIP0001); obj.push_back(Pair("softforks", softforks)); obj.push_back(Pair("bip9_softforks", bip9_softforks)); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 14ad47d91ea3..904713f00932 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -428,8 +428,13 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) // set the sequence number if passed in the parameters object const UniValue& sequenceObj = find_value(o, "sequence"); - if (sequenceObj.isNum()) - nSequence = sequenceObj.get_int(); + if (sequenceObj.isNum()) { + int64_t seqNr64 = sequenceObj.get_int64(); + if (seqNr64 < 0 || seqNr64 > std::numeric_limits::max()) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range"); + else + nSequence = (uint32_t)seqNr64; + } CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence); diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 180ad667a7ef..fb3ff06f478a 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -182,7 +182,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) tx.vout.resize(1); tx.vout[0].nValue = 1*CENT; tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID()); - tx.vin.resize(500); + tx.vin.resize(2777); for (unsigned int j = 0; j < tx.vin.size(); j++) { tx.vin[j].prevout.n = j; diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 7da7a11ea793..5740e79d1143 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -72,6 +72,116 @@ bool TestSequenceLocks(const CTransaction &tx, int flags) return CheckSequenceLocks(tx, flags); } +// Test suite for ancestor feerate transaction selection. +// Implemented as an additional function, rather than a separate test case, +// to allow reusing the blockchain created in CreateNewBlock_validity. +// Note that this test assumes blockprioritysize is 0. +void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, std::vector& txFirst) +{ + // Disable free transactions, otherwise TX selection is non-deterministic + SoftSetArg("-blockprioritysize", "0"); + + // Test the ancestor feerate transaction selection. + TestMemPoolEntryHelper entry; + + // Test that a medium fee transaction will be selected after a higher fee + // rate package with a low fee rate parent. + CMutableTransaction tx; + tx.vin.resize(1); + tx.vin[0].scriptSig = CScript() << OP_1; + tx.vin[0].prevout.hash = txFirst[0]->GetHash(); + tx.vin[0].prevout.n = 0; + tx.vout.resize(1); + tx.vout[0].nValue = 5000000000LL - 1000; + // This tx has a low fee: 1000 satoshis + uint256 hashParentTx = tx.GetHash(); // save this txid for later use + mempool.addUnchecked(hashParentTx, entry.Fee(1000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + + // This tx has a medium fee: 10000 satoshis + tx.vin[0].prevout.hash = txFirst[1]->GetHash(); + tx.vout[0].nValue = 5000000000LL - 10000; + uint256 hashMediumFeeTx = tx.GetHash(); + mempool.addUnchecked(hashMediumFeeTx, entry.Fee(10000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + + // This tx has a high fee, but depends on the first transaction + tx.vin[0].prevout.hash = hashParentTx; + tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 50k satoshi fee + uint256 hashHighFeeTx = tx.GetHash(); + mempool.addUnchecked(hashHighFeeTx, entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); + + CBlockTemplate *pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); + BOOST_CHECK(pblocktemplate->block.vtx[1].GetHash() == hashParentTx); + BOOST_CHECK(pblocktemplate->block.vtx[2].GetHash() == hashHighFeeTx); + BOOST_CHECK(pblocktemplate->block.vtx[3].GetHash() == hashMediumFeeTx); + + // Test that a package below the min relay fee doesn't get included + tx.vin[0].prevout.hash = hashHighFeeTx; + tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee + uint256 hashFreeTx = tx.GetHash(); + mempool.addUnchecked(hashFreeTx, entry.Fee(0).FromTx(tx)); + size_t freeTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION); + + // Calculate a fee on child transaction that will put the package just + // below the min relay fee (assuming 1 child tx of the same size). + CAmount feeToUse = minRelayTxFee.GetFee(2*freeTxSize) - 1; + + tx.vin[0].prevout.hash = hashFreeTx; + tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse; + uint256 hashLowFeeTx = tx.GetHash(); + mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse).FromTx(tx)); + pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); + // Verify that the free tx and the low fee tx didn't get selected + for (size_t i=0; iblock.vtx.size(); ++i) { + BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashFreeTx); + BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashLowFeeTx); + } + + // Test that packages above the min relay fee do get included, even if one + // of the transactions is below the min relay fee + // Remove the low fee transaction and replace with a higher fee transaction + std::list dummy; + mempool.removeRecursive(tx, dummy); + tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee + hashLowFeeTx = tx.GetHash(); + mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse+2).FromTx(tx)); + pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); + BOOST_CHECK(pblocktemplate->block.vtx[4].GetHash() == hashFreeTx); + BOOST_CHECK(pblocktemplate->block.vtx[5].GetHash() == hashLowFeeTx); + + // Test that transaction selection properly updates ancestor fee + // calculations as ancestor transactions get included in a block. + // Add a 0-fee transaction that has 2 outputs. + tx.vin[0].prevout.hash = txFirst[2]->GetHash(); + tx.vout.resize(2); + tx.vout[0].nValue = 5000000000LL - 100000000; + tx.vout[1].nValue = 100000000; // 1BTC output + uint256 hashFreeTx2 = tx.GetHash(); + mempool.addUnchecked(hashFreeTx2, entry.Fee(0).SpendsCoinbase(true).FromTx(tx)); + + // This tx can't be mined by itself + tx.vin[0].prevout.hash = hashFreeTx2; + tx.vout.resize(1); + feeToUse = minRelayTxFee.GetFee(freeTxSize); + tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse; + uint256 hashLowFeeTx2 = tx.GetHash(); + mempool.addUnchecked(hashLowFeeTx2, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx)); + pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); + + // Verify that this tx isn't selected. + for (size_t i=0; iblock.vtx.size(); ++i) { + BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashFreeTx2); + BOOST_CHECK(pblocktemplate->block.vtx[i].GetHash() != hashLowFeeTx2); + } + + // This tx will be mineable, and should cause hashLowFeeTx2 to be selected + // as well. + tx.vin[0].prevout.n = 1; + tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee + mempool.addUnchecked(tx.GetHash(), entry.Fee(10000).FromTx(tx)); + pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey); + BOOST_CHECK(pblocktemplate->block.vtx[8].GetHash() == hashLowFeeTx2); +} + // NOTE: These tests rely on CreateNewBlock doing its own self-validation! BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { @@ -387,6 +497,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) SetMockTime(0); mempool.clear(); + TestPackageSelection(chainparams, scriptPubKey, txFirst); + BOOST_FOREACH(CTransaction *_tx, txFirst) delete _tx; diff --git a/src/test/test_dash.cpp b/src/test/test_dash.cpp index a4484441df2c..6cca19305ef3 100644 --- a/src/test/test_dash.cpp +++ b/src/test/test_dash.cpp @@ -59,6 +59,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha pathTemp = GetTempPath() / strprintf("test_dash_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); boost::filesystem::create_directories(pathTemp); mapArgs["-datadir"] = pathTemp.string(); + mempool.setSanityCheck(1.0); pblocktree = new CBlockTreeDB(1 << 20, true); pcoinsdbview = new CCoinsViewDB(1 << 23, true); pcoinsTip = new CCoinsViewCache(pcoinsdbview); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 36b13918be82..06623908bbcd 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1219,7 +1219,7 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector* pvNoSpends unsigned nTxnRemoved = 0; CFeeRate maxFeeRateRemoved(0); - while (DynamicMemoryUsage() > sizelimit) { + while (!mapTx.empty() && DynamicMemoryUsage() > sizelimit) { indexed_transaction_set::index::type::iterator it = mapTx.get().begin(); // We set the new mempool min fee to the feerate of the removed set, plus the diff --git a/src/univalue/configure.ac b/src/univalue/configure.ac index 0515b632bdf9..93d3ba945d14 100644 --- a/src/univalue/configure.ac +++ b/src/univalue/configure.ac @@ -1,7 +1,7 @@ m4_define([libunivalue_major_version], [1]) m4_define([libunivalue_minor_version], [1]) -m4_define([libunivalue_micro_version], [1]) -m4_define([libunivalue_interface_age], [1]) +m4_define([libunivalue_micro_version], [2]) +m4_define([libunivalue_interface_age], [2]) # If you need a modifier for the version number. # Normally empty, but can be used to make "fixup" releases. m4_define([libunivalue_extraversion], []) @@ -14,7 +14,7 @@ m4_define([libunivalue_age], [m4_eval(libunivalue_binary_age - libunivalue_inter m4_define([libunivalue_version], [libunivalue_major_version().libunivalue_minor_version().libunivalue_micro_version()libunivalue_extraversion()]) -AC_INIT([univalue], [1.0.1], +AC_INIT([univalue], [1.0.2], [http://github.com/jgarzik/univalue/]) dnl make the compilation flags quiet unless V=1 is used diff --git a/src/validation.cpp b/src/validation.cpp index 825a54c7b7ce..37295058ca2e 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -102,6 +102,10 @@ CTxMemPool mempool(::minRelayTxFee); FeeFilterRounder filterRounder(::minRelayTxFee); map mapRejectedBlocks GUARDED_BY(cs_main); +// TODO temporary hack for backporting +void LoopMapOrphanTransactionsByPrev(const CTransaction &tx, std::vector &vOrphanErase); +int EraseOrphanTx(uint256 hash); + /** * Returns true if there are nRequired or more blocks of minVersion or above * in the last Consensus::Params::nMajorityWindow blocks, starting at pstart and going backwards. @@ -2078,6 +2082,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd CCheckQueueControl control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL); + std::vector vOrphanErase; std::vector prevheights; CAmount nFees = 0; int nInputs = 0; @@ -2117,6 +2122,22 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd prevheights[j] = view.AccessCoin(tx.vin[j].prevout).nHeight; } + // Which orphan pool entries must we evict? + //for (size_t j = 0; j < tx.vin.size(); j++) { + // auto itByPrev = mapOrphanTransactionsByPrev.find(tx.vin[j].prevout); + // if (itByPrev == mapOrphanTransactionsByPrev.end()) continue; + // for (auto mi = itByPrev->second.begin(); mi != itByPrev->second.end(); ++mi) { + // const CTransaction& orphanTx = (*mi)->second.tx; + // const uint256& orphanHash = orphanTx.GetHash(); + // vOrphanErase.push_back(orphanHash); + // } + //} + // TODO This is a temporary solution while backporting Bitcoin 0.13 changes into Dash + // It is needed because the splitting of main.cpp into validation.cpp/net_processing.cpp was done out of order + // When we catch up with backporting, the above loop will be at the correct place in net_processing.cpp + // and this hack can be removed + LoopMapOrphanTransactionsByPrev(tx, vOrphanErase); + if (!SequenceLocks(tx, nLockTimeFlags, &prevheights, *pindex)) { return state.DoS(100, error("%s: contains a non-BIP68-final transaction", __func__), REJECT_INVALID, "bad-txns-nonfinal"); @@ -2302,6 +2323,15 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd GetMainSignals().UpdatedTransaction(hashPrevBestCoinBase); hashPrevBestCoinBase = block.vtx[0].GetHash(); + // Erase orphan transactions include or precluded by this block + if (vOrphanErase.size()) { + int nErased = 0; + BOOST_FOREACH(uint256 &orphanHash, vOrphanErase) { + nErased += EraseOrphanTx(orphanHash); + } + LogPrint("mempool", "Erased %d orphan tx included or conflicted by block\n", nErased); + } + int64_t nTime6 = GetTimeMicros(); nTimeCallbacks += nTime6 - nTime5; LogPrint("bench", " - Callbacks: %.2fms [%.2fs]\n", 0.001 * (nTime6 - nTime5), nTimeCallbacks * 0.000001); diff --git a/src/validation.h b/src/validation.h index 7c58651438b7..54e9d2975dd9 100644 --- a/src/validation.h +++ b/src/validation.h @@ -62,8 +62,6 @@ static const CAmount DEFAULT_TRANSACTION_MAXFEE = 0.2 * COIN; // "smallest denom static const CAmount HIGH_TX_FEE_PER_KB = 0.01 * COIN; //! -maxtxfee will warn if called with a higher fee than this amount (in duffs) static const CAmount HIGH_MAX_TX_FEE = 100 * HIGH_TX_FEE_PER_KB; -/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */ -static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100; /** Default for -limitancestorcount, max number of in-mempool ancestors */ static const unsigned int DEFAULT_ANCESTOR_LIMIT = 25; /** Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors */ @@ -145,6 +143,9 @@ static const bool DEFAULT_FEEFILTER = true; /** Maximum number of headers to announce when relaying blocks with headers message.*/ static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8; +/** Maximum number of unconnecting headers announcements before DoS score */ +static const int MAX_UNCONNECTING_HEADERS = 10; + static const bool DEFAULT_PEERBLOOMFILTERS = true; struct BlockHasher diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 7544bb18821b..7401d8745491 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -168,6 +168,11 @@ void ImportScript(const CScript& script, const string& strLabel, bool isRedeemSc if (!pwalletMain->HaveCScript(script) && !pwalletMain->AddCScript(script)) throw JSONRPCError(RPC_WALLET_ERROR, "Error adding p2sh redeemScript to wallet"); ImportAddress(CBitcoinAddress(CScriptID(script)), strLabel); + } else { + CTxDestination destination; + if (ExtractDestination(script, destination)) { + pwalletMain->SetAddressBook(destination, strLabel, "receive"); + } } } @@ -196,6 +201,8 @@ UniValue importaddress(const UniValue& params, bool fHelp) "4. p2sh (boolean, optional, default=false) Add the P2SH version of the script as well\n" "\nNote: This call can take minutes to complete if rescan is true.\n" "If you have the full public key, you should call importpubkey instead of this.\n" + "\nNote: If you import a non-standard raw script in hex form, outputs sending to it will be treated\n" + "as change, and not show up in many RPCs.\n" "\nExamples:\n" "\nImport a script with rescan\n" + HelpExampleCli("importaddress", "\"myscript\"") + diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 387b22358934..c6c5058984c0 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -27,7 +27,7 @@ typedef set > CoinSet; BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup) -static CWallet wallet; +static const CWallet wallet; static vector vCoins; static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0) @@ -188,11 +188,11 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // empty the wallet and start again, now with fractions of a cent, to test small change avoidance empty_wallet(); - add_coin(0.1*MIN_CHANGE); - add_coin(0.2*MIN_CHANGE); - add_coin(0.3*MIN_CHANGE); - add_coin(0.4*MIN_CHANGE); - add_coin(0.5*MIN_CHANGE); + add_coin(MIN_CHANGE * 1 / 10); + add_coin(MIN_CHANGE * 2 / 10); + add_coin(MIN_CHANGE * 3 / 10); + add_coin(MIN_CHANGE * 4 / 10); + add_coin(MIN_CHANGE * 5 / 10); // try making 1 * MIN_CHANGE from the 1.5 * MIN_CHANGE // we'll get change smaller than MIN_CHANGE whatever happens, so can expect MIN_CHANGE exactly @@ -207,8 +207,8 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) BOOST_CHECK_EQUAL(nValueRet, 1 * MIN_CHANGE); // we should get the exact amount // if we add more small coins: - add_coin(0.6*MIN_CHANGE); - add_coin(0.7*MIN_CHANGE); + add_coin(MIN_CHANGE * 6 / 10); + add_coin(MIN_CHANGE * 7 / 10); // and try again to make 1.0 * MIN_CHANGE BOOST_CHECK( wallet.SelectCoinsMinConf(1 * MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet)); @@ -229,9 +229,9 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // sometimes it will fail, and so we use the next biggest coin: empty_wallet(); - add_coin(0.5 * MIN_CHANGE); - add_coin(0.6 * MIN_CHANGE); - add_coin(0.7 * MIN_CHANGE); + add_coin(MIN_CHANGE * 5 / 10); + add_coin(MIN_CHANGE * 6 / 10); + add_coin(MIN_CHANGE * 7 / 10); add_coin(1111 * MIN_CHANGE); BOOST_CHECK( wallet.SelectCoinsMinConf(1 * MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 1111 * MIN_CHANGE); // we get the bigger coin @@ -239,9 +239,9 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // but sometimes it's possible, and we use an exact subset (0.4 + 0.6 = 1.0) empty_wallet(); - add_coin(0.4 * MIN_CHANGE); - add_coin(0.6 * MIN_CHANGE); - add_coin(0.8 * MIN_CHANGE); + add_coin(MIN_CHANGE * 4 / 10); + add_coin(MIN_CHANGE * 6 / 10); + add_coin(MIN_CHANGE * 8 / 10); add_coin(1111 * MIN_CHANGE); BOOST_CHECK( wallet.SelectCoinsMinConf(MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, MIN_CHANGE); // we should get the exact amount @@ -249,17 +249,17 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // test avoiding small change empty_wallet(); - add_coin(0.05 * MIN_CHANGE); - add_coin(1 * MIN_CHANGE); - add_coin(100 * MIN_CHANGE); + add_coin(MIN_CHANGE * 5 / 100); + add_coin(MIN_CHANGE * 1); + add_coin(MIN_CHANGE * 100); // trying to make 100.01 from these three coins - BOOST_CHECK( wallet.SelectCoinsMinConf(100.01 * MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet)); - BOOST_CHECK_EQUAL(nValueRet, 101.05 * MIN_CHANGE); // we should get all coins + BOOST_CHECK(wallet.SelectCoinsMinConf(MIN_CHANGE * 10001 / 100, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK_EQUAL(nValueRet, MIN_CHANGE * 10105 / 100); // we should get all coins BOOST_CHECK_EQUAL(setCoinsRet.size(), 3U); // but if we try to make 99.9, we should take the bigger of the two small coins to avoid small change - BOOST_CHECK( wallet.SelectCoinsMinConf(99.9 * MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet)); + BOOST_CHECK(wallet.SelectCoinsMinConf(MIN_CHANGE * 9990 / 100, 1, 1, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 101 * MIN_CHANGE); BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U); @@ -310,7 +310,11 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // add 75 cents in small change. not enough to make 90 cents, // then try making 90 cents. there are multiple competing "smallest bigger" coins, // one of which should be picked at random - add_coin( 5*CENT); add_coin(10*CENT); add_coin(15*CENT); add_coin(20*CENT); add_coin(25*CENT); + add_coin(5 * CENT); + add_coin(10 * CENT); + add_coin(15 * CENT); + add_coin(20 * CENT); + add_coin(25 * CENT); fails = 0; for (int i = 0; i < RANDOM_REPEATS; i++) @@ -345,20 +349,6 @@ BOOST_AUTO_TEST_CASE(ApproximateBestSubset) BOOST_CHECK(wallet.SelectCoinsMinConf(1003 * COIN, 1, 6, vCoins, setCoinsRet, nValueRet)); BOOST_CHECK_EQUAL(nValueRet, 1003 * COIN); BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U); - - empty_wallet(); - - // Test trimming - for (int i = 0; i < 100; i++) - add_coin(10 * COIN); - for (int i = 0; i < 100; i++) - add_coin(1000 * COIN); - - BOOST_CHECK(wallet.SelectCoinsMinConf(100001 * COIN, 1, 6, vCoins, setCoinsRet, nValueRet)); - // We need all 100 larger coins and exactly one small coin. - // Superfluous small coins must be trimmed from the set: - BOOST_CHECK_EQUAL(nValueRet, 100010 * COIN); - BOOST_CHECK_EQUAL(setCoinsRet.size(), 101); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 078c0323b996..c25587244516 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2537,16 +2537,6 @@ static void ApproximateBestSubset(vector= nTargetValue ) - { - vfBest[i] = false; - nBest -= vValue[i].first; - } - } } // move denoms down @@ -4526,9 +4516,9 @@ std::string CWallet::GetWalletHelpString(bool showDebug) strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), DEFAULT_SEND_FREE_TRANSACTIONS)); strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE)); strUsage += HelpMessageOpt("-txconfirmtarget=", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET)); - strUsage += HelpMessageOpt("-usehd", _("Use hierarchical deterministic key generation (HD) after bip39/bip44. Only has effect during wallet creation/first start") + " " + strprintf(_("(default: %u)"), DEFAULT_USE_HD_WALLET)); + strUsage += HelpMessageOpt("-usehd", _("Use hierarchical deterministic key generation (HD) after BIP39/BIP44. Only has effect during wallet creation/first start") + " " + strprintf(_("(default: %u)"), DEFAULT_USE_HD_WALLET)); strUsage += HelpMessageOpt("-mnemonic", _("User defined mnemonic for HD wallet (bip39). Only has effect during wallet creation/first start (default: randomly generated)")); - strUsage += HelpMessageOpt("-mnemonicpassphrase", _("User defined mnemonic passphrase for HD wallet (bip39). Only has effect during wallet creation/first start (default: empty string)")); + strUsage += HelpMessageOpt("-mnemonicpassphrase", _("User defined mnemonic passphrase for HD wallet (BIP39). Only has effect during wallet creation/first start (default: empty string)")); strUsage += HelpMessageOpt("-hdseed", _("User defined seed for HD wallet (should be in hex). Only has effect during wallet creation/first start (default: randomly generated)")); strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup")); strUsage += HelpMessageOpt("-wallet=", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT));