diff --git a/.gitignore b/.gitignore
index fbe1f8f..2d8f6ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,7 +68,6 @@ libconftest.dylib*
*.pyc
*.o
*.o-*
-*.patch
.xdna
*.a
*.pb.cc
diff --git a/COPYING b/COPYING
index 07ac687..308d671 100644
--- a/COPYING
+++ b/COPYING
@@ -1,7 +1,7 @@
Copyright (c) 2009-2015 Bitcoin Developers
Copyright (c) 2014-2015 Dash Developers
Copyright (c) 2015-2017 PIVX Developers
-Copyright (c) 2017-2018 The XDNA Core developers
+Copyright (c) 2017-2019 The XDNA Core developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/Makefile.am b/Makefile.am
index 57a80f8..7b0be09 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -160,6 +160,7 @@ $(BITCOIN_CLI_BIN): FORCE
$(MAKE) -C src $(@F)
if USE_LCOV
+LCOV_FILTER_PATTERN=-p "/usr/include/" -p "/usr/lib/" -p "src/leveldb/" -p "src/univalue" -p "src/secp256k1"
baseline.info:
$(LCOV) -c -i -d $(abs_builddir)/src -o $@
diff --git a/README.md b/README.md
index 9776b11..6f39f23 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ More information at [xdna.io](https://xdna.io) Visit our ANN thread at [BitcoinT
Name & ticker | XDNA |
Consensus algorithm | PoW/POS |
POW phase duration | 1440000 blocks |
-PoW block reward | Dynamic from 4 to 109 coins with lowering by 6.94% each month |
+PoW block reward | Dynamic from 4 to 511 XDNA |
Instamine protection | First 720 blocks |
Hashing algorithm | HEX |
Estimated XDNA supply during POW | 138,000,000 |
@@ -34,20 +34,20 @@ More information at [xdna.io](https://xdna.io) Visit our ANN thread at [BitcoinT
Level | Network hashrate (Gh/s) | Block reward |
-1 | 10 | 3.6 |
-2 | 20 | 4.4 |
-3 | 30 | 6.2 |
-4 | 50 | 8.8 |
-5 | 80 | 12.2 |
-6 | 130 | 16.5 |
-7 | 210 | 21.7 |
-8 | 340 | 27.8 |
-9 | 550 | 34.8 |
-10 | 890 | 42.5 |
-11 | 1.440 | 51.2 |
-12 | 2.330 | 60.7 |
-13 | 3.770 | 71.1 |
-14 | 6.100 | 82.4 |
-15 | 9.870 | 94.5 |
+1 | 10 | 4 |
+2 | 20 | 5 |
+3 | 30 | 7 |
+4 | 50 | 10 |
+5 | 80 | 14 |
+6 | 130 | 19 |
+7 | 210 | 25 |
+8 | 340 | 32 |
+9 | 550 | 40 |
+10 | 890 | 49 |
+11 | 1.440 | 59 |
+12 | 2.330 | 70 |
+13 | 3.770 | 82 |
+14 | 6.100 | 95 |
+15 | 9.870 | 109 |
-![](https://github.com/XDNA-Core/XDNA/blob/master/doc/POW.png)
+![](doc/POW.png)
diff --git a/configure.ac b/configure.ac
index 714aaab..e9e90cb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,9 +1,9 @@
dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
AC_PREREQ([2.60])
-define(_CLIENT_VERSION_MAJOR, 1)
-define(_CLIENT_VERSION_MINOR, 3)
+define(_CLIENT_VERSION_MAJOR, 2)
+define(_CLIENT_VERSION_MINOR, 0)
define(_CLIENT_VERSION_REVISION, 0)
-define(_CLIENT_VERSION_BUILD, 1)
+define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_IS_RELEASE, true)
define(_COPYRIGHT_YEAR, 2019)
AC_INIT([XDNA Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[www.xdna.io],[xdna])
@@ -17,6 +17,12 @@ BITCOIN_GUI_NAME=xdna-qt
BITCOIN_CLI_NAME=xdna-cli
BITCOIN_TX_NAME=xdna-tx
+dnl Unless the user specified ARFLAGS, force it to be cr
+AC_ARG_VAR(ARFLAGS, [Flags for the archiver, defaults to if not set])
+if test "x${ARFLAGS+set}" != "xset"; then
+ ARFLAGS="cr"
+fi
+
AC_CANONICAL_HOST
AH_TOP([#ifndef XDNA_CONFIG_H])
@@ -54,7 +60,9 @@ case $host in
;;
esac
dnl Require C++11 compiler (no GNU extensions)
-AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory])
+AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory], [nodefault])
+dnl Check if -latomic is required for
+CHECK_ATOMIC
dnl Unless the user specified OBJCXX, force it to be the same as CXX. This ensures
dnl that we get the same -std flags for both.
@@ -84,16 +92,14 @@ AC_PATH_PROG(HEXDUMP,hexdump)
AC_PATH_TOOL(READELF, readelf)
AC_PATH_TOOL(CPPFILT, c++filt)
AC_PATH_TOOL(OBJCOPY, objcopy)
+AC_PATH_PROG(DOXYGEN, doxygen)
+if test -z "$DOXYGEN"; then
+ AC_MSG_WARN([Doxygen not found])
+fi
+AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$DOXYGEN"])
AC_ARG_VAR(PYTHONPATH, Augments the default search path for python module files)
-# This m4 will only be used if a system copy cannot be found. This is helpful
-# on systems where autotools are installed but the pkg-config macros are not in
-# a default location. It is currently used for building on OSX where autotools
-# are preinstalled but pkg-config comes from macports or homebrew. It should
-# probably be removed when building on <= 10.6 is no longer supported.
-m4_include([pkg.m4])
-
# Enable wallet
AC_ARG_ENABLE([wallet],
[AS_HELP_STRING([--enable-wallet],
@@ -118,10 +124,15 @@ AC_ARG_ENABLE(tests,
[use_tests=$enableval],
[use_tests=no])
-AC_ARG_WITH([comparison-tool],
- AS_HELP_STRING([--with-comparison-tool],[path to java comparison tool (requires --enable-tests)]),
- [use_comparison_tool=$withval],
- [use_comparison_tool=no])
+AC_ARG_ENABLE(gui-tests,
+ AS_HELP_STRING([--disable-gui-tests],[do not compile GUI tests (default is to compile if GUI and tests enabled)]),
+ [use_gui_tests=$enableval],
+ [use_gui_tests=$use_tests])
+
+AC_ARG_ENABLE(bench,
+ AS_HELP_STRING([--disable-bench],[do not compile benchmarks (default is to compile)]),
+ [use_bench=$enableval],
+ [use_bench=no])
AC_ARG_ENABLE([comparison-tool-reorg-tests],
AS_HELP_STRING([--enable-comparison-tool-reorg-tests],[enable expensive reorg tests in the comparison tool (default no)]),
@@ -158,11 +169,12 @@ AC_ARG_ENABLE([lcov],
[use_lcov=yes],
[use_lcov=no])
-AC_ARG_ENABLE([glibc-back-compat],
- [AS_HELP_STRING([--enable-glibc-back-compat],
- [enable backwards compatibility with glibc and libstdc++])],
- [use_glibc_compat=$enableval],
- [use_glibc_compat=no])
+AC_ARG_ENABLE([lcov-branch-coverage],
+ [AS_HELP_STRING([--enable-lcov-branch-coverage],
+ [enable lcov testing branch coverage (default is no)])],
+ [use_lcov_branch=yes],
+ [use_lcov_branch=no])
+
AC_ARG_ENABLE([zmq],
[AS_HELP_STRING([--disable-zmq],
@@ -672,7 +684,43 @@ fi
if test x$use_boost = xyes; then
-BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_PROGRAM_OPTIONS_LIB $BOOST_THREAD_LIB"
+BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_PROGRAM_OPTIONS_LIB $BOOST_THREAD_LIB $BOOST_CHRONO_LIB"
+
+
+dnl If boost (prior to 1.57) was built without c++11, it emulated scoped enums
+dnl using c++98 constructs. Unfortunately, this implementation detail leaked into
+dnl the abi. This was fixed in 1.57.
+
+dnl When building against that installed version using c++11, the headers pick up
+dnl on the native c++11 scoped enum support and enable it, however it will fail to
+dnl link. This can be worked around by disabling c++11 scoped enums if linking will
+dnl fail.
+dnl BOOST_NO_SCOPED_ENUMS was changed to BOOST_NO_CXX11_SCOPED_ENUMS in 1.51.
+
+TEMP_LIBS="$LIBS"
+LIBS="$BOOST_LIBS $LIBS"
+TEMP_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+AC_MSG_CHECKING([for mismatched boost c++11 scoped enums])
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+ #include
+ #include
+ #if !defined(BOOST_NO_SCOPED_ENUMS) && !defined(BOOST_NO_CXX11_SCOPED_ENUMS) && BOOST_VERSION < 105700
+ #define BOOST_NO_SCOPED_ENUMS
+ #define BOOST_NO_CXX11_SCOPED_ENUMS
+ #define CHECK
+ #endif
+ #include
+ ]],[[
+ #if defined(CHECK)
+ boost::filesystem::copy_file("foo", "bar");
+ #else
+ choke;
+ #endif
+ ]])],
+ [AC_MSG_RESULT(mismatched); BOOST_CPPFLAGS="$BOOST_CPPFLAGS -DBOOST_NO_SCOPED_ENUMS -DBOOST_NO_CXX11_SCOPED_ENUMS"], [AC_MSG_RESULT(ok)])
+LIBS="$TEMP_LIBS"
+CPPFLAGS="$TEMP_CPPFLAGS"
dnl Boost >= 1.50 uses sleep_for rather than the now-deprecated sleep, however
dnl it was broken from 1.50 to 1.52 when backed by nanosleep. Use sleep_for if
@@ -814,6 +862,12 @@ AC_CHECK_LIB([crypto],[RAND_egd],[],[
dnl univalue check
+need_bundled_univalue=yes
+
+if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnonononono; then
+ need_bundled_univalue=no
+else
+
if test x$system_univalue != xno ; then
found_univalue=no
if test x$use_pkgconfig = xyes; then
@@ -821,7 +875,7 @@ if test x$system_univalue != xno ; then
m4_ifdef(
[PKG_CHECK_MODULES],
[
- PKG_CHECK_MODULES([UNIVALUE],[libunivalue],[found_univalue=yes],[true])
+ PKG_CHECK_MODULES([UNIVALUE],[libunivalue >= 1.0.4],[found_univalue=yes],[true])
]
)
else
@@ -835,6 +889,7 @@ if test x$system_univalue != xno ; then
if test x$found_univalue = xyes ; then
system_univalue=yes
+ need_bundled_univalue=no
elif test x$system_univalue = xyes ; then
AC_MSG_ERROR([univalue not found])
else
@@ -842,11 +897,14 @@ if test x$system_univalue != xno ; then
fi
fi
-if test x$system_univalue = xno ; then
+if test x$need_bundled_univalue = xyes ; then
UNIVALUE_CFLAGS='-I$(srcdir)/univalue/include'
UNIVALUE_LIBS='univalue/libunivalue.la'
fi
-AM_CONDITIONAL([EMBEDDED_UNIVALUE],[test x$system_univalue = xno])
+
+fi
+
+AM_CONDITIONAL([EMBEDDED_UNIVALUE],[test x$need_bundled_univalue = xyes])
AC_SUBST(UNIVALUE_CFLAGS)
AC_SUBST(UNIVALUE_LIBS)
@@ -1073,7 +1131,7 @@ PKGCONFIG_LIBDIR_TEMP="$PKG_CONFIG_LIBDIR"
unset PKG_CONFIG_LIBDIR
PKG_CONFIG_LIBDIR="$PKGCONFIG_LIBDIR_TEMP"
-if test x$system_univalue = xno; then
+if test x$need_bundled_univalue = xyes; then
AC_CONFIG_SUBDIRS([src/univalue])
fi
diff --git a/depends/Makefile b/depends/Makefile
index dedb067..0ddd348 100644
--- a/depends/Makefile
+++ b/depends/Makefile
@@ -134,6 +134,7 @@ $(host_prefix)/share/config.site : config.site.in $(host_prefix)/.stamp_$(final_
-e 's|@CXXFLAGS@|$(strip $(host_CXXFLAGS) $(host_$(release_type)_CXXFLAGS))|' \
-e 's|@CPPFLAGS@|$(strip $(host_CPPFLAGS) $(host_$(release_type)_CPPFLAGS))|' \
-e 's|@LDFLAGS@|$(strip $(host_LDFLAGS) $(host_$(release_type)_LDFLAGS))|' \
+ -e 's|@allow_host_packages@|$(ALLOW_HOST_PACKAGES)|' \
-e 's|@no_qt@|$(NO_QT)|' \
-e 's|@no_wallet@|$(NO_WALLET)|' \
-e 's|@no_upnp@|$(NO_UPNP)|' \
diff --git a/depends/README.md b/depends/README.md
index 6053c53..99eef19 100644
--- a/depends/README.md
+++ b/depends/README.md
@@ -28,6 +28,22 @@ Common `host-platform-triplets` for cross compilation are:
No other options are needed, the paths are automatically configured.
+Install the required dependencies: Ubuntu & Debian
+--------------------------------------------------
+
+For macOS cross compilation:
+
+ sudo apt-get install curl librsvg2-bin libtiff-tools bsdmainutils cmake imagemagick libcap-dev libz-dev libbz2-dev python-setuptools
+
+For Win32/Win64 cross compilation:
+
+- see [build-windows.md](../doc/build-windows.md#cross-compilation-for-ubuntu-and-windows-subsystem-for-linux)
+
+For linux (including i386, ARM) cross compilation:
+
+ sudo apt-get install curl g++-aarch64-linux-gnu g++-4.8-aarch64-linux-gnu gcc-4.8-aarch64-linux-gnu binutils-aarch64-linux-gnu g++-arm-linux-gnueabihf g++-4.8-arm-linux-gnueabihf gcc-4.8-arm-linux-gnueabihf binutils-arm-linux-gnueabihf g++-4.8-multilib gcc-4.8-multilib binutils-gold bsdmainutils
+
+
Dependency Options:
The following can be set when running make: make FOO=bar
diff --git a/depends/config.guess b/depends/config.guess
index bbd48b6..f5710e4 100755
--- a/depends/config.guess
+++ b/depends/config.guess
@@ -837,10 +837,11 @@ EOF
UNAME_PROCESSOR=`/usr/bin/uname -p`
case ${UNAME_PROCESSOR} in
amd64)
- echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- *)
- echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ UNAME_PROCESSOR=x86_64 ;;
+ i386)
+ UNAME_PROCESSOR=i586 ;;
esac
+ echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit ;;
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
@@ -1038,6 +1039,9 @@ EOF
riscv32:Linux:*:* | riscv64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
+ riscv32:Linux:*:* | riscv64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
exit ;;
@@ -1343,6 +1347,9 @@ EOF
NSR-?:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
exit ;;
+ NSX-?:NONSTOP_KERNEL:*:*)
+ echo nsx-tandem-nsk${UNAME_RELEASE}
+ exit ;;
*:NonStop-UX:*:*)
echo mips-compaq-nonstopux
exit ;;
diff --git a/depends/config.site.in b/depends/config.site.in
index 3d7c9fd..0a4a9c3 100644
--- a/depends/config.site.in
+++ b/depends/config.site.in
@@ -13,10 +13,10 @@ fi
if test -z $with_qt_translationdir; then
with_qt_translationdir=$depends_prefix/translations
fi
-if test -z $with_qt_bindir; then
+if test -z $with_qt_bindir && test -z "@no_qt@"; then
with_qt_bindir=$depends_prefix/native/bin
fi
-if test -z $with_protoc_bindir; then
+if test -z $with_protoc_bindir && test -z "@no_qt@"; then
with_protoc_bindir=$depends_prefix/native/bin
fi
@@ -53,9 +53,10 @@ PKG_CONFIG="`which pkg-config` --static"
# These two need to remain exported because pkg-config does not see them
# otherwise. That means they must be unexported at the end of configure.ac to
# avoid ruining the cache. Sigh.
-
-export PKG_CONFIG_LIBDIR=$depends_prefix/lib/pkgconfig
-export PKG_CONFIG_PATH=$depends_prefix/share/pkgconfig
+export PKG_CONFIG_PATH=$depends_prefix/share/pkgconfig:$depends_prefix/lib/pkgconfig
+if test -z "@allow_host_packages@"; then
+ export PKGCONFIG_LIBDIR=
+fi
CPPFLAGS="-I$depends_prefix/include/ $CPPFLAGS"
LDFLAGS="-L$depends_prefix/lib $LDFLAGS"
diff --git a/depends/config.sub b/depends/config.sub
index 7e792b4..38faf30 100755
--- a/depends/config.sub
+++ b/depends/config.sub
@@ -263,7 +263,7 @@ case $basic_machine in
| fido | fr30 | frv | ft32 \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
- | i370 | i860 | i960 | ia64 \
+ | i370 | i860 | i960 | ia16 | ia64 \
| ip2k | iq2000 \
| k1om \
| le32 | le64 \
@@ -315,6 +315,7 @@ case $basic_machine in
| ubicom32 \
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| visium \
+ | wasm32 \
| we32k \
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
@@ -388,7 +389,7 @@ case $basic_machine in
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| hexagon-* \
- | i*86-* | i860-* | i960-* | ia64-* \
+ | i*86-* | i860-* | i960-* | ia16-* | ia64-* \
| ip2k-* | iq2000-* \
| k1om-* \
| le32-* | le64-* \
@@ -446,6 +447,7 @@ case $basic_machine in
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
| vax-* \
| visium-* \
+ | wasm32-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
@@ -653,6 +655,14 @@ case $basic_machine in
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
os=$os"spe"
;;
+ e500v[12])
+ basic_machine=powerpc-unknown
+ os=$os"spe"
+ ;;
+ e500v[12]-*)
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=$os"spe"
+ ;;
ebmon29k)
basic_machine=a29k-amd
os=-ebmon
@@ -948,6 +958,9 @@ case $basic_machine in
nsr-tandem)
basic_machine=nsr-tandem
;;
+ nsx-tandem)
+ basic_machine=nsx-tandem
+ ;;
op50n-* | op60c-*)
basic_machine=hppa1.1-oki
os=-proelf
@@ -1243,6 +1256,9 @@ case $basic_machine in
basic_machine=a29k-wrs
os=-vxworks
;;
+ wasm32)
+ basic_machine=wasm32-unknown
+ ;;
w65*)
basic_machine=w65-wdc
os=-none
@@ -1641,6 +1657,9 @@ case $basic_machine in
pru-*)
os=-elf
;;
+ pru-*)
+ os=-elf
+ ;;
*-be)
os=-beos
;;
diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk
index 57d96e4..bf773cc 100644
--- a/depends/packages/boost.mk
+++ b/depends/packages/boost.mk
@@ -1,8 +1,8 @@
package=boost
-$(package)_version=1_63_0
-$(package)_download_path=https://sourceforge.net/projects/boost/files/boost/1.63.0
+$(package)_version=1_64_0
+$(package)_download_path=https://dl.bintray.com/boostorg/release/1.64.0/source/
$(package)_file_name=$(package)_$($(package)_version).tar.bz2
-$(package)_sha256_hash=beae2529f759f6b3bf3f4969a19c2e9d6f0c503edcb2de4a61d1428519fcb3b0
+$(package)_sha256_hash=7bcc5caace97baa948931d712ea5f37038dbb1c5d89b43ad4def4ed7cb683332
define $(package)_set_vars
$(package)_config_opts_release=variant=release
diff --git a/depends/packages/dbus.mk b/depends/packages/dbus.mk
index 90ddcb9..bbe0375 100644
--- a/depends/packages/dbus.mk
+++ b/depends/packages/dbus.mk
@@ -1,8 +1,8 @@
package=dbus
-$(package)_version=1.10.14
-$(package)_download_path=http://dbus.freedesktop.org/releases/dbus
+$(package)_version=1.10.18
+$(package)_download_path=https://dbus.freedesktop.org/releases/dbus
$(package)_file_name=$(package)-$($(package)_version).tar.gz
-$(package)_sha256_hash=23238f70353e38ce5ca183ebc9525c0d97ac00ef640ad29cf794782af6e6a083
+$(package)_sha256_hash=6049ddd5f3f3e2618f615f1faeda0a115104423a7996b7aa73e2f36e38cc514a
$(package)_dependencies=expat
define $(package)_set_vars
diff --git a/depends/packages/expat.mk b/depends/packages/expat.mk
index 81a660e..7f48472 100644
--- a/depends/packages/expat.mk
+++ b/depends/packages/expat.mk
@@ -1,8 +1,8 @@
package=expat
-$(package)_version=2.2.0
+$(package)_version=2.2.1
$(package)_download_path=https://downloads.sourceforge.net/project/expat/expat/$($(package)_version)
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
-$(package)_sha256_hash=d9e50ff2d19b3538bd2127902a89987474e1a4db8e43a66a4d1a712ab9a504ff
+$(package)_sha256_hash=1868cadae4c82a018e361e2b2091de103cd820aaacb0d6cfa49bd2cd83978885
define $(package)_set_vars
$(package)_config_opts=--disable-static
diff --git a/depends/packages/gmp.mk b/depends/packages/gmp.mk
new file mode 100644
index 0000000..afc3f39
--- /dev/null
+++ b/depends/packages/gmp.mk
@@ -0,0 +1,24 @@
+package=gmp
+$(package)_version=6.1.2
+$(package)_download_path=https://gmplib.org/download/gmp
+$(package)_file_name=$(package)-$($(package)_version).tar.bz2
+$(package)_sha256_hash=5275bb04f4863a13516b2f39392ac5e272f5e1bb8057b18aec1c9b79d73d8fb2
+
+define $(package)_set_vars
+$(package)_config_opts=--disable-shared
+$(package)_config_opts_mingw32=--enable-mingw
+$(package)_config_opts_linux=--with-pic
+endef
+
+define $(package)_config_cmds
+ $($(package)_autoconf)
+endef
+
+define $(package)_build_cmds
+ $(MAKE)
+endef
+
+define $(package)_stage_cmds
+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
+endef
+
diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk
index 70f345e..5f622f8 100644
--- a/depends/packages/libevent.mk
+++ b/depends/packages/libevent.mk
@@ -1,15 +1,15 @@
package=libevent
-$(package)_version=2.1.7
+$(package)_version=2.1.8-stable
$(package)_download_path=https://github.com/libevent/libevent/archive/
-$(package)_file_name=release-$($(package)_version)-rc.tar.gz
-$(package)_sha256_hash=548362d202e22fe24d4c3fad38287b4f6d683e6c21503341373b89785fa6f991
+$(package)_file_name=release-$($(package)_version).tar.gz
+$(package)_sha256_hash=316ddb401745ac5d222d7c529ef1eada12f58f6376a66c1118eee803cb70f83d
define $(package)_preprocess_cmds
./autogen.sh
endef
define $(package)_set_vars
- $(package)_config_opts=--disable-shared --disable-openssl --disable-libevent-regress
+ $(package)_config_opts=--disable-shared --disable-openssl --disable-libevent-regress --disable-samples
$(package)_config_opts_release=--disable-debug-mode
$(package)_config_opts_linux=--with-pic
endef
diff --git a/depends/packages/native_ccache.mk b/depends/packages/native_ccache.mk
index 4ed61a4..966804c 100644
--- a/depends/packages/native_ccache.mk
+++ b/depends/packages/native_ccache.mk
@@ -1,8 +1,8 @@
package=native_ccache
-$(package)_version=3.3.3
+$(package)_version=3.3.4
$(package)_download_path=https://samba.org/ftp/ccache
$(package)_file_name=ccache-$($(package)_version).tar.bz2
-$(package)_sha256_hash=2985bc5e32ebe38d2958d508eb54ddcad39eed909489c0c2988035214597ca54
+$(package)_sha256_hash=fa9d7f38367431bc86b19ad107d709ca7ecf1574fdacca01698bdf0a47cd8567
define $(package)_set_vars
$(package)_config_opts=
diff --git a/depends/packages/native_ds_store.mk b/depends/packages/native_ds_store.mk
index 49f5829..116fa25 100644
--- a/depends/packages/native_ds_store.mk
+++ b/depends/packages/native_ds_store.mk
@@ -1,9 +1,8 @@
package=native_ds_store
-$(package)_version=1.1.0
-$(package)_download_path=https://bitbucket.org/al45tair/ds_store/get
-$(package)_download_file=v$($(package)_version).tar.bz2
-$(package)_file_name=$(package)-$($(package)_version).tar.bz2
-$(package)_sha256_hash=921596764d71d1bbd3297a90ef6d286f718794d667e4f81d91d14053525d64c1
+$(package)_version=1.1.2
+$(package)_download_path=https://github.com/al45tair/ds_store/archive/
+$(package)_file_name=v$($(package)_version).tar.gz
+$(package)_sha256_hash=3b3ecb7bf0a5157f5b6010bc3af7c141fb0ad3527084e63336220d22744bc20c
$(package)_install_libdir=$(build_prefix)/lib/python/dist-packages
$(package)_dependencies=native_biplist
diff --git a/depends/packages/native_mac_alias.mk b/depends/packages/native_mac_alias.mk
index 85a8a40..488ec8b 100644
--- a/depends/packages/native_mac_alias.mk
+++ b/depends/packages/native_mac_alias.mk
@@ -1,14 +1,13 @@
package=native_mac_alias
-$(package)_version=1.1.0
-$(package)_download_path=https://bitbucket.org/al45tair/mac_alias/get
-$(package)_download_file=v$($(package)_version).tar.bz2
-$(package)_file_name=$(package)-$($(package)_version).tar.bz2
-$(package)_sha256_hash=87ad827e66790028361e43fc754f68ed041a9bdb214cca03c853f079b04fb120
+$(package)_version=2.0.6
+$(package)_download_path=https://github.com/al45tair/mac_alias/archive/
+$(package)_file_name=v$($(package)_version).tar.gz
+$(package)_sha256_hash=78a3332d9a597eebf09ae652d38ad1e263b28db5c2e6dd725fad357b03b77371
$(package)_install_libdir=$(build_prefix)/lib/python/dist-packages
$(package)_patches=python3.patch
define $(package)_preprocess_cmds
- patch -p1 < $($(package)_patch_dir)/python3.patch
+ patch -p1 < $($(package)_patch_dir)/python3.patch
endef
define $(package)_build_cmds
diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk
index 11c2e55..c82944d 100644
--- a/depends/packages/packages.mk
+++ b/depends/packages/packages.mk
@@ -1,4 +1,4 @@
-packages:=boost openssl libevent zeromq
+packages:=boost openssl libevent zeromq gmp
native_packages := native_ccache
qt_native_packages = native_protobuf
diff --git a/depends/packages/qrencode.mk b/depends/packages/qrencode.mk
index 7b21247..44fdf1c 100644
--- a/depends/packages/qrencode.mk
+++ b/depends/packages/qrencode.mk
@@ -1,7 +1,7 @@
package=qrencode
$(package)_version=3.4.4
$(package)_download_path=https://fukuchi.org/works/qrencode/
-$(package)_file_name=qrencode-$(qrencode_version).tar.bz2
+$(package)_file_name=$(package)-$($(package)_version).tar.bz2
$(package)_sha256_hash=efe5188b1ddbcbf98763b819b146be6a90481aac30cfc8d858ab78a19cde1fa5
define $(package)_set_vars
diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk
index 858898b..cd0d6cc 100644
--- a/depends/packages/qt.mk
+++ b/depends/packages/qt.mk
@@ -1,6 +1,6 @@
PACKAGE=qt
$(package)_version=5.7.1
-$(package)_download_path=http://download.qt.io/official_releases/qt/5.7/$($(package)_version)/submodules
+$(package)_download_path=https://download.qt.io/archive/qt/5.7/$($(package)_version)/submodules
$(package)_suffix=opensource-src-$($(package)_version).tar.gz
$(package)_file_name=qtbase-$($(package)_suffix)
$(package)_sha256_hash=95f83e532d23b3ddbde7973f380ecae1bac13230340557276f75f2e37984e410
diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk
index 01146c2..3f97221 100644
--- a/depends/packages/zeromq.mk
+++ b/depends/packages/zeromq.mk
@@ -1,19 +1,18 @@
package=zeromq
-$(package)_version=4.1.5
-$(package)_download_path=https://github.com/zeromq/zeromq4-1/releases/download/v$($(package)_version)/
+$(package)_version=4.2.2
+$(package)_download_path=https://github.com/zeromq/libzmq/releases/download/v$($(package)_version)/
$(package)_file_name=$(package)-$($(package)_version).tar.gz
-$(package)_sha256_hash=04aac57f081ffa3a2ee5ed04887be9e205df3a7ddade0027460b8042432bdbcf
-$(package)_patches=9114d3957725acd34aa8b8d011585812f3369411.patch 9e6745c12e0b100cd38acecc16ce7db02905e27c.patch
+$(package)_sha256_hash=5b23f4ca9ef545d5bd3af55d305765e3ee06b986263b31967435d285a3e6df6b
+$(package)_patches=0001-fix-build-with-older-mingw64.patch
define $(package)_set_vars
- $(package)_config_opts=--without-documentation --disable-shared --without-libsodium --disable-curve
+ $(package)_config_opts=--without-docs --disable-shared --without-libsodium --disable-curve --disable-curve-keygen --disable-perf
$(package)_config_opts_linux=--with-pic
$(package)_cxxflags=-std=c++11
endef
define $(package)_preprocess_cmds
- patch -p1 < $($(package)_patch_dir)/9114d3957725acd34aa8b8d011585812f3369411.patch && \
- patch -p1 < $($(package)_patch_dir)/9e6745c12e0b100cd38acecc16ce7db02905e27c.patch && \
+ patch -p1 < $($(package)_patch_dir)/0001-fix-build-with-older-mingw64.patch && \
./autogen.sh
endef
@@ -22,7 +21,7 @@ define $(package)_config_cmds
endef
define $(package)_build_cmds
- $(MAKE) libzmq.la
+ $(MAKE) src/libzmq.la
endef
define $(package)_stage_cmds
@@ -30,5 +29,6 @@ define $(package)_stage_cmds
endef
define $(package)_postprocess_cmds
+ sed -i.old "s/ -lstdc++//" lib/pkgconfig/libzmq.pc && \
rm -rf bin share
endef
diff --git a/depends/patches/native_mac_alias/python3.patch b/depends/patches/native_mac_alias/python3.patch
index 1a32340..6f2f553 100644
--- a/depends/patches/native_mac_alias/python3.patch
+++ b/depends/patches/native_mac_alias/python3.patch
@@ -1,7 +1,7 @@
diff -dur a/mac_alias/alias.py b/mac_alias/alias.py
---- a/mac_alias/alias.py 2015-10-19 12:12:48.000000000 +0200
-+++ b/mac_alias/alias.py 2016-04-03 12:13:12.037159417 +0200
-@@ -243,10 +243,10 @@
+--- a/mac_alias/alias.py
++++ b/mac_alias/alias.py
+@@ -258,10 +258,10 @@
alias = Alias()
alias.appinfo = appinfo
@@ -14,7 +14,7 @@ diff -dur a/mac_alias/alias.py b/mac_alias/alias.py
folder_cnid, cnid,
crdate, creator_code, type_code)
alias.target.levels_from = levels_from
-@@ -261,9 +261,9 @@
+@@ -276,9 +276,9 @@
b.read(1)
if tag == TAG_CARBON_FOLDER_NAME:
@@ -26,7 +26,7 @@ diff -dur a/mac_alias/alias.py b/mac_alias/alias.py
value)
elif tag == TAG_CARBON_PATH:
alias.target.carbon_path = value
-@@ -298,9 +298,9 @@
+@@ -313,9 +313,9 @@
alias.target.creation_date \
= mac_epoch + datetime.timedelta(seconds=seconds)
elif tag == TAG_POSIX_PATH:
@@ -38,23 +38,7 @@ diff -dur a/mac_alias/alias.py b/mac_alias/alias.py
elif tag == TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE:
alias.volume.disk_image_alias = Alias.from_bytes(value)
elif tag == TAG_USER_HOME_LENGTH_PREFIX:
-@@ -422,13 +422,13 @@
- # (so doing so is ridiculous, and nothing could rely on it).
- b.write(struct.pack(b'>h28pI2shI64pII4s4shhI2s10s',
- self.target.kind,
-- carbon_volname, voldate,
-+ carbon_volname, int(voldate),
- self.volume.fs_type,
- self.volume.disk_type,
- self.target.folder_cnid,
- carbon_filename,
- self.target.cnid,
-- crdate,
-+ int(crdate),
- self.target.creator_code,
- self.target.type_code,
- self.target.levels_from,
-@@ -449,12 +449,12 @@
+@@ -467,12 +467,12 @@
b.write(struct.pack(b'>hhQhhQ',
TAG_HIGH_RES_VOLUME_CREATION_DATE,
diff --git a/depends/patches/qt/mac-qmake.conf b/depends/patches/qt/mac-qmake.conf
index ca70d30..236988f 100644
--- a/depends/patches/qt/mac-qmake.conf
+++ b/depends/patches/qt/mac-qmake.conf
@@ -1,6 +1,7 @@
MAKEFILE_GENERATOR = UNIX
CONFIG += app_bundle incremental global_init_link_order lib_version_first plugin_no_soname absolute_library_soname
QMAKE_INCREMENTAL_STYLE = sublib
+QMAKE_APPLE_DEVICE_ARCHS = x86_64
include(../common/macx.conf)
include(../common/gcc-base-mac.conf)
include(../common/clang.conf)
@@ -8,12 +9,12 @@ include(../common/clang-mac.conf)
QMAKE_MAC_SDK_PATH=$${MAC_SDK_PATH}
QMAKE_XCODE_VERSION=4.3
QMAKE_XCODE_DEVELOPER_PATH=/Developer
-QMAKE_MACOSX_DEPLOYMENT_TARGET = $${MAC_MIN_VERSION}
QMAKE_MAC_SDK=macosx
QMAKE_MAC_SDK.macosx.Path = $${MAC_SDK_PATH}
QMAKE_MAC_SDK.macosx.platform_name = macosx
QMAKE_MAC_SDK.macosx.SDKVersion = $${MAC_SDK_VERSION}
QMAKE_MAC_SDK.macosx.PlatformPath = /phony
+QMAKE_MACOSX_DEPLOYMENT_TARGET = $${MAC_MIN_VERSION}
!host_build: QMAKE_CFLAGS += -target $${MAC_TARGET}
!host_build: QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_CFLAGS
!host_build: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS
diff --git a/depends/patches/zeromq/0001-fix-build-with-older-mingw64.patch b/depends/patches/zeromq/0001-fix-build-with-older-mingw64.patch
new file mode 100644
index 0000000..a6c508f
--- /dev/null
+++ b/depends/patches/zeromq/0001-fix-build-with-older-mingw64.patch
@@ -0,0 +1,30 @@
+From 1a159c128c69a42d90819375c06a39994f3fbfc1 Mon Sep 17 00:00:00 2001
+From: Cory Fields
+Date: Tue, 28 Nov 2017 20:33:25 -0500
+Subject: [PATCH] fix build with older mingw64
+
+---
+ src/windows.hpp | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/src/windows.hpp b/src/windows.hpp
+index 99e889d..e69038e 100644
+--- a/src/windows.hpp
++++ b/src/windows.hpp
+@@ -55,6 +55,13 @@
+ #include
+ #include
+ #include
++
++#if defined __MINGW64_VERSION_MAJOR && __MINGW64_VERSION_MAJOR < 4
++// Workaround for mingw-w64 < v4.0 which did not include ws2ipdef.h in iphlpapi.h.
++// Fixed in mingw-w64 by 9bd8fe9148924840d315b4c915dd099955ea89d1.
++#include
++#include
++#endif
+ #include
+
+ #if !defined __MINGW32__
+--
+2.7.4
+
diff --git a/doc/README.md b/doc/README.md
index 9696933..2247bb5 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -26,9 +26,7 @@ Drag XDNA-Qt to your applications folder, and then run XDNA-Qt.
### Need Help?
-* See the documentation at the [XDNA Wiki](https://en.xdna.io/wiki/Main_Page) ***TODO***
-for help and more information.
-* Ask for help on [BitcoinTalk](https://bitcointalk.org) or on the [XDNA Forum](http://forum.xdna.io/).
+* Ask for help on [BitcoinTalk](https://bitcointalk.org/index.php?topic=1262920.0).
* Join our Discord server [Discord Server](https://discord.gg/S9adMgS)
Building
@@ -48,7 +46,6 @@ The XDNA repo's [root README](https://github.com/XDNA-Core/XDNA/blob/master/READ
- [Multiwallet Qt Development](multiwallet-qt.md)
- [Release Notes](release-notes.md)
- [Release Process](release-process.md)
-- [Source Code Documentation (External Link)](https://dev.visucore.com/bitcoin/doxygen/) ***TODO***
- [Unit Tests](unit-tests.md)
- [Unauthenticated REST Interface](REST-interface.md)
- [Dnsseed Policy](dnsseed-policy.md)
@@ -56,7 +53,7 @@ The XDNA repo's [root README](https://github.com/XDNA-Core/XDNA/blob/master/READ
### Resources
-* Discuss on the [BitcoinTalk](https://bitcointalk.org/index.php?topic=1262920.0) or the [XDNA](http://forum.xdna.io/) forum.
+* Discuss on the [BitcoinTalk](https://bitcointalk.org/index.php?topic=1262920.0).
### Miscellaneous
- [Assets Attribution](assets-attribution.md)
diff --git a/doc/build-windows.md b/doc/build-windows.md
index 9740102..33068ed 100644
--- a/doc/build-windows.md
+++ b/doc/build-windows.md
@@ -32,6 +32,7 @@ To build executables for Windows 32-bit:
make HOST=i686-w64-mingw32 -j4
cd ..
./configure --prefix=`pwd`/depends/i686-w64-mingw32
+ sudo update-alternatives --config i686-w64-mingw32-g++ #For Ubuntu Xenial 16.04, Ubuntu Artful 17.10 and Windows Subsystem for Linux: Set the default mingw32 g++ compiler option to posix.
make
To build executables for Windows 64-bit:
@@ -42,6 +43,7 @@ To build executables for Windows 64-bit:
make HOST=x86_64-w64-mingw32 -j4
cd ..
./configure --prefix=`pwd`/depends/x86_64-w64-mingw32
+ sudo update-alternatives --config x86_64-w64-mingw32-g++ # Ubuntu Xenial 16.04 and Windows Subsystem for Linux: Set the default mingw32 g++ compiler option to posix.
make
For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory.
diff --git a/doc/release-notes.md b/doc/release-notes.md
index c81811e..20098bd 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -1,4 +1,4 @@
-XDNA Core version 1.0 is now available from:
+XDNA Core version 2.0 is now available from:
@@ -13,7 +13,7 @@ Compatibility
==============
XDNA Core is extensively tested on multiple operating systems using
-the Linux kernel, macOS 10.8+, and Windows Vista and later.
+the Linux kernel, macOS 10.8+, and Windows 7 and later.
Microsoft ended support for Windows XP on [April 8th, 2014](https://www.microsoft.com/en-us/WindowsForBusiness/end-of-xp-support),
No attempt is made to prevent installing or running the software on Windows XP, you
diff --git a/doc/release-process.md b/doc/release-process.md
index 0238ec9..1bd2ed5 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -3,8 +3,6 @@ Release Process
Before every release candidate:
-* Update translations (ping Fuzzbawls on Slack) see [translation_process.md](https://github.com/XDNA-Core/XDNA/blob/master/doc/translation_process.md#synchronising-translations).
-
Before every minor and major release:
* Update version in `configure.ac` (don't forget to set `CLIENT_VERSION_IS_RELEASE` to `true`)
diff --git a/src/Makefile.am b/src/Makefile.am
index 2c86a33..fead977 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -106,7 +106,7 @@ BITCOIN_CORE_H = \
crypter.h \
obfuscation.h \
obfuscation-relay.h \
- db.h \
+ wallet/db.h \
eccryptoverify.h \
ecwrapper.h \
hash.h \
@@ -133,9 +133,10 @@ BITCOIN_CORE_H = \
protocol.h \
pubkey.h \
random.h \
- rpcclient.h \
- rpcprotocol.h \
- rpcserver.h \
+ reverse_iterate.h \
+ rpc/client.h \
+ rpc/protocol.h \
+ rpc/server.h \
script/interpreter.h \
script/script.h \
script/sigcache.h \
@@ -144,11 +145,13 @@ BITCOIN_CORE_H = \
script/script_error.h \
serialize.h \
spork.h \
+ sporkdb.h \
streams.h \
sync.h \
threadsafety.h \
timedata.h \
tinyformat.h \
+ torcontrol.h \
txdb.h \
txmempool.h \
ui_interface.h \
@@ -160,18 +163,19 @@ BITCOIN_CORE_H = \
utiltime.h \
validationinterface.h \
version.h \
- wallet.h \
- wallet_ismine.h \
- walletdb.h \
+ wallet/wallet.h \
+ wallet/wallet_ismine.h \
+ wallet/walletdb.h \
zmq/zmqabstractnotifier.h \
zmq/zmqconfig.h \
zmq/zmqnotificationinterface.h \
- zmq/zmqpublishnotifier.h
+ zmq/zmqpublishnotifier.h \
+ compat/sanity.h
obj/build.h: FORCE
@$(MKDIR_P) $(builddir)/obj
- @$(top_srcdir)/share/genbuild.sh "$(abs_top_builddir)/src/obj/build.h" \
- "$(abs_top_srcdir)"
+ @$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \
+ $(abs_top_srcdir)
libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h
# server: shared between xdnad and xdna-qt
@@ -192,15 +196,17 @@ libbitcoin_server_a_SOURCES = \
noui.cpp \
pow.cpp \
rest.cpp \
- rpcblockchain.cpp \
- rpcmasternode.cpp \
- rpcmining.cpp \
- rpcmisc.cpp \
- rpcnet.cpp \
- rpcrawtransaction.cpp \
- rpcserver.cpp \
+ rpc/blockchain.cpp \
+ rpc/masternode.cpp \
+ rpc/mining.cpp \
+ rpc/misc.cpp \
+ rpc/net.cpp \
+ rpc/rawtransaction.cpp \
+ rpc/server.cpp \
script/sigcache.cpp \
+ sporkdb.cpp \
timedata.cpp \
+ torcontrol.cpp \
txdb.cpp \
txmempool.cpp \
validationinterface.cpp \
@@ -224,7 +230,7 @@ libbitcoin_wallet_a_SOURCES = \
bip38.cpp \
obfuscation.cpp \
obfuscation-relay.cpp \
- db.cpp \
+ wallet/db.cpp \
crypter.cpp \
swifttx.cpp \
masternode.cpp \
@@ -232,12 +238,12 @@ libbitcoin_wallet_a_SOURCES = \
masternode-sync.cpp \
masternodeconfig.cpp \
masternodeman.cpp \
- rpcdump.cpp \
- rpcwallet.cpp \
+ wallet/rpcdump.cpp \
+ wallet/rpcwallet.cpp \
kernel.cpp \
- wallet.cpp \
- wallet_ismine.cpp \
- walletdb.cpp \
+ wallet/wallet.cpp \
+ wallet/wallet_ismine.cpp \
+ wallet/walletdb.cpp \
$(BITCOIN_CORE_H)
# crypto primitives library
@@ -344,6 +350,7 @@ libbitcoin_common_a_SOURCES = \
script/standard.cpp \
script/script_error.cpp \
spork.cpp \
+ sporkdb.cpp \
$(BITCOIN_CORE_H)
# util: shared between all executables.
@@ -359,7 +366,7 @@ libbitcoin_util_a_SOURCES = \
chainparamsbase.cpp \
clientversion.cpp \
random.cpp \
- rpcprotocol.cpp \
+ rpc/protocol.cpp \
sync.cpp \
uint256.cpp \
util.cpp \
@@ -377,7 +384,7 @@ endif
libbitcoin_cli_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
libbitcoin_cli_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_cli_a_SOURCES = \
- rpcclient.cpp \
+ rpc/client.cpp \
$(BITCOIN_CORE_H)
nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h
@@ -503,14 +510,6 @@ clean-local:
@test -f $(PROTOC)
$(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $(vin != vin)
- {
- errorMessage = strprintf("Duplicate Masternode address: %s", service.ToString());
- LogPrintf("CActiveMasternode::Register() - %s\n", errorMessage);
- return false;
- }
+ // wait for reindex and/or import to finish
+ if (fImporting || fReindex) return false;
CMasternodePing mnp(vin);
if (!mnp.Sign(keyMasternode, pubKeyMasternode)) {
errorMessage = strprintf("Failed to sign ping, vin: %s", vin.ToString());
- LogPrintf("CActiveMasternode::Register() - %s\n", errorMessage);
+ LogPrintf("CActiveMasternode::CreateBroadcast() - %s\n", errorMessage);
+ mnb = CMasternodeBroadcast();
return false;
}
- mnodeman.mapSeenMasternodePing.insert(make_pair(mnp.GetHash(), mnp));
- LogPrintf("CActiveMasternode::Register() - Adding to Masternode list\n service: %s\n vin: %s\n", service.ToString(), vin.ToString());
- CMasternodeBroadcast mnb(service, vin, pubKeyCollateralAddress, pubKeyMasternode, PROTOCOL_VERSION);
+ mnb = CMasternodeBroadcast(service, vin, pubKeyCollateralAddress, pubKeyMasternode, PROTOCOL_VERSION);
mnb.lastPing = mnp;
if (!mnb.Sign(keyCollateralAddress)) {
errorMessage = strprintf("Failed to sign broadcast, vin: %s", vin.ToString());
- LogPrintf("CActiveMasternode::Register() - %s\n", errorMessage);
+ LogPrintf("CActiveMasternode::CreateBroadcast() - %s\n", errorMessage);
+ mnb = CMasternodeBroadcast();
return false;
}
- mnodeman.mapSeenMasternodeBroadcast.insert(make_pair(mnb.GetHash(), mnb));
- masternodeSync.AddedMasternodeList(mnb.GetHash());
-
- CMasternode* pmn = mnodeman.Find(vin);
- if (!pmn) {
- CMasternode mn(mnb);
- mnodeman.Add(mn);
- } else {
- pmn->UpdateFromNewBroadcast(mnb);
- }
-
- //send to all peers
- LogPrintf("CActiveMasternode::Register() - RelayElectionEntry vin = %s\n", vin.ToString());
- mnb.Relay();
return true;
}
@@ -294,6 +276,9 @@ bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secr
bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey, std::string strTxHash, std::string strOutputIndex)
{
+ // wait for reindex and/or import to finish
+ if (fImporting || fReindex) return false;
+
// Find possible candidates
TRY_LOCK(pwalletMain->cs_wallet, fWallet);
if (!fWallet) return false;
@@ -314,12 +299,12 @@ bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secr
return false;
}
- BOOST_FOREACH (COutput& out, possibleCoins) {
+ for (COutput& out : possibleCoins) {
if(out.tx->GetHash() != txHash || out.i != outputIndex)
continue;
- if(!CMasternode::Level(out.tx->vout[out.i].nValue))
+ if(!CMasternode::Level(out.tx->vout[out.i].nValue, chainActive.Height()))
continue;
selectedOutput = &out;
@@ -339,14 +324,14 @@ bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secr
selectedOutput = &possibleCoins[0];
- auto selected_level = CMasternode::Level(selectedOutput->tx->vout[selectedOutput->i].nValue);
+ auto selected_level = CMasternode::Level(selectedOutput->tx->vout[selectedOutput->i].nValue, chainActive.Height());
for(auto& out : possibleCoins) {
if(selected_level == 3u)
break;
- if(CMasternode::Level(out.tx->vout[out.i].nValue) > selected_level)
+ if(CMasternode::Level(out.tx->vout[out.i].nValue, chainActive.Height()) > selected_level)
selectedOutput = &out;
}
}
@@ -358,6 +343,9 @@ bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secr
// Extract Masternode vin information from output
bool CActiveMasternode::GetVinFromOutput(COutput out, CTxIn& vin, CPubKey& pubkey, CKey& secretKey)
{
+ // wait for reindex and/or import to finish
+ if (fImporting || fReindex) return false;
+
CScript pubScript;
vin = CTxIn(out.tx->GetHash(), out.i);
@@ -392,7 +380,7 @@ vector CActiveMasternode::SelectCoinsMasternode()
// Temporary unlock MN coins from masternode.conf
if (GetBoolArg("-mnconflock", true)) {
uint256 mnTxHash;
- BOOST_FOREACH (CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
+ for (CMasternodeConfig::CMasternodeEntry mne : masternodeConfig.getEntries()) {
mnTxHash.SetHex(mne.getTxHash());
int nIndex;
@@ -410,12 +398,12 @@ vector CActiveMasternode::SelectCoinsMasternode()
// Lock MN coins from masternode.conf back if they where temporary unlocked
if (!confLockedCoins.empty()) {
- BOOST_FOREACH (COutPoint outpoint, confLockedCoins)
+ for (COutPoint outpoint : confLockedCoins)
pwalletMain->LockCoin(outpoint);
}
// Filter
- BOOST_FOREACH (const COutput& out, vCoins) {
+ for (const COutput& out : vCoins) {
if(CMasternode::IsDepositCoins(out.tx->vout[out.i].nValue))
filteredCoins.push_back(out);
diff --git a/src/activemasternode.h b/src/activemasternode.h
index 1e7238e..8a011cc 100644
--- a/src/activemasternode.h
+++ b/src/activemasternode.h
@@ -1,6 +1,6 @@
// Copyright (c) 2014-2016 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -14,7 +14,7 @@
#include "net.h"
#include "obfuscation.h"
#include "sync.h"
-#include "wallet.h"
+#include "wallet/wallet.h"
#define ACTIVE_MASTERNODE_INITIAL 0 // initial state
#define ACTIVE_MASTERNODE_SYNC_IN_PROCESS 1
@@ -32,8 +32,8 @@ class CActiveMasternode
/// Ping Masternode
bool SendMasternodePing(std::string& errorMessage);
- /// Register any Masternode
- bool Register(CTxIn vin, CService service, CKey key, CPubKey pubKey, CKey keyMasternode, CPubKey pubKeyMasternode, std::string& errorMessage);
+ /// Create Masternode broadcast, needs to be relayed manually after that
+ bool CreateBroadcast(CTxIn vin, CService service, CKey key, CPubKey pubKey, CKey keyMasternode, CPubKey pubKeyMasternode, std::string& errorMessage, CMasternodeBroadcast &mnb);
/// Get XDNA input that can be used for the Masternode
bool GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey, std::string strTxHash, std::string strOutputIndex);
@@ -60,8 +60,8 @@ class CActiveMasternode
void ManageStatus();
std::string GetStatus();
- /// Register remote Masternode
- bool Register(std::string strService, std::string strKey, std::string strTxHash, std::string strOutputIndex, std::string& errorMessage);
+ /// Create Masternode broadcast, needs to be relayed manually after that
+ bool CreateBroadcast(std::string strService, std::string strKey, std::string strTxHash, std::string strOutputIndex, std::string& errorMessage, CMasternodeBroadcast &mnb, bool fOffline = false);
/// Get XDNA input that can be used for the Masternode
bool GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey);
diff --git a/src/addrman.cpp b/src/addrman.cpp
index f479f3b..be0a105 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -451,17 +451,12 @@ int CAddrMan::Check_()
void CAddrMan::GetAddr_(std::vector& vAddr)
{
unsigned int nNodes = ADDRMAN_GETADDR_MAX_PCT * vRandom.size() / 100;
-
- if(nNodes < 100 / ADDRMAN_GETADDR_MAX_PCT)
- nNodes = 100 / ADDRMAN_GETADDR_MAX_PCT;
-
- if(nNodes > ADDRMAN_GETADDR_MAX)
+ if (nNodes > ADDRMAN_GETADDR_MAX)
nNodes = ADDRMAN_GETADDR_MAX;
// gather a list of random nodes, skipping those of low quality
- for(unsigned int n = 0; n < vRandom.size(); n++) {
-
- if(vAddr.size() >= nNodes)
+ for (unsigned int n = 0; n < vRandom.size(); n++) {
+ if (vAddr.size() >= nNodes)
break;
int nRndPos = GetRandInt(vRandom.size() - n) + n;
diff --git a/src/chain.cpp b/src/chain.cpp
index 7e2cc67..5388fc1 100644
--- a/src/chain.cpp
+++ b/src/chain.cpp
@@ -13,8 +13,6 @@ using namespace std;
int64_t CChain::GetNetworkHashPS(int lookup, int height)
{
- --height;
-
CBlockIndex *pb = this->Tip();
if (height >= 0 && height < this->Height())
diff --git a/src/chain.h b/src/chain.h
index 27e9db8..49f8998 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -1,7 +1,7 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 44bc662..4356619 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -2,7 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -58,12 +58,13 @@ static Checkpoints::MapCheckpoints mapCheckpoints =
(50, uint256("000000224104db4572f767923cafd543f36b9a4d1eee117c4dc3e1961ca6371b"))
(60200, uint256("00000000000031ba24b923e1966fbe17ae0cdff1efa9d1efc556e2a3cafb5c55"))
(134000, uint256("0000000000c08ddeef3b04f5ead225a8d5f4765756d32407b74da5ca9c708b80"))
- (165000, uint256("00000000010f679ac3889908996bed4716f33de4608eb48594fd36b65f03831b"));
+ (165000, uint256("00000000010f679ac3889908996bed4716f33de4608eb48594fd36b65f03831b"))
+ (680700, uint256("0000000007151c76d2da2416f700269ef7f030a3ad8d0f788cb7107887df40fe"));
static const Checkpoints::CCheckpointData data = {
&mapCheckpoints,
- 1540098739, // * UNIX timestamp of last checkpoint block
- 234944, // * total number of transactions between genesis and last checkpoint
+ 1572678180, // * UNIX timestamp of last checkpoint block
+ 844756, // * total number of transactions between genesis and last checkpoint
// (the tx=... number in the SetBestChain debug.log lines)
2000 // * estimated number of transactions per day after checkpoint
};
@@ -237,8 +238,12 @@ class CMainParams : public CChainParams
nStartMasternodePaymentsBlock = 7001;
/** Height or Time Based Activations **/
- nLastPOWBlock = 1440000;
+ nLastPOWBlock = 682500;
nModifierUpdateBlock = std::numeric_limits::max();
+ nStartMasternodePayments = 1403728576; //Wed, 25 Jun 2014 20:36:16 GMT
+ nHEXHashTimestamp = 1533567600; // 6 August 2018, 15:00:00 GMT+00:00
+ nF2Timestamp = 1540728000; // 28 October 2018, 12:00:00 GMT+00:00
+ nF3ActivationHeight = 682500;
/**
* Build the genesis block. Note that the output of the genesis coinbase cannot
@@ -294,10 +299,7 @@ class CMainParams : public CChainParams
nPoolMaxTransactions = 3;
strSporkKey = "04520C1E6A46596DD9CA9A1A69B96D630410CBA2A1047FC462ADAA5D3BE451CC43B2E30C64A03513F31B3DB9450A3FC2F742DCB4AD99450575219549890392F465";
strObfuscationPoolDummyAddress = "X87q2gC9j6nNrnzCsg4aY6bHMLsT9nUhEw";
- nStartMasternodePayments = 1403728576; //Wed, 25 Jun 2014 20:36:16 GMT
- nHEXHashTimestamp = 1533567600; // 6 August 2018, 15:00:00 GMT+00:00
- nF2Timestamp = 1540728000; // 28 October 2018, 12:00:00 GMT+00:00
}
const Checkpoints::CCheckpointData& Checkpoints() const
diff --git a/src/chainparams.h b/src/chainparams.h
index a6ffcb8..b16c98a 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -2,7 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX Core developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -107,12 +107,13 @@ class CChainParams
/** Height or Time Based Activations **/
//todo: ModifierUpgradeBlock affect POS
- int ModifierUpgradeBlock() const { return nModifierUpdateBlock; }
- int LAST_POW_BLOCK() const { return nLastPOWBlock; }
- int StartMNPaymentsBlock() const {return nStartMasternodePaymentsBlock; }
+ int ModifierUpgradeBlock() const { return nModifierUpdateBlock; }
+ int LAST_POW_BLOCK() const { return nLastPOWBlock; }
+ int StartMNPaymentsBlock() const { return nStartMasternodePaymentsBlock; }
+ int F3Activation() const { return nF3ActivationHeight; }
- uint32_t HEXHashActivationTime() const {return nHEXHashTimestamp;}
- uint32_t F2ActivationTime() const {return nF2Timestamp;}
+ uint32_t HEXHashActivationTime() const { return nHEXHashTimestamp; }
+ uint32_t F2ActivationTime() const { return nF2Timestamp; }
const SubsidySwitchPoints& GetSubsidySwitchPoints(uint32_t nTime, int nHeight) const;
@@ -142,6 +143,7 @@ class CChainParams
int nMasternodeCountDrift;
int nMaturity;
int nModifierUpdateBlock;
+ int nF3ActivationHeight;
CAmount nMaxMoneyOut;
int nMinerThreads;
std::vector vSeeds;
diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h
index 4635ecf..90bb25f 100644
--- a/src/chainparamsseeds.h
+++ b/src/chainparamsseeds.h
@@ -52,6 +52,7 @@ static SeedSpec6 pnSeed6_test[] = {
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x95,0x1c,0x64,0x7c}, 11945},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x2d,0x4c,0xbe,0x23}, 11945},
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xca,0xb6,0x71,0x0c}, 11945}
+
};
#endif // BITCOIN_CHAINPARAMSSEEDS_H
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
index 4a601ec..51e3855 100644
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -1,7 +1,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/checkqueue.h b/src/checkqueue.h
index 9648347..a66f0b3 100644
--- a/src/checkqueue.h
+++ b/src/checkqueue.h
@@ -119,7 +119,7 @@ class CCheckQueue
fOk = fAllOk;
}
// execute work
- BOOST_FOREACH (T& check, vChecks)
+ for (T& check : vChecks)
if (fOk)
fOk = check();
vChecks.clear();
@@ -146,7 +146,7 @@ class CCheckQueue
void Add(std::vector& vChecks)
{
boost::unique_lock lock(mutex);
- BOOST_FOREACH (T& check, vChecks) {
+ for (T& check : vChecks) {
queue.push_back(T());
check.swap(queue.back());
}
diff --git a/src/clientversion.cpp b/src/clientversion.cpp
index 1841599..6f34d53 100644
--- a/src/clientversion.cpp
+++ b/src/clientversion.cpp
@@ -39,13 +39,13 @@ const std::string CLIENT_NAME("XDNA Core");
//! First, include build.h if requested
#ifdef HAVE_BUILD_INFO
-#include "build.h"
+#include "obj/build.h"
#endif
-//! git will put "#define GIT_ARCHIVE 1" on the next line inside archives.
+//! git will put "#define GIT_ARCHIVE 1" on the next line inside archives. $Format:%n#define GIT_ARCHIVE 1$
#ifdef GIT_ARCHIVE
-#define GIT_COMMIT_ID "cbcb549"
-#define GIT_COMMIT_DATE "Tue, 9 Feb 2016 16:54:57 -0500"
+#define GIT_COMMIT_ID "$Format:%H$"
+#define GIT_COMMIT_DATE "$Format:%cD$"
#endif
#define BUILD_DESC_WITH_SUFFIX(maj, min, rev, build, suffix) \
diff --git a/src/clientversion.h b/src/clientversion.h
index 2716985..293b51e 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -14,10 +14,10 @@
*/
//! These need to be macros, as clientversion.cpp's and xdna*-res.rc's voodoo requires it
-#define CLIENT_VERSION_MAJOR 1
-#define CLIENT_VERSION_MINOR 3
+#define CLIENT_VERSION_MAJOR 2
+#define CLIENT_VERSION_MINOR 0
#define CLIENT_VERSION_REVISION 0
-#define CLIENT_VERSION_BUILD 1
+#define CLIENT_VERSION_BUILD 0
//! Set to true for release, false for prerelease or test build
#define CLIENT_VERSION_IS_RELEASE true
diff --git a/src/coincontrol.h b/src/coincontrol.h
index 0cfa92f..0e9ffdf 100644
--- a/src/coincontrol.h
+++ b/src/coincontrol.h
@@ -36,7 +36,7 @@ class CCoinControl
destChange = CNoDestination();
setSelected.clear();
useSwiftTX = false;
- useObfuScation = true;
+ useObfuScation = false;
fAllowOtherInputs = false;
fAllowWatchOnly = true;
nMinimumTotalFee = 0;
diff --git a/src/core_write.cpp b/src/core_write.cpp
index f0af3e6..6421939 100644
--- a/src/core_write.cpp
+++ b/src/core_write.cpp
@@ -91,10 +91,11 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry)
{
entry.pushKV("txid", tx.GetHash().GetHex());
entry.pushKV("version", tx.nVersion);
+ entry.pushKV("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION));
entry.pushKV("locktime", (int64_t)tx.nLockTime);
UniValue vin(UniValue::VARR);
- BOOST_FOREACH (const CTxIn& txin, tx.vin) {
+ for (const CTxIn& txin : tx.vin) {
UniValue in(UniValue::VOBJ);
if (tx.IsCoinBase())
in.pushKV("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()));
diff --git a/src/crypto/hex/hex.c b/src/crypto/hex/hex.c
index 5e20266..9081ff8 100644
--- a/src/crypto/hex/hex.c
+++ b/src/crypto/hex/hex.c
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/crypto/hex/hex.h b/src/crypto/hex/hex.h
index 4d45a97..7f843fa 100644
--- a/src/crypto/hex/hex.h
+++ b/src/crypto/hex/hex.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/hash.h b/src/hash.h
index 77fbfdf..bd506e2 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -2,7 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/init.cpp b/src/init.cpp
index a677df2..8113216 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -2,7 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -24,18 +24,21 @@
#include "masternodeman.h"
#include "miner.h"
#include "net.h"
-#include "rpcserver.h"
+#include "rpc/server.h"
#include "script/standard.h"
#include "spork.h"
+#include "sporkdb.h"
#include "txdb.h"
+#include "torcontrol.h"
#include "ui_interface.h"
#include "util.h"
#include "utilmoneystr.h"
#include "validationinterface.h"
+
#ifdef ENABLE_WALLET
-#include "db.h"
-#include "wallet.h"
-#include "walletdb.h"
+#include "wallet/db.h"
+#include "wallet/wallet.h"
+#include "wallet/walletdb.h"
#endif
#include
@@ -51,6 +54,7 @@
#include
#include
#include
+#include
#include
#if ENABLE_ZMQ
@@ -156,6 +160,12 @@ class CCoinsViewErrorCatcher : public CCoinsViewBacked
static CCoinsViewDB* pcoinsdbview = NULL;
static CCoinsViewErrorCatcher* pcoinscatcher = NULL;
+static boost::thread_group threadGroup;
+
+void Interrupt()
+{
+ InterruptTorControl();
+}
/** Preparing steps before shutting down or restarting the wallet */
void PrepareShutdown()
@@ -184,6 +194,11 @@ void PrepareShutdown()
DumpMasternodes();
UnregisterNodeSignals(GetNodeSignals());
+ // After everything has been shut down, but before things get flushed, stop the
+ // CScheduler/checkqueue threadGroup
+ threadGroup.interrupt_all();
+ threadGroup.join_all();
+
if (fFeeEstimatesInitialized) {
boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
CAutoFile est_fileout(fopen(est_path.string().c_str(), "wb"), SER_DISK, CLIENT_VERSION);
@@ -210,6 +225,8 @@ void PrepareShutdown()
pcoinsdbview = NULL;
delete pblocktree;
pblocktree = NULL;
+ delete pSporkDB;
+ pSporkDB = NULL;
}
#ifdef ENABLE_WALLET
if (pwalletMain)
@@ -225,7 +242,11 @@ void PrepareShutdown()
#endif
#ifndef WIN32
+ try {
boost::filesystem::remove(GetPidFile());
+ } catch (const boost::filesystem::filesystem_error& e) {
+ LogPrintf("%s: Unable to remove pidfile: %s\n", __func__, e.what());
+ }
#endif
UnregisterAllValidationInterfaces();
}
@@ -246,7 +267,8 @@ void Shutdown()
PrepareShutdown();
}
-// Shutdown part 2: delete wallet instance
+ // Shutdown part 2: Stop TOR thread and delete wallet instance
+ StopTorControl();
#ifdef ENABLE_WALLET
delete pwalletMain;
pwalletMain = NULL;
@@ -303,7 +325,6 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-alerts", strprintf(_("Receive and display P2P network alerts (default: %u)"), DEFAULT_ALERTS));
strUsage += HelpMessageOpt("-blocknotify=", _("Execute command when the best block changes (%s in cmd is replaced by block hash)"));
strUsage += HelpMessageOpt("-checkblocks=", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), 500));
- strUsage += HelpMessageOpt("-checklevel=", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), 3));
strUsage += HelpMessageOpt("-conf=", strprintf(_("Specify configuration file (default: %s)"), "xdna.conf"));
if (mode == HMM_BITCOIND) {
#if !defined(WIN32)
@@ -313,12 +334,15 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-datadir=", _("Specify data directory"));
strUsage += HelpMessageOpt("-dbcache=", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache));
strUsage += HelpMessageOpt("-loadblock=", _("Imports blocks from external blk000??.dat file") + " " + _("on startup"));
+ strUsage += HelpMessageOpt("-maxreorg=", strprintf(_("Set the Maximum reorg depth (default: %u)"), Params(CBaseChainParams::MAIN).MaxReorganizationDepth()));
strUsage += HelpMessageOpt("-maxorphantx=", strprintf(_("Keep at most unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS));
strUsage += HelpMessageOpt("-par=", strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), -(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS));
#ifndef WIN32
strUsage += HelpMessageOpt("-pid=", strprintf(_("Specify pid file (default: %s)"), "xdnad.pid"));
#endif
strUsage += HelpMessageOpt("-reindex", _("Rebuild block chain index from current blk000??.dat files") + " " + _("on startup"));
+ strUsage += HelpMessageOpt("-reindexmoneysupply", _("Reindex the XDNA money supply statistics") + " " + _("on startup"));
+ strUsage += HelpMessageOpt("-resync", _("Delete blockchain folders and resync from scratch") + " " + _("on startup"));
#if !defined(WIN32)
strUsage += HelpMessageOpt("-sysperms", _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)"));
#endif
@@ -337,6 +361,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-externalip=", _("Specify your own public address"));
strUsage += HelpMessageOpt("-forcednsseed", strprintf(_("Always query for peer addresses via DNS lookup (default: %u)"), 0));
strUsage += HelpMessageOpt("-listen", _("Accept connections from outside (default: 1 if no -proxy or -connect)"));
+ strUsage += HelpMessageOpt("-listenonion", strprintf(_("Automatically create Tor hidden service (default: %d)"), DEFAULT_LISTEN_ONION));
strUsage += HelpMessageOpt("-maxconnections=", strprintf(_("Maintain at most connections to peers (default: %u)"), 125));
strUsage += HelpMessageOpt("-maxreceivebuffer=", strprintf(_("Maximum per-connection receive buffer, *1000 bytes (default: %u)"), 5000));
strUsage += HelpMessageOpt("-maxsendbuffer=", strprintf(_("Maximum per-connection send buffer, *1000 bytes (default: %u)"), 1000));
@@ -346,8 +371,11 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-peerbloomfilters", strprintf(_("Support filtering of blocks and transaction with bloom filters (default: %u)"), DEFAULT_PEERBLOOMFILTERS));
strUsage += HelpMessageOpt("-port=", strprintf(_("Listen for connections on (default: %u or testnet: %u)"), 1945, 11945));
strUsage += HelpMessageOpt("-proxy=", _("Connect through SOCKS5 proxy"));
+ strUsage += HelpMessageOpt("-proxyrandomize", strprintf(_("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)"), 1));
strUsage += HelpMessageOpt("-seednode=", _("Connect to a node to retrieve peer addresses, and disconnect"));
strUsage += HelpMessageOpt("-timeout=", strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT));
+ strUsage += HelpMessageOpt("-torcontrol=:", strprintf(_("Tor control port to use if onion listening enabled (default: %s)"), DEFAULT_TOR_CONTROL));
+ strUsage += HelpMessageOpt("-torpassword=", _("Tor control port password (default: empty)"));
#ifdef USE_UPNP
#if USE_UPNP
strUsage += HelpMessageOpt("-upnp", _("Use UPnP to map the listening port (default: 1 when listening)"));
@@ -373,6 +401,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup"));
strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0));
strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1));
+ strUsage += HelpMessageOpt("-disablesystemnotifications", strprintf(_("Disable OS notifications for incoming transactions (default: %u)"), 0));
strUsage += HelpMessageOpt("-txconfirmtarget=", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), 1));
strUsage += HelpMessageOpt("-maxtxfee=", strprintf(_("Maximum total fees to use in a single wallet transaction, setting too low may abort large transactions (default: %s)"),
FormatMoney(maxTxFee)));
@@ -396,6 +425,7 @@ std::string HelpMessage(HelpMessageMode mode)
#endif
strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
+ strUsage += HelpMessageOpt("-uacomment=", _("Append comment to the user agent string"));
if (GetBoolArg("-help-debug", false)) {
strUsage += HelpMessageOpt("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. Also sets -checkmempool (default: %u)", Params(CBaseChainParams::MAIN).DefaultConsistencyChecks()));
strUsage += HelpMessageOpt("-checkmempool=", strprintf("Run checks every transactions (default: %u)", Params(CBaseChainParams::MAIN).DefaultConsistencyChecks()));
@@ -406,10 +436,11 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-dropmessagestest=", _("Randomly drop 1 of every network messages"));
strUsage += HelpMessageOpt("-fuzzmessagestest=", _("Randomly fuzz 1 of every network messages"));
strUsage += HelpMessageOpt("-flushwallet", strprintf(_("Run a thread to flush wallet periodically (default: %u)"), 1));
+ strUsage += HelpMessageOpt("-maxreorg", strprintf(_("Use a custom max chain reorganization depth (default: %u)"), 100));
strUsage += HelpMessageOpt("-stopafterblockimport", strprintf(_("Stop running after importing blocks from disk (default: %u)"), 0));
strUsage += HelpMessageOpt("-sporkkey=", _("Enable spork administration functionality with the appropriate private key."));
}
- string debugCategories = "addrman, alert, bench, coindb, db, lock, rand, rpc, selectcoins, mempool, net, proxy, xdna, (obfuscation, swiftx, masternode, mnpayments)"; // Don't translate these and qt below
+ string debugCategories = "addrman, alert, bench, coindb, db, lock, rand, rpc, selectcoins, tor, mempool, net, proxy, xdna, (obfuscation, swiftx, masternode, mnpayments)"; // Don't translate these and qt below
if (mode == HMM_BITCOIN_QT)
debugCategories += ", qt";
strUsage += HelpMessageOpt("-debug=", strprintf(_("Output debugging information (default: %u, supplying is optional)"), 0) + ". " +
@@ -428,6 +459,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-relaypriority", strprintf(_("Require high priority for relaying free or low-fee transactions (default:%u)"), 1));
strUsage += HelpMessageOpt("-maxsigcachesize=", strprintf(_("Limit size of signature cache to entries (default: %u)"), 50000));
}
+ strUsage += HelpMessageOpt("-maxtipage=", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE));
strUsage += HelpMessageOpt("-minrelaytxfee=", strprintf(_("Fees (in XDNA/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK())));
strUsage += HelpMessageOpt("-printtoconsole", strprintf(_("Send trace/debug info to console instead of debug.log file (default: %u)"), 0));
if (GetBoolArg("-help-debug", false)) {
@@ -439,7 +471,7 @@ std::string HelpMessage(HelpMessageMode mode)
}
strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)"));
strUsage += HelpMessageOpt("-testnet", _("Use the test network"));
- strUsage += HelpMessageOpt("-litemode=", strprintf(_("Disable all XDNA specific functionality (Masternodes, Obfuscation, SwiftX) (0-1, default: %u)"), 0));
+ strUsage += HelpMessageOpt("-litemode=", strprintf(_("Disable all XDNA specific functionality (Masternodes, SwiftX) (0-1, default: %u)"), 0));
#ifdef ENABLE_WALLET
strUsage += HelpMessageGroup(_("Staking options:"));
@@ -458,12 +490,6 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-masternodeprivkey=", _("Set the masternode private key"));
strUsage += HelpMessageOpt("-masternodeaddr=", strprintf(_("Set external address:port to get to this masternode (example: %s)"), "128.127.106.235:1945"));
- strUsage += HelpMessageGroup(_("Obfuscation options:"));
- strUsage += HelpMessageOpt("-enableobfuscation=", strprintf(_("Enable use of automated obfuscation for funds stored in this wallet (0-1, default: %u)"), 0));
- strUsage += HelpMessageOpt("-obfuscationrounds=", strprintf(_("Use N separate masternodes to anonymize funds (2-8, default: %u)"), 2));
- strUsage += HelpMessageOpt("-anonymizexdnaamount=", strprintf(_("Keep N XDNA anonymized (default: %u)"), 0));
- strUsage += HelpMessageOpt("-liquidityprovider=", strprintf(_("Provide liquidity to Obfuscation by infrequently mixing coins on a continual basis (0-100, default: %u, 1=very frequent, high fees, 100=very infrequent, low fees)"), 0));
-
strUsage += HelpMessageGroup(_("SwiftX options:"));
strUsage += HelpMessageOpt("-enableswifttx=", strprintf(_("Enable SwiftX, show confirmations for locked transactions (bool, default: %s)"), "true"));
strUsage += HelpMessageOpt("-swifttxdepth=", strprintf(_("Show N confirmations for a successfully locked transaction (0-9999, default: %u)"), nSwiftTXDepth));
@@ -582,7 +608,7 @@ void ThreadImport(std::vector vImportFiles)
}
// -loadblock=
- BOOST_FOREACH (boost::filesystem::path& path, vImportFiles) {
+ for (boost::filesystem::path& path : vImportFiles) {
FILE* file = fopen(path.string().c_str(), "rb");
if (file) {
CImportingNow imp;
@@ -606,8 +632,7 @@ void ThreadImport(std::vector vImportFiles)
bool InitSanityCheck(void)
{
if (!ECC_InitSanityCheck()) {
- InitError("OpenSSL appears to lack support for elliptic curve cryptography. For more "
- "information, visit https://en.bitcoin.it/wiki/OpenSSL_and_EC_Libraries");
+ InitError("Elliptic curve cryptography sanity check failure. Aborting.");
return false;
}
if (!glibc_sanity_test() || !glibcxx_sanity_test())
@@ -620,7 +645,7 @@ bool InitSanityCheck(void)
/** Initialize XDNA.
* @pre Parameters should be parsed and config file should be read.
*/
-bool AppInit2(boost::thread_group& threadGroup)
+bool AppInit2()
{
// ********************************************************* Step 1: setup
#ifdef _MSC_VER
@@ -725,6 +750,8 @@ bool AppInit2(boost::thread_group& threadGroup)
LogPrintf("AppInit2 : parameter interaction: -listen=0 -> setting -upnp=0\n");
if (SoftSetBoolArg("-discover", false))
LogPrintf("AppInit2 : parameter interaction: -listen=0 -> setting -discover=0\n");
+ if (SoftSetBoolArg("-listenonion", false))
+ LogPrintf("AppInit2 : parameter interaction: -listen=0 -> setting -listenonion=0\n");
}
if (mapArgs.count("-externalip")) {
@@ -784,6 +811,9 @@ bool AppInit2(boost::thread_group& threadGroup)
// Check for -tor - as this is a privacy risk to continue, exit here
if (GetBoolArg("-tor", false))
return InitError(_("Error: Unsupported argument -tor found, use -onion."));
+ // Check level must be 4 for zerocoin checks
+ if (mapArgs.count("-checklevel"))
+ return InitError(_("Error: Unsupported argument -checklevel found. Checklevel must be level 4."));
if (GetBoolArg("-benchmark", false))
InitWarning(_("Warning: Unsupported argument -benchmark ignored, use -debug=bench."));
@@ -867,13 +897,14 @@ bool AppInit2(boost::thread_group& threadGroup)
}
}
nTxConfirmTarget = GetArg("-txconfirmtarget", 1);
- bSpendZeroConfChange = GetArg("-spendzeroconfchange", true);
- fSendFreeTransactions = GetArg("-sendfreetransactions", false);
+ bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", false);
+ bdisableSystemnotifications = GetBoolArg("-disablesystemnotifications", false);
+ fSendFreeTransactions = GetBoolArg("-sendfreetransactions", false);
std::string strWalletFile = GetArg("-wallet", "wallet.dat");
#endif // ENABLE_WALLET
- fIsBareMultisigStd = GetArg("-permitbaremultisig", true) != 0;
+ fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", true) != 0;
nMaxDatacarrierBytes = GetArg("-datacarriersize", nMaxDatacarrierBytes);
fAlerts = GetBoolArg("-alerts", DEFAULT_ALERTS);
@@ -1018,6 +1049,37 @@ bool AppInit2(boost::thread_group& threadGroup)
}
}
+ if (GetBoolArg("-resync", false)) {
+ uiInterface.InitMessage(_("Preparing for resync..."));
+ // Delete the local blockchain folders to force a resync from scratch to get a consitent blockchain-state
+ filesystem::path blocksDir = GetDataDir() / "blocks";
+ filesystem::path chainstateDir = GetDataDir() / "chainstate";
+ filesystem::path sporksDir = GetDataDir() / "sporks";
+ filesystem::path zerocoinDir = GetDataDir() / "zerocoin";
+
+ LogPrintf("Deleting blockchain folders blocks, chainstate, sporks and zerocoin\n");
+ // We delete in 4 individual steps in case one of the folder is missing already
+ try {
+ if (filesystem::exists(blocksDir)){
+ boost::filesystem::remove_all(blocksDir);
+ LogPrintf("-resync: folder deleted: %s\n", blocksDir.string().c_str());
+ }
+
+ if (filesystem::exists(chainstateDir)){
+ boost::filesystem::remove_all(chainstateDir);
+ LogPrintf("-resync: folder deleted: %s\n", chainstateDir.string().c_str());
+ }
+
+ if (filesystem::exists(sporksDir)){
+ boost::filesystem::remove_all(sporksDir);
+ LogPrintf("-resync: folder deleted: %s\n", sporksDir.string().c_str());
+ }
+
+ } catch (boost::filesystem::filesystem_error& error) {
+ LogPrintf("Failed to delete blockchain folders %s\n", error.what());
+ }
+ }
+
LogPrintf("Using wallet %s\n", strWalletFile);
uiInterface.InitMessage(_("Verifying wallet..."));
@@ -1066,9 +1128,24 @@ bool AppInit2(boost::thread_group& threadGroup)
RegisterNodeSignals(GetNodeSignals());
+ // sanitize comments per BIP-0014, format user agent and check total size
+ std::vector uacomments;
+ for (const std::string& cmt : mapMultiArgs["-uacomment"]) {
+ if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT))
+ return InitError(strprintf(_("User Agent comment (%s) contains unsafe characters."), cmt));
+ uacomments.push_back(cmt);
+ }
+
+ // format user agent, check total size
+ strSubVersion = FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, uacomments);
+ if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) {
+ return InitError(strprintf(_("Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments."),
+ strSubVersion.size(), MAX_SUBVERSION_LENGTH));
+ }
+
if (mapArgs.count("-onlynet")) {
std::set nets;
- BOOST_FOREACH (std::string snet, mapMultiArgs["-onlynet"]) {
+ for (std::string snet : mapMultiArgs["-onlynet"]) {
enum Network net = ParseNetwork(snet);
if (net == NET_UNROUTABLE)
return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet));
@@ -1082,7 +1159,7 @@ bool AppInit2(boost::thread_group& threadGroup)
}
if (mapArgs.count("-whitelist")) {
- BOOST_FOREACH (const std::string& net, mapMultiArgs["-whitelist"]) {
+ for (const std::string& net : mapMultiArgs["-whitelist"]) {
CSubNet subnet(net);
if (!subnet.IsValid())
return InitError(strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net));
@@ -1097,21 +1174,22 @@ bool AppInit2(boost::thread_group& threadGroup)
// -proxy sets a proxy for all outgoing network traffic
// -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default
std::string proxyArg = GetArg("-proxy", "");
+ SetLimited(NET_TOR);
if (proxyArg != "" && proxyArg != "0") {
CService proxyAddr;
if (!Lookup(proxyArg.c_str(), proxyAddr, 9050, fNameLookup)) {
- return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxyArg));
+ return InitError(strprintf(_("Lookup(): Invalid -proxy address or hostname: '%s'"), proxyArg));
}
proxyType addrProxy = proxyType(proxyAddr, proxyRandomize);
if (!addrProxy.IsValid())
- return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxyArg));
+ return InitError(strprintf(_("isValid(): Invalid -proxy address or hostname: '%s'"), proxyArg));
SetProxy(NET_IPV4, addrProxy);
SetProxy(NET_IPV6, addrProxy);
SetProxy(NET_TOR, addrProxy);
SetNameProxy(addrProxy);
- SetReachable(NET_TOR); // by default, -proxy sets onion as reachable, unless -noonion later
+ SetLimited(NET_TOR, false); // by default, -proxy sets onion as reachable, unless -noonion later
}
// -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
@@ -1120,7 +1198,7 @@ bool AppInit2(boost::thread_group& threadGroup)
std::string onionArg = GetArg("-onion", "");
if (onionArg != "") {
if (onionArg == "0") { // Handle -noonion/-onion=0
- SetReachable(NET_TOR, false); // set onions as unreachable
+ SetLimited(NET_TOR); // set onions as unreachable
} else {
CService onionProxy;
if (!Lookup(onionArg.c_str(), onionProxy, 9050, fNameLookup)) {
@@ -1130,25 +1208,24 @@ bool AppInit2(boost::thread_group& threadGroup)
if (!addrOnion.IsValid())
return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));
SetProxy(NET_TOR, addrOnion);
- SetReachable(NET_TOR);
+ SetLimited(NET_TOR, false);
}
}
// see Step 2: parameter interactions for more information about these
fListen = GetBoolArg("-listen", DEFAULT_LISTEN);
fDiscover = GetBoolArg("-discover", true);
- fNameLookup = GetBoolArg("-dns", true);
bool fBound = false;
if (fListen) {
if (mapArgs.count("-bind") || mapArgs.count("-whitebind")) {
- BOOST_FOREACH (std::string strBind, mapMultiArgs["-bind"]) {
+ for (std::string strBind : mapMultiArgs["-bind"]) {
CService addrBind;
if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false))
return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind));
fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR));
}
- BOOST_FOREACH (std::string strBind, mapMultiArgs["-whitebind"]) {
+ for (std::string strBind : mapMultiArgs["-whitebind"]) {
CService addrBind;
if (!Lookup(strBind.c_str(), addrBind, 0, false))
return InitError(strprintf(_("Cannot resolve -whitebind address: '%s'"), strBind));
@@ -1159,7 +1236,7 @@ bool AppInit2(boost::thread_group& threadGroup)
} else {
struct in_addr inaddr_any;
inaddr_any.s_addr = INADDR_ANY;
- fBound |= Bind(CService(in6addr_any, GetListenPort()), BF_NONE);
+ fBound |= Bind(CService((in6_addr)IN6ADDR_ANY_INIT, GetListenPort()), BF_NONE);
fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE);
}
if (!fBound)
@@ -1167,7 +1244,7 @@ bool AppInit2(boost::thread_group& threadGroup)
}
if (mapArgs.count("-externalip")) {
- BOOST_FOREACH (string strAddr, mapMultiArgs["-externalip"]) {
+ for (string strAddr : mapMultiArgs["-externalip"]) {
CService addrLocal(strAddr, GetListenPort(), fNameLookup);
if (!addrLocal.IsValid())
return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr));
@@ -1175,7 +1252,7 @@ bool AppInit2(boost::thread_group& threadGroup)
}
}
- BOOST_FOREACH (string strDest, mapMultiArgs["-seednode"])
+ for (string strDest : mapMultiArgs["-seednode"])
AddOneShot(strDest);
#if ENABLE_ZMQ
@@ -1244,7 +1321,9 @@ bool AppInit2(boost::thread_group& threadGroup)
delete pcoinsdbview;
delete pcoinscatcher;
delete pblocktree;
+ delete pSporkDB;
+ pSporkDB = new CSporkDB(0, false, false);
pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex);
pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex);
pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview);
@@ -1253,8 +1332,15 @@ bool AppInit2(boost::thread_group& threadGroup)
if (fReindex)
pblocktree->WriteReindexing(true);
- if (!LoadBlockIndex()) {
+ // MERGE: load previous sessions sporks if we have them.
+ uiInterface.InitMessage(_("Loading sporks..."));
+ LoadSporksFromDB();
+
+ uiInterface.InitMessage(_("Loading block index..."));
+ string strBlockIndexError = "";
+ if (!LoadBlockIndex(strBlockIndexError)) {
strLoadError = _("Error loading block database");
+ strLoadError = strprintf("%s : %s", strLoadError, strBlockIndexError);
break;
}
@@ -1275,18 +1361,33 @@ bool AppInit2(boost::thread_group& threadGroup)
break;
}
- uiInterface.InitMessage(_("Verifying blocks..."));
- if (!CVerifyDB().VerifyDB(pcoinsdbview, GetArg("-checklevel", 4),
- GetArg("-checkblocks", 500))) {
- strLoadError = _("Corrupted block database detected");
- break;
+ if (!fReindex) {
+ uiInterface.InitMessage(_("Verifying blocks..."));
+
+ // Flag sent to validation code to let it know it can skip certain checks
+ fVerifyingBlocks = true;
+
+ {
+ LOCK(cs_main);
+ CBlockIndex *tip = chainActive[chainActive.Height()];
+ RPCNotifyBlockChange(tip->GetBlockHash());
+ if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) {
+ strLoadError = _("The block database contains a block which appears to be from the future. "
+ "This may be due to your computer's date and time being set incorrectly. "
+ "Only rebuild the block database if you are sure that your computer's date and time are correct");
+ break;
+ }
+ }
+
}
} catch (std::exception& e) {
if (fDebug) LogPrintf("%s\n", e.what());
strLoadError = _("Error opening block database");
+ fVerifyingBlocks = false;
break;
}
+ fVerifyingBlocks = false;
fLoaded = true;
} while (false);
@@ -1349,6 +1450,7 @@ bool AppInit2(boost::thread_group& threadGroup)
}
uiInterface.InitMessage(_("Loading wallet..."));
+ fVerifyingBlocks = true;
nStart = GetTimeMillis();
bool fFirstRun = true;
@@ -1426,7 +1528,7 @@ bool AppInit2(boost::thread_group& threadGroup)
// Restore wallet transaction metadata after -zapwallettxes=1
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2") {
- BOOST_FOREACH (const CWalletTx& wtxOld, vWtx) {
+ for (const CWalletTx& wtxOld : vWtx) {
uint256 hash = wtxOld.GetHash();
std::map::iterator mi = pwalletMain->mapWallet.find(hash);
if (mi != pwalletMain->mapWallet.end()) {
@@ -1444,6 +1546,7 @@ bool AppInit2(boost::thread_group& threadGroup)
}
}
}
+ fVerifyingBlocks = false;
} // (!fDisableWallet)
#else // ENABLE_WALLET
LogPrintf("No wallet compiled in!\n");
@@ -1460,7 +1563,7 @@ bool AppInit2(boost::thread_group& threadGroup)
std::vector vImportFiles;
if (mapArgs.count("-loadblock")) {
- BOOST_FOREACH (string strFile, mapMultiArgs["-loadblock"])
+ for (string strFile : mapMultiArgs["-loadblock"])
vImportFiles.push_back(strFile);
}
threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles));
@@ -1494,7 +1597,7 @@ bool AppInit2(boost::thread_group& threadGroup)
}
if (fMasterNode) {
- LogPrintf("IS OBFUSCATION MASTER NODE\n");
+ LogPrintf("IS MASTER NODE\n");
strMasterNodeAddr = GetArg("-masternodeaddr", "");
LogPrintf(" addr %s\n", strMasterNodeAddr.c_str());
@@ -1528,7 +1631,7 @@ bool AppInit2(boost::thread_group& threadGroup)
LOCK(pwalletMain->cs_wallet);
LogPrintf("Locking Masternodes:\n");
uint256 mnTxHash;
- BOOST_FOREACH (CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
+ for (CMasternodeConfig::CMasternodeEntry mne : masternodeConfig.getEntries()) {
LogPrintf(" %s %s\n", mne.getTxHash(), mne.getOutputIndex());
mnTxHash.SetHex(mne.getTxHash());
COutPoint outpoint = COutPoint(mnTxHash, boost::lexical_cast(mne.getOutputIndex()));
@@ -1611,6 +1714,9 @@ bool AppInit2(boost::thread_group& threadGroup)
LogPrintf("mapAddressBook.size() = %u\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0);
#endif
+ if (GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION))
+ StartTorControl(threadGroup);
+
StartNode(threadGroup);
#ifdef ENABLE_WALLET
diff --git a/src/init.h b/src/init.h
index 36300ea..1a519cb 100644
--- a/src/init.h
+++ b/src/init.h
@@ -19,9 +19,11 @@ extern CWallet* pwalletMain;
void StartShutdown();
bool ShutdownRequested();
+/** Interrupt threads */
void Shutdown();
+void Interrupt();
void PrepareShutdown();
-bool AppInit2(boost::thread_group& threadGroup);
+bool AppInit2();
/** The help message mode determines what help message to show */
enum HelpMessageMode {
diff --git a/src/kernel.cpp b/src/kernel.cpp
index 2a5fd66..3d15dfc 100644
--- a/src/kernel.cpp
+++ b/src/kernel.cpp
@@ -1,7 +1,7 @@
/* @flow */
// Copyright (c) 2012-2013 The PPCoin developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -87,7 +87,7 @@ static bool SelectBlockFromCandidates(
bool fSelected = false;
uint256 hashBest = 0;
*pindexSelected = (const CBlockIndex*)0;
- BOOST_FOREACH (const PAIRTYPE(int64_t, uint256) & item, vSortedByTimestamp) {
+ for (const PAIRTYPE(int64_t, uint256) & item : vSortedByTimestamp) {
if (!mapBlockIndex.count(item.second))
return error("SelectBlockFromCandidates: failed to find block index for candidate block %s", item.second.ToString().c_str());
@@ -170,7 +170,7 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64_t& nStakeMod
return error("ComputeNextStakeModifier: unable to get last modifier");
if (GetBoolArg("-printstakemodifier", false))
- LogPrintf("ComputeNextStakeModifier: prev modifier= %s time=%s\n", boost::lexical_cast(nStakeModifier).c_str(), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", nModifierTime).c_str());
+ LogPrintf("ComputeNextStakeModifier: prev modifier= %s time=%s\n", std::to_string(nStakeModifier).c_str(), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", nModifierTime).c_str());
if (nModifierTime / getIntervalVersion(fTestNet) >= pindexPrev->GetBlockTime() / getIntervalVersion(fTestNet))
return true;
@@ -225,7 +225,7 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64_t& nStakeMod
strSelectionMap.replace(pindex->nHeight - nHeightFirstCandidate, 1, "=");
pindex = pindex->pprev;
}
- BOOST_FOREACH (const PAIRTYPE(uint256, const CBlockIndex*) & item, mapSelectedBlocks) {
+ for (const std::pair &item : mapSelectedBlocks) {
// 'S' indicates selected proof-of-stake blocks
// 'W' indicates selected proof-of-work blocks
strSelectionMap.replace(item.second->nHeight - nHeightFirstCandidate, 1, item.second->IsProofOfStake() ? "S" : "W");
@@ -233,7 +233,7 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64_t& nStakeMod
LogPrintf("ComputeNextStakeModifier: selection height [%d, %d] map %s\n", nHeightFirstCandidate, pindexPrev->nHeight, strSelectionMap.c_str());
}
if (fDebug || GetBoolArg("-printstakemodifier", false)) {
- LogPrintf("ComputeNextStakeModifier: new modifier=%s time=%s\n", boost::lexical_cast(nStakeModifierNew).c_str(), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexPrev->GetBlockTime()).c_str());
+ LogPrintf("ComputeNextStakeModifier: new modifier=%s time=%s\n", std::to_string(nStakeModifierNew).c_str(), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexPrev->GetBlockTime()).c_str());
}
nStakeModifier = nStakeModifierNew;
diff --git a/src/leveldb/db/memtable.cc b/src/leveldb/db/memtable.cc
index bfec0a7..31ad995 100644
--- a/src/leveldb/db/memtable.cc
+++ b/src/leveldb/db/memtable.cc
@@ -101,7 +101,7 @@ void MemTable::Add(SequenceNumber s, ValueType type,
p += 8;
p = EncodeVarint32(p, val_size);
memcpy(p, value.data(), val_size);
- assert((p + val_size) - buf == encoded_len);
+ assert((p + val_size) - buf == (long)encoded_len);
table_.Insert(buf);
}
diff --git a/src/leveldb/util/bloom.cc b/src/leveldb/util/bloom.cc
index a27a2ac..79276b8 100644
--- a/src/leveldb/util/bloom.cc
+++ b/src/leveldb/util/bloom.cc
@@ -47,7 +47,7 @@ class BloomFilterPolicy : public FilterPolicy {
dst->resize(init_size + bytes, 0);
dst->push_back(static_cast(k_)); // Remember # of probes in filter
char* array = &(*dst)[init_size];
- for (size_t i = 0; i < n; i++) {
+ for (size_t i = 0; i < (size_t)n; i++) {
// Use double-hashing to generate a sequence of hash values.
// See analysis in [Kirsch,Mitzenmacher 2006].
uint32_t h = BloomHash(keys[i]);
diff --git a/src/leveldb/util/logging.cc b/src/leveldb/util/logging.cc
index ca6b324..2a1028a 100644
--- a/src/leveldb/util/logging.cc
+++ b/src/leveldb/util/logging.cc
@@ -55,7 +55,7 @@ bool ConsumeDecimalNumber(Slice* in, uint64_t* val) {
const int delta = (c - '0');
static const uint64_t kMaxUint64 = ~static_cast(0);
if (v > kMaxUint64/10 ||
- (v == kMaxUint64/10 && delta > kMaxUint64%10)) {
+ (v == kMaxUint64/10 && (uint64_t)delta > kMaxUint64%10)) {
// Overflow
return false;
}
diff --git a/src/leveldbwrapper.cpp b/src/leveldbwrapper.cpp
index 70980fe..a5c56ef 100644
--- a/src/leveldbwrapper.cpp
+++ b/src/leveldbwrapper.cpp
@@ -13,7 +13,7 @@
#include
#include
-void HandleError(const leveldb::Status& status) throw(leveldb_error)
+void HandleError(const leveldb::Status& status)
{
if (status.ok())
return;
@@ -27,6 +27,31 @@ void HandleError(const leveldb::Status& status) throw(leveldb_error)
throw leveldb_error("Unknown database error");
}
+static void SetMaxOpenFiles(leveldb::Options *options) {
+ // On most platforms the default setting of max_open_files (which is 1000)
+ // is optimal. On Windows using a large file count is OK because the handles
+ // do not interfere with select() loops. On 64-bit Unix hosts this value is
+ // also OK, because up to that amount LevelDB will use an mmap
+ // implementation that does not use extra file descriptors (the fds are
+ // closed after being mmaped).
+ //
+ // Increasing the value beyond the default is dangerous because LevelDB will
+ // fall back to a non-mmap implementation when the file count is too large.
+ // On 32-bit Unix host we should decrease the value because the handles use
+ // up real fds, and we want to avoid fd exhaustion issues.
+ //
+ // See PR #12495 for further discussion.
+
+ int default_open_files = options->max_open_files;
+#ifndef WIN32
+ if (sizeof(void*) < 8) {
+ options->max_open_files = 64;
+ }
+#endif
+ LogPrintf("LevelDB using max_open_files=%d (default=%d)\n",
+ options->max_open_files, default_open_files);
+}
+
static leveldb::Options GetOptions(size_t nCacheSize)
{
leveldb::Options options;
@@ -34,12 +59,12 @@ static leveldb::Options GetOptions(size_t nCacheSize)
options.write_buffer_size = nCacheSize / 4; // up to two write buffers may be held in memory simultaneously
options.filter_policy = leveldb::NewBloomFilterPolicy(10);
options.compression = leveldb::kNoCompression;
- options.max_open_files = 64;
if (leveldb::kMajorVersion > 1 || (leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16)) {
// LevelDB versions before 1.16 consider short writes to be corruption. Only trigger error
// on corruption in later versions.
options.paranoid_checks = true;
}
+ SetMaxOpenFiles(&options);
return options;
}
@@ -80,7 +105,7 @@ CLevelDBWrapper::~CLevelDBWrapper()
options.env = NULL;
}
-bool CLevelDBWrapper::WriteBatch(CLevelDBBatch& batch, bool fSync) throw(leveldb_error)
+bool CLevelDBWrapper::WriteBatch(CLevelDBBatch& batch, bool fSync)
{
leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
HandleError(status);
diff --git a/src/leveldbwrapper.h b/src/leveldbwrapper.h
index 4247920..6f8427a 100644
--- a/src/leveldbwrapper.h
+++ b/src/leveldbwrapper.h
@@ -22,7 +22,7 @@ class leveldb_error : public std::runtime_error
leveldb_error(const std::string& msg) : std::runtime_error(msg) {}
};
-void HandleError(const leveldb::Status& status) throw(leveldb_error);
+void HandleError(const leveldb::Status& status);
/** Batch of changes queued to be written to a CLevelDBWrapper */
class CLevelDBBatch
@@ -90,7 +90,7 @@ class CLevelDBWrapper
~CLevelDBWrapper();
template
- bool Read(const K& key, V& value) const throw(leveldb_error)
+ bool Read(const K& key, V& value) const
{
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(ssKey.GetSerializeSize(key));
@@ -115,7 +115,7 @@ class CLevelDBWrapper
}
template
- bool Write(const K& key, const V& value, bool fSync = false) throw(leveldb_error)
+ bool Write(const K& key, const V& value, bool fSync = false)
{
CLevelDBBatch batch;
batch.Write(key, value);
@@ -123,7 +123,7 @@ class CLevelDBWrapper
}
template
- bool Exists(const K& key) const throw(leveldb_error)
+ bool Exists(const K& key) const
{
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(ssKey.GetSerializeSize(key));
@@ -142,14 +142,14 @@ class CLevelDBWrapper
}
template
- bool Erase(const K& key, bool fSync = false) throw(leveldb_error)
+ bool Erase(const K& key, bool fSync = false)
{
CLevelDBBatch batch;
batch.Erase(key);
return WriteBatch(batch, fSync);
}
- bool WriteBatch(CLevelDBBatch& batch, bool fSync = false) throw(leveldb_error);
+ bool WriteBatch(CLevelDBBatch& batch, bool fSync = false);
// not available for LevelDB; provide for compatibility with BDB
bool Flush()
@@ -157,7 +157,7 @@ class CLevelDBWrapper
return true;
}
- bool Sync() throw(leveldb_error)
+ bool Sync()
{
CLevelDBBatch batch;
return WriteBatch(batch, true);
diff --git a/src/main.cpp b/src/main.cpp
index 9962972..a13733d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2,7 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -22,20 +22,24 @@
#include "obfuscation.h"
#include "pow.h"
#include "spork.h"
+#include "sporkdb.h"
#include "swifttx.h"
#include "txdb.h"
#include "txmempool.h"
#include "ui_interface.h"
#include "util.h"
#include "utilmoneystr.h"
+#include "validationinterface.h"
#include
#include
#include
#include
-#include
#include
+#include
+#include
+#include
using namespace boost;
using namespace std;
@@ -44,15 +48,21 @@ using namespace std;
#error "XDNA cannot be compiled without assertions."
#endif
+// 6 comes from OPCODE (1) + vch.size() (1) + BIGNUM size (4)
+#define SCRIPT_OFFSET 6
+// For Script size (BIGNUM/Uint256 size)
+#define BIGNUM_SIZE 4
/**
* Global state
*/
CCriticalSection cs_main;
+CCriticalSection cs_mapstake;
BlockMap mapBlockIndex;
map mapProofOfStake;
set > setStakeSeen;
+map mapStakeSpent;
map mapHashedBlocks;
CChain chainActive;
CBlockIndex* pindexBestHeader = NULL;
@@ -65,10 +75,15 @@ bool fReindex = false;
bool fTxIndex = true;
bool fIsBareMultisigStd = true;
bool fCheckBlockIndex = false;
+bool fVerifyingBlocks = false;
unsigned int nCoinCacheSize = 5000;
bool fAlerts = DEFAULT_ALERTS;
+bool fClearSpendCache = false;
-unsigned int nStakeMinAge = 60 * 60;
+/* If the tip is older than this (in seconds), the node is considered to be in initial block download. */
+int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
+
+unsigned int nStakeMinAge = 1 * 60 * 60;
int64_t nReserveBalance = 0;
/** Fees smaller than this (in uxdna) are considered zero fee (for relaying and mining)
@@ -87,7 +102,6 @@ map mapOrphanTransactions;
map > mapOrphanTransactionsByPrev;
map mapRejectedBlocks;
-
void EraseOrphansFor(NodeId peer);
static void CheckBlockIndex();
@@ -176,84 +190,95 @@ set setDirtyFileInfo;
//////////////////////////////////////////////////////////////////////////////
//
-// dispatching functions
+// Registration of network node signals.
//
-// These functions dispatch to one or all registered wallets
-
namespace
{
-struct CMainSignals {
- /** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */
- boost::signals2::signal SyncTransaction;
- /** Notifies listeners of an erased transaction (currently disabled, requires transaction replacement). */
- // XX42 boost::signals2::signal EraseTransaction;
- /** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */
- boost::signals2::signal UpdatedTransaction;
- /** Notifies listeners of a new active block chain. */
- boost::signals2::signal SetBestChain;
- /** Notifies listeners about an inventory item being seen on the network. */
- boost::signals2::signal Inventory;
- /** Tells listeners to broadcast their data. */
- boost::signals2::signal Broadcast;
- /** Notifies listeners of a block validation result */
- boost::signals2::signal BlockChecked;
-} g_signals;
+struct CBlockReject {
+ unsigned char chRejectCode;
+ string strRejectReason;
+ uint256 hashBlock;
+};
-} // anon namespace
-void RegisterValidationInterface(CValidationInterface* pwalletIn)
+class CNodeBlocks
{
- g_signals.SyncTransaction.connect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2));
- // XX42 g_signals.EraseTransaction.connect(boost::bind(&CValidationInterface::EraseFromWallet, pwalletIn, _1));
- g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
- g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
- g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
- g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn));
- g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
-}
+public:
+ CNodeBlocks():
+ maxSize(0),
+ maxAvg(0)
+ {
+ maxSize = GetArg("-blockspamfiltermaxsize", DEFAULT_BLOCK_SPAM_FILTER_MAX_SIZE);
+ maxAvg = GetArg("-blockspamfiltermaxavg", DEFAULT_BLOCK_SPAM_FILTER_MAX_AVG);
+ }
-void UnregisterValidationInterface(CValidationInterface* pwalletIn)
-{
- g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
- g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn));
- g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
- g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
- g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
- // XX42 g_signals.EraseTransaction.disconnect(boost::bind(&CValidationInterface::EraseFromWallet, pwalletIn, _1));
- g_signals.SyncTransaction.disconnect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2));
-}
+ bool onBlockReceived(int nHeight) {
+ if(nHeight > 0 && maxSize && maxAvg) {
+ addPoint(nHeight);
+ return true;
+ }
+ return false;
+ }
-void UnregisterAllValidationInterfaces()
-{
- g_signals.BlockChecked.disconnect_all_slots();
- g_signals.Broadcast.disconnect_all_slots();
- g_signals.Inventory.disconnect_all_slots();
- g_signals.SetBestChain.disconnect_all_slots();
- g_signals.UpdatedTransaction.disconnect_all_slots();
- // XX42 g_signals.EraseTransaction.disconnect_all_slots();
- g_signals.SyncTransaction.disconnect_all_slots();
-}
+ bool updateState(CValidationState& state, bool ret)
+ {
+ // No Blocks
+ size_t size = points.size();
+ if(size == 0)
+ return ret;
+
+ // Compute the number of the received blocks
+ size_t nBlocks = 0;
+ for(auto point : points)
+ {
+ nBlocks += point.second;
+ }
-void SyncWithWallets(const CTransaction& tx, const CBlock* pblock)
-{
- g_signals.SyncTransaction(tx, pblock);
-}
+ // Compute the average value per height
+ double nAvgValue = (double)nBlocks / size;
-//////////////////////////////////////////////////////////////////////////////
-//
-// Registration of network node signals.
-//
+ // Ban the node if try to spam
+ bool banNode = (nAvgValue >= 1.5 * maxAvg && size >= maxAvg) ||
+ (nAvgValue >= maxAvg && nBlocks >= maxSize) ||
+ (nBlocks >= maxSize * 3);
+ if(banNode)
+ {
+ // Clear the points and ban the node
+ points.clear();
+ return state.DoS(100, error("block-spam ban node for sending spam"));
+ }
-namespace
-{
-struct CBlockReject {
- unsigned char chRejectCode;
- string strRejectReason;
- uint256 hashBlock;
+ return ret;
+ }
+
+private:
+ void addPoint(int height)
+ {
+ // Remove the last element in the list
+ if(points.size() == maxSize)
+ {
+ points.erase(points.begin());
+ }
+
+ // Add the point to the list
+ int occurrence = 0;
+ auto mi = points.find(height);
+ if (mi != points.end())
+ occurrence = (*mi).second;
+ occurrence++;
+ points[height] = occurrence;
+ }
+
+private:
+ std::map points;
+ size_t maxSize;
+ size_t maxAvg;
};
-/**
+
+
+ /**
* Maintain validation-specific state about nodes, protected by cs_main, instead
* by CNode's own locks. This simplifies asynchronous operation, where
* processing of incoming data is done after the ProcessMessage call returns,
@@ -287,6 +312,8 @@ struct CNodeState {
//! Whether we consider this a preferred download peer.
bool fPreferredDownload;
+ CNodeBlocks nodeBlocks;
+
CNodeState()
{
fCurrentlyConnected = false;
@@ -356,7 +383,7 @@ void FinalizeNode(NodeId nodeid)
AddressCurrentlyConnected(state->address);
}
- BOOST_FOREACH (const QueuedBlock& entry, state->vBlocksInFlight)
+ for (const QueuedBlock& entry : state->vBlocksInFlight)
mapBlocksInFlight.erase(entry.hash);
EraseOrphansFor(nodeid);
nPreferredDownload -= state->fPreferredDownload;
@@ -503,7 +530,7 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vectorIsValid(BLOCK_VALID_TREE)) {
// We consider the chain that this peer is on invalid.
return;
@@ -544,7 +571,7 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats)
stats.nMisbehavior = state->nMisbehavior;
stats.nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
stats.nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
- BOOST_FOREACH (const QueuedBlock& queue, state->vBlocksInFlight) {
+ for (const QueuedBlock& queue : state->vBlocksInFlight) {
if (queue.pindex)
stats.vHeightInFlight.push_back(queue.pindex->nHeight);
}
@@ -572,7 +599,7 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals)
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator)
{
// Find the first block the caller has in the main chain
- BOOST_FOREACH (const uint256& hash, locator.vHave) {
+ for (const uint256& hash : locator.vHave) {
BlockMap::iterator mi = mapBlockIndex.find(hash);
if (mi != mapBlockIndex.end()) {
CBlockIndex* pindex = (*mi).second;
@@ -585,6 +612,7 @@ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& loc
CCoinsViewCache* pcoinsTip = NULL;
CBlockTreeDB* pblocktree = NULL;
+CSporkDB* pSporkDB = NULL;
//////////////////////////////////////////////////////////////////////////////
//
@@ -612,7 +640,7 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer)
mapOrphanTransactions[hash].tx = tx;
mapOrphanTransactions[hash].fromPeer = peer;
- BOOST_FOREACH (const CTxIn& txin, tx.vin)
+ for (const CTxIn& txin : tx.vin)
mapOrphanTransactionsByPrev[txin.prevout.hash].insert(hash);
LogPrint("mempool", "stored orphan tx %s (mapsz %u prevsz %u)\n", hash.ToString(),
@@ -625,7 +653,7 @@ void static EraseOrphanTx(uint256 hash)
map::iterator it = mapOrphanTransactions.find(hash);
if (it == mapOrphanTransactions.end())
return;
- BOOST_FOREACH (const CTxIn& txin, it->second.tx.vin) {
+ for (const CTxIn& txin : it->second.tx.vin) {
map >::iterator itPrev = mapOrphanTransactionsByPrev.find(txin.prevout.hash);
if (itPrev == mapOrphanTransactionsByPrev.end())
continue;
@@ -701,12 +729,13 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
// computing signature hashes is O(ninputs*txsize). Limiting transactions
// to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
- if (sz >= MAX_STANDARD_TX_SIZE) {
+ unsigned int nMaxSize = MAX_STANDARD_TX_SIZE;
+ if (sz >= nMaxSize) {
reason = "tx-size";
return false;
}
- BOOST_FOREACH (const CTxIn& txin, tx.vin) {
+ for (const CTxIn& txin : tx.vin) {
// Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
// keys. (remember the 520 byte limit on redeemScript size) That works
// out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
@@ -726,7 +755,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
unsigned int nDataOut = 0;
txnouttype whichType;
- BOOST_FOREACH (const CTxOut& txout, tx.vout) {
+ for (const CTxOut& txout : tx.vout) {
if (!::IsStandard(txout.scriptPubKey, whichType)) {
reason = "scriptpubkey";
return false;
@@ -836,10 +865,10 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
unsigned int GetLegacySigOpCount(const CTransaction& tx)
{
unsigned int nSigOps = 0;
- BOOST_FOREACH (const CTxIn& txin, tx.vin) {
+ for (const CTxIn& txin : tx.vin) {
nSigOps += txin.scriptSig.GetSigOpCount(false);
}
- BOOST_FOREACH (const CTxOut& txout, tx.vout) {
+ for (const CTxOut& txout : tx.vout) {
nSigOps += txout.scriptPubKey.GetSigOpCount(false);
}
return nSigOps;
@@ -925,7 +954,7 @@ bool GetCoinAge(const CTransaction& tx, const unsigned int nTxTime, uint64_t& nC
nCoinAge = 0;
CBlockIndex* pindex = NULL;
- BOOST_FOREACH (const CTxIn& txin, tx.vin) {
+ for (const CTxIn& txin : tx.vin) {
// First try finding the previous transaction in database
CTransaction txPrev;
uint256 hashBlockPrev;
@@ -977,7 +1006,6 @@ bool CheckTransaction(const CTransaction& tx, CValidationState& state)
if (tx.vout.empty())
return state.DoS(10, error("CheckTransaction() : vout empty"),
REJECT_INVALID, "bad-txns-vout-empty");
-
// Size limits
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
return state.DoS(100, error("CheckTransaction() : size limits failed"),
@@ -985,13 +1013,13 @@ bool CheckTransaction(const CTransaction& tx, CValidationState& state)
// Check for negative or overflow output values
CAmount nValueOut = 0;
- BOOST_FOREACH (const CTxOut& txout, tx.vout) {
+ for (const CTxOut& txout : tx.vout) {
if (txout.IsEmpty() && !tx.IsCoinBase() && !tx.IsCoinStake())
return state.DoS(100, error("CheckTransaction(): txout empty for user transaction"));
- if (txout.nValue < 0){LogPrintf("txout.nValue= %d",txout.nValue);
+ if (txout.nValue < 0)
return state.DoS(100, error("CheckTransaction() : txout.nValue negative"),
- REJECT_INVALID, "bad-txns-vout-negative");}
+ REJECT_INVALID, "bad-txns-vout-negative");
if (txout.nValue > Params().MaxMoneyOut())
return state.DoS(100, error("CheckTransaction() : txout.nValue too high"),
REJECT_INVALID, "bad-txns-vout-toolarge");
@@ -1001,9 +1029,9 @@ bool CheckTransaction(const CTransaction& tx, CValidationState& state)
REJECT_INVALID, "bad-txns-txouttotal-toolarge");
}
- // Check for duplicate inputs
set vInOutPoints;
- BOOST_FOREACH (const CTxIn& txin, tx.vin) {
+ for (const CTxIn& txin : tx.vin) {
+ // Check for duplicate inputs
if (vInOutPoints.count(txin.prevout))
return state.DoS(100, error("CheckTransaction() : duplicate inputs"),
REJECT_INVALID, "bad-txns-inputs-duplicate");
@@ -1011,12 +1039,12 @@ bool CheckTransaction(const CTransaction& tx, CValidationState& state)
}
if (tx.IsCoinBase()) {
- if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 150)
+ if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 150)
+ return state.DoS(100, error("CheckTransaction() : coinbase script size=%d", tx.vin[0].scriptSig.size()),
+ REJECT_INVALID, "bad-cb-length");
- return state.DoS(100, error("CheckTransaction() : coinbase script size=%d", tx.vin[0].scriptSig.size()),
- REJECT_INVALID, "bad-cb-length");
} else {
- BOOST_FOREACH (const CTxIn& txin, tx.vin)
+ for (const CTxIn& txin : tx.vin)
if (txin.prevout.IsNull())
return state.DoS(10, error("CheckTransaction() : prevout is null"),
REJECT_INVALID, "bad-txns-prevout-null");
@@ -1083,7 +1111,6 @@ CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF
return nMinFee;
}
-
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransaction& tx, bool fLimitFree, bool* pfMissingInputs, bool fRejectInsaneFee, bool ignoreFees)
{
AssertLockHeld(cs_main);
@@ -1100,9 +1127,15 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransa
//Coinstake is also only valid in a block, not as a loose transaction
if (tx.IsCoinStake())
- return state.DoS(100, error("AcceptToMemoryPool: coinstake as individual tx"),
+ return state.DoS(100, error("AcceptToMemoryPool: coinstake as individual tx. txid=%s", tx.GetHash().GetHex()),
REJECT_INVALID, "coinstake");
+ // Only accept nLockTime-using transactions that can be mined in the next
+ // block; we don't want our mempool filled up with transactions that can't
+ // be mined yet.
+ if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS))
+ return state.DoS(0, false, REJECT_NONSTANDARD, "non-final");
+
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
string reason;
if (Params().RequireStandard() && !IsStandardTx(tx, reason))
@@ -1116,31 +1149,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransa
return false;
}
- // ----------- swiftTX transaction scanning -----------
-
- BOOST_FOREACH (const CTxIn& in, tx.vin) {
- if (mapLockedInputs.count(in.prevout)) {
- if (mapLockedInputs[in.prevout] != tx.GetHash()) {
- return state.DoS(0,
- error("AcceptToMemoryPool : conflicts with existing transaction lock: %s", reason),
- REJECT_INVALID, "tx-lock-conflict");
- }
- }
- }
-
- // Check for conflicts with in-memory transactions
- {
- LOCK(pool.cs); // protect pool.mapNextTx
- for (unsigned int i = 0; i < tx.vin.size(); i++) {
- COutPoint outpoint = tx.vin[i].prevout;
- if (pool.mapNextTx.count(outpoint)) {
- // Disable replacement feature for now
- return false;
- }
- }
- }
-
-
{
CCoinsView dummy;
CCoinsViewCache view(&dummy);
@@ -1158,7 +1166,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransa
// do all inputs exist?
// Note that this does not check for the presence of actual outputs (see the next check for that),
// only helps filling in pfMissingInputs (to determine missing vs spent).
- for (const CTxIn txin : tx.vin) {
+ for (const CTxIn& txin : tx.vin) {
if (!view.HaveCoins(txin.prevout.hash)) {
if (pfMissingInputs)
*pfMissingInputs = true;
@@ -1169,7 +1177,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransa
// are the actual inputs available?
if (!view.HaveInputs(tx))
return state.Invalid(error("AcceptToMemoryPool : inputs already spent"),
- REJECT_DUPLICATE, "bad-txns-inputs-spent");
+ REJECT_DUPLICATE, "bad-txns-inputs-spent");
// Bring the best block into scope
view.GetBestBlock();
@@ -1184,6 +1192,9 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransa
if (Params().RequireStandard() && !AreInputsStandard(tx, view))
return error("AcceptToMemoryPool: : nonstandard transaction input");
+ static const unsigned int MAX_BLOCK_SIGOPS = 1000000 / 50;
+ static const unsigned int MAX_TX_SIGOPS = MAX_BLOCK_SIGOPS / 5;
+
// Check that the transaction doesn't have an excessive number of
// sigops, making it impossible to mine. Since the coinbase transaction
// itself can contain sigops MAX_TX_SIGOPS is less than
@@ -1192,10 +1203,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransa
unsigned int nSigOps = GetLegacySigOpCount(tx);
nSigOps += GetP2SHSigOpCount(tx, view);
if (nSigOps > MAX_TX_SIGOPS)
- return state.DoS(0,
- error("AcceptToMemoryPool : too many sigops %s, %d > %d",
+ return state.DoS(0,
+ error("AcceptToMemoryPool : too many sigops %s, %d > %d",
hash.ToString(), nSigOps, MAX_TX_SIGOPS),
- REJECT_NONSTANDARD, "bad-txns-too-many-sigops");
+ REJECT_NONSTANDARD, "bad-txns-too-many-sigops");
CAmount nValueOut = tx.GetValueOut();
CAmount nFees = nValueIn - nValueOut;
@@ -1204,46 +1215,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransa
CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height());
unsigned int nSize = entry.GetTxSize();
- // Don't accept it if it can't get into a block
- // but prioritise dstx and don't check fees for it
- if (mapObfuscationBroadcastTxes.count(hash)) {
- mempool.PrioritiseTransaction(hash, hash.ToString(), 1000, 0.1 * COIN);
- } else if (!ignoreFees) {
- CAmount txMinFee = GetMinRelayFee(tx, nSize, true);
- if (fLimitFree && nFees < txMinFee)
- return state.DoS(0, error("AcceptToMemoryPool : not enough fees %s, %d < %d",
- hash.ToString(), nFees, txMinFee),
- REJECT_INSUFFICIENTFEE, "insufficient fee");
-
- // Require that free transactions have sufficient priority to be mined in the next block.
- if (GetBoolArg("-relaypriority", true) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(view.GetPriority(tx, chainActive.Height() + 1))) {
- return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient priority");
- }
-
- // Continuously rate-limit free (really, very-low-fee) transactions
- // This mitigates 'penny-flooding' -- sending thousands of free transactions just to
- // be annoying or make others' transactions take longer to confirm.
- if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize)) {
- static CCriticalSection csFreeLimiter;
- static double dFreeCount;
- static int64_t nLastTime;
- int64_t nNow = GetTime();
-
- LOCK(csFreeLimiter);
-
- // Use an exponentially decaying ~10-minute window:
- dFreeCount *= pow(1.0 - 1.0 / 600.0, (double)(nNow - nLastTime));
- nLastTime = nNow;
- // -limitfreerelay unit is thousand-bytes-per-minute
- // At default rate it would take over a month to fill 1GB
- if (dFreeCount >= GetArg("-limitfreerelay", 30) * 10 * 1000)
- return state.DoS(0, error("AcceptToMemoryPool : free transaction rejected by rate limiter"),
- REJECT_INSUFFICIENTFEE, "rate limited free transaction");
- LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount + nSize);
- dFreeCount += nSize;
- }
- }
-
if (fRejectInsaneFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000)
return error("AcceptToMemoryPool: : insane fees %s, %d > %d",
hash.ToString(),
@@ -1283,6 +1254,7 @@ bool AcceptableInputs(CTxMemPool& pool, CValidationState& state, const CTransact
if (pfMissingInputs)
*pfMissingInputs = false;
+
if (!CheckTransaction(tx, state))
return error("AcceptableInputs: : CheckTransaction failed");
@@ -1304,31 +1276,6 @@ bool AcceptableInputs(CTxMemPool& pool, CValidationState& state, const CTransact
if (pool.exists(hash))
return false;
- // ----------- swiftTX transaction scanning -----------
-
- BOOST_FOREACH (const CTxIn& in, tx.vin) {
- if (mapLockedInputs.count(in.prevout)) {
- if (mapLockedInputs[in.prevout] != tx.GetHash()) {
- return state.DoS(0,
- error("AcceptableInputs : conflicts with existing transaction lock: %s", reason),
- REJECT_INVALID, "tx-lock-conflict");
- }
- }
- }
-
- // Check for conflicts with in-memory transactions
- {
- LOCK(pool.cs); // protect pool.mapNextTx
- for (unsigned int i = 0; i < tx.vin.size(); i++) {
- COutPoint outpoint = tx.vin[i].prevout;
- if (pool.mapNextTx.count(outpoint)) {
- // Disable replacement feature for now
- return false;
- }
- }
- }
-
-
{
CCoinsView dummy;
CCoinsViewCache view(&dummy);
@@ -1468,16 +1415,30 @@ bool AcceptableInputs(CTxMemPool& pool, CValidationState& state, const CTransact
return true;
}
+bool GetOutput(const uint256& hash, unsigned int index, CValidationState& state, CTxOut& out)
+{
+ CTransaction txPrev;
+ uint256 hashBlock;
+ if (!GetTransaction(hash, txPrev, hashBlock, true)) {
+ return state.DoS(100, error("Output not found"));
+ }
+ if (index > txPrev.vout.size()) {
+ return state.DoS(100, error("Output not found, invalid index %d for %s",index, hash.GetHex()));
+ }
+ out = txPrev.vout[index];
+ return true;
+}
+
/** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */
-bool GetTransaction(const uint256& hash, CTransaction& txOut, uint256& hashBlock, bool fAllowSlow)
+bool GetTransaction(const uint256& hash, CTransaction& txOut, uint256& hashBlock, bool fAllowSlow, CBlockIndex* blockIndex)
{
- CBlockIndex* pindexSlow = NULL;
- {
- LOCK(cs_main);
- {
- if (mempool.lookup(hash, txOut)) {
- return true;
- }
+ CBlockIndex* pindexSlow = blockIndex;
+
+ LOCK(cs_main);
+
+ if (!blockIndex) {
+ if (mempool.lookup(hash, txOut)) {
+ return true;
}
if (fTxIndex) {
@@ -1520,7 +1481,7 @@ bool GetTransaction(const uint256& hash, CTransaction& txOut, uint256& hashBlock
if (pindexSlow) {
CBlock block;
if (ReadBlockFromDisk(block, pindexSlow)) {
- BOOST_FOREACH (const CTransaction& tx, block.vtx) {
+ for (const CTransaction& tx : block.vtx) {
if (tx.GetHash() == hash) {
txOut = tx;
hashBlock = pindexSlow->GetBlockHash();
@@ -1623,51 +1584,30 @@ CAmount GetBlockValue(int nHeight, uint32_t nTime)
} else if (nHeight <= Params().ANTI_INSTAMINE_TIME()) {
return 1 * COIN;
- // POS Year 1
- } else if (nHeight <= 1965600 && nHeight > Params().LAST_POW_BLOCK()) {
- return 57 * COIN;
- // POS Year 2
- } else if (nHeight <= 2491200 && nHeight >= 1965601) {
- return 53 * COIN;
- // POS Year 3
- } else if (nHeight <= 3016800 && nHeight >= 2491201) {
- return 49 * COIN;
- // POS Year 4
- } else if (nHeight <= 3542400 && nHeight >= 3016801) {
- return 45 * COIN;
- // POS Year 5
- } else if (nHeight <= 4068000 && nHeight >= 3542401) {
- return 41 * COIN;
- // POS Year 6
- } else if (nHeight <= 4593600 && nHeight >= 4068001) {
- return 37 * COIN;
- // POS Year 7
- } else if (nHeight <= 5119200 && nHeight >= 4593601) {
- return 33 * COIN;
- // POS Year 8
- } else if (nHeight <= 5644800 && nHeight >= 5119201) {
- return 29 * COIN;
- // POS Year 9
- } else if (nHeight <= 6170400 && nHeight >= 5644801) {
- return 25 * COIN;
- // POS Year 10
- } else if (nHeight <= 6696000 && nHeight >= 6170401) {
- return 21 * COIN;
- // POS Year 11
- } else if (nHeight <= 7221600 && nHeight >= 6696001) {
- return 17 * COIN;
- // POS Year 12
- } else if (nHeight <= 7747200 && nHeight >= 7221601) {
- return 13 * COIN;
- // POS Year 13
- } else if (nHeight <= 8272800 && nHeight >= 7747201) {
- return 9 * COIN;
- // POS Year 14
- } else if (nHeight <= 8798400 && nHeight >= 8272801) {
- return 5 * COIN;
- // POS Year 15
- } else if (nHeight >= 8798401) {
+ // POS Year 1 & 2
+ } else if (nHeight <= 1733700 && nHeight > Params().LAST_POW_BLOCK()) {
+ return 8 * COIN;
+ // POS Year 3 & 4
+ } else if (nHeight <= 2784900 && nHeight >= 1733701) {
+ return 4 * COIN;
+ // POS Year 5 & 6
+ } else if (nHeight <= 3836100 && nHeight >= 2784901) {
+ return 2 * COIN;
+ // POS Year 7 & 8
+ } else if (nHeight <= 4887300 && nHeight >= 3836101) {
return 1 * COIN;
+ // POS Year 9 & 10
+ } else if (nHeight <= 5938500 && nHeight >= 4887301) {
+ return 0.5 * COIN;
+ // POS Year 11 & 12
+ } else if (nHeight <= 6989700 && nHeight >= 5938501) {
+ return 0.25 * COIN;
+ // POS Year 12 & 13
+ } else if (nHeight <= 8040900 && nHeight >= 6989701) {
+ return 0.125 * COIN;
+ // POS Year 14
+ } else if (nHeight >= 8040901) {
+ return 0.0625 * COIN;
}
int64_t netHashRate = chainActive.GetNetworkHashPS(24, nHeight);
@@ -1684,8 +1624,10 @@ int64_t GetMasternodePayment(int nHeight, uint32_t nTime, unsigned mnlevel, int6
if(nTime <= Params().F2ActivationTime())
coeff = { 3, 9, 15 };
- else
+ else if (nTime > Params().F2ActivationTime() && (nHeight <= 682500))
coeff = { 5, 15, 25 };
+ else
+ coeff = { 10, 30, 50 };
if(mnlevel - 1 < coeff.size())
return blockValue / 100 * coeff[mnlevel - 1];
@@ -1695,17 +1637,28 @@ int64_t GetMasternodePayment(int nHeight, uint32_t nTime, unsigned mnlevel, int6
bool IsInitialBlockDownload()
{
+ const CChainParams& chainParams = Params();
+
+ // Once this function has returned false, it must remain false.
+ static std::atomic latchToFalse{false};
+ // Optimization: pre-test latch before taking the lock.
+ if (latchToFalse.load(std::memory_order_relaxed))
+ return false;
+
LOCK(cs_main);
- if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate())
- return true;
- static bool lockIBDState = false;
- if (lockIBDState)
+ if (latchToFalse.load(std::memory_order_relaxed))
return false;
- bool state = (chainActive.Height() < pindexBestHeader->nHeight - 24 * 6 ||
- pindexBestHeader->GetBlockTime() < GetTime() - 6 * 60 * 60); // ~144 blocks behind -> 2 x fork detection time
- if (!state)
- lockIBDState = true;
- return state;
+ if (fImporting || fReindex)
+ return true;
+ if (chainActive.Tip() == NULL)
+ return true;
+ if (chainActive.Height() < Checkpoints::GetTotalBlocksEstimate())
+ return true;
+ if (chainActive.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge))
+ return true;
+ latchToFalse.store(true, std::memory_order_relaxed);
+ return false;
+
}
bool fLargeWorkForkFound = false;
@@ -1839,7 +1792,7 @@ void UpdateCoins(const CTransaction& tx, CValidationState& state, CCoinsViewCach
// mark inputs spent
if (!tx.IsCoinBase()) {
txundo.vprevout.reserve(tx.vin.size());
- BOOST_FOREACH (const CTxIn& txin, tx.vin) {
+ for (const CTxIn& txin : tx.vin) {
txundo.vprevout.push_back(CTxInUndo());
bool ret = inputs.ModifyCoins(txin.prevout.hash)->Spend(txin.prevout, txundo.vprevout.back());
assert(ret);
@@ -1982,6 +1935,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
// undo transactions in reverse order
for (int i = block.vtx.size() - 1; i >= 0; i--) {
const CTransaction& tx = block.vtx[i];
+
uint256 hash = tx.GetHash();
// Check that all outputs are available and match the outputs in the block itself
@@ -2007,7 +1961,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
}
// restore inputs
- if (!tx.IsCoinBase()) { // not coinbases
+ if (!tx.IsCoinBase()) { // not coinbases because they dont have traditional inputs
const CTxUndo& txundo = blockUndo.vtxundo[i - 1];
if (txundo.vprevout.size() != tx.vin.size())
return error("DisconnectBlock() : transaction and undo data inconsistent - txundo.vprevout.siz=%d tx.vin.siz=%d", txundo.vprevout.size(), tx.vin.size());
@@ -2032,6 +1986,10 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
if (coins->vout.size() < out.n + 1)
coins->vout.resize(out.n + 1);
coins->vout[out.n] = undo.txout;
+
+ LOCK(cs_mapstake);
+ // erase the spent input
+ mapStakeSpent.erase(out);
}
}
}
@@ -2086,11 +2044,11 @@ static int64_t nTimeIndex = 0;
static int64_t nTimeCallbacks = 0;
static int64_t nTimeTotal = 0;
-bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck)
+bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck, bool fAlreadyChecked)
{
AssertLockHeld(cs_main);
// Check it again in case a previous version let a bad block in
- if (!CheckBlock(block, state, !fJustCheck, !fJustCheck))
+ if (!fAlreadyChecked && !CheckBlock(block, state, !fJustCheck, !fJustCheck))
return false;
// verify that the view's current state corresponds to the previous block
@@ -2110,9 +2068,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return state.DoS(100, error("ConnectBlock() : PoS period not active"),
REJECT_INVALID, "PoS-early");
- if (pindex->nHeight > Params().LAST_POW_BLOCK() && block.IsProofOfWork())
- return state.DoS(100, error("ConnectBlock() : PoW period ended"),
- REJECT_INVALID, "PoW-ended");
+ if (pindex->nHeight > Params().LAST_POW_BLOCK() && block.IsProofOfWork()) {
+ return state.DoS(100, error("ConnectBlock() : PoW period ended"), REJECT_INVALID, "PoW-ended");
+ }
bool fScriptChecks = pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate();
@@ -2141,8 +2099,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
// DERSIG (BIP66) rules
flags |= SCRIPT_VERIFY_DERSIG;
- CBlockUndo blockundo;
-
CCheckQueueControl control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
int64_t nTimeStart = GetTimeMicros();
@@ -2152,6 +2108,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
std::vector > vPos;
vPos.reserve(block.vtx.size());
+ CBlockUndo blockundo;
blockundo.vtxundo.reserve(block.vtx.size() - 1);
CAmount nValueOut = 0;
CAmount nValueIn = 0;
@@ -2202,7 +2159,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
// ppcoin: track money supply and mint amount info
CAmount nMoneySupplyPrev = pindex->pprev ? pindex->pprev->nMoneySupply : 0;
pindex->nMoneySupply = nMoneySupplyPrev + nValueOut - nValueIn;
- pindex->nMint = pindex->nMoneySupply - nMoneySupplyPrev;
+ pindex->nMint = pindex->nMoneySupply - nMoneySupplyPrev + nFees;
if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex)))
return error("Connect() : WriteBlockIndex for pindex failed");
@@ -2216,6 +2173,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (block.IsProofOfWork())
nExpectedMint += nFees;
+ //Check that the block does not overmint
if (!IsBlockValueValid(block, nExpectedMint, pindex->nMint)) {
return state.DoS(100,
error("ConnectBlock() : reward pays too much (actual=%s vs limit=%s)",
@@ -2224,7 +2182,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
}
if (!control.Wait())
- return state.DoS(100, false);
+ return state.DoS(100, error("%s: CheckQueue failed", __func__), REJECT_INVALID, "block-validation-failed");
int64_t nTime2 = GetTimeMicros();
nTimeVerify += nTime2 - nTimeStart;
LogPrint("bench", " - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs]\n", nInputs - 1, 0.001 * (nTime2 - nTimeStart), nInputs <= 1 ? 0 : 0.001 * (nTime2 - nTimeStart) / (nInputs - 1), nTimeVerify * 0.000001);
@@ -2254,6 +2212,29 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (!pblocktree->WriteTxIndex(vPos))
return state.Abort("Failed to write transaction index");
+ {
+ LOCK(cs_mapstake);
+ // add new entries
+ for (const CTransaction& tx : block.vtx) {
+ if (tx.IsCoinBase())
+ continue;
+ for (const CTxIn& in: tx.vin) {
+ if (fDebug) LogPrintf("mapStakeSpent: Insert %s | %u\n", in.prevout.ToString(), pindex->nHeight);
+ mapStakeSpent.insert(std::make_pair(in.prevout, pindex->nHeight));
+ }
+ }
+
+ // delete old entries
+ for (auto it = mapStakeSpent.begin(); it != mapStakeSpent.end();) {
+ if (it->second < pindex->nHeight - Params().MaxReorganizationDepth()) {
+ if (fDebug) LogPrintf("mapStakeSpent: Erase %s | %u\n", it->first.ToString(), it->second);
+ it = mapStakeSpent.erase(it);
+ }
+ else {
+ it++;
+ }
+ }
+ }
// add this block to the view's block chain
view.SetBestBlock(pindex->GetBlockHash());
@@ -2263,7 +2244,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
// Watch for changes to the previous coinbase transaction.
static uint256 hashPrevBestCoinBase;
- g_signals.UpdatedTransaction(hashPrevBestCoinBase);
+ GetMainSignals().UpdatedTransaction(hashPrevBestCoinBase);
hashPrevBestCoinBase = block.vtx[0].GetHash();
int64_t nTime4 = GetTimeMicros();
@@ -2325,7 +2306,7 @@ bool static FlushStateToDisk(CValidationState& state, FlushStateMode mode)
return state.Abort("Failed to write to coin database");
// Update best block in wallet (so we can detect restored wallets).
if (mode != FLUSH_STATE_IF_NEEDED) {
- g_signals.SetBestChain(chainActive.GetLocator());
+ GetMainSignals().SetBestChain(chainActive.GetLocator());
}
nLastWrite = GetTimeMicros();
}
@@ -2350,8 +2331,8 @@ void static UpdateTip(CBlockIndex* pindexNew)
nTimeBestReceived = GetTime();
mempool.AddTransactionsUpdated(1);
- LogPrintf("UpdateTip: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f cache=%u\n",
- chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), log(chainActive.Tip()->nChainWork.getdouble()) / log(2.0), (unsigned long)chainActive.Tip()->nChainTx,
+ LogPrintf("UpdateTip: new best=%s height=%d version=%d log2_work=%.8g tx=%lu date=%s progress=%f cache=%u\n",
+ chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nVersion, log(chainActive.Tip()->nChainWork.getdouble()) / log(2.0), (unsigned long)chainActive.Tip()->nChainTx,
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
Checkpoints::GuessVerificationProgress(chainActive.Tip()), (unsigned int)pcoinsTip->GetCacheSize());
@@ -2401,7 +2382,7 @@ bool static DisconnectTip(CValidationState& state)
if (!FlushStateToDisk(state, FLUSH_STATE_ALWAYS))
return false;
// Resurrect mempool transactions from the disconnected block.
- BOOST_FOREACH (const CTransaction& tx, block.vtx) {
+ for (const CTransaction& tx : block.vtx) {
// ignore validation errors in resurrected transactions
list removed;
CValidationState stateDummy;
@@ -2414,7 +2395,7 @@ bool static DisconnectTip(CValidationState& state)
UpdateTip(pindexDelete->pprev);
// Let wallets know transactions went from 1-confirmed to
// 0-confirmed or conflicted:
- BOOST_FOREACH (const CTransaction& tx, block.vtx) {
+ for (const CTransaction& tx : block.vtx) {
SyncWithWallets(tx, NULL);
}
return true;
@@ -2430,12 +2411,15 @@ static int64_t nTimePostConnect = 0;
* Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
* corresponding to pindexNew, to bypass loading it again from disk.
*/
-bool static ConnectTip(CValidationState& state, CBlockIndex* pindexNew, CBlock* pblock)
+bool static ConnectTip(CValidationState& state, CBlockIndex* pindexNew, CBlock* pblock, bool fAlreadyChecked)
{
assert(pindexNew->pprev == chainActive.Tip());
mempool.check(pcoinsTip);
CCoinsViewCache view(pcoinsTip);
+ if (pblock == NULL)
+ fAlreadyChecked = false;
+
// Read block from disk.
int64_t nTime1 = GetTimeMicros();
CBlock block;
@@ -2451,8 +2435,8 @@ bool static ConnectTip(CValidationState& state, CBlockIndex* pindexNew, CBlock*
LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001);
{
CInv inv(MSG_BLOCK, pindexNew->GetBlockHash());
- bool rv = ConnectBlock(*pblock, state, pindexNew, view);
- g_signals.BlockChecked(*pblock, state);
+ bool rv = ConnectBlock(*pblock, state, pindexNew, view, false, fAlreadyChecked);
+ GetMainSignals().BlockChecked(*pblock, state);
if (!rv) {
if (state.IsInvalid())
InvalidBlockFound(pindexNew, state);
@@ -2486,11 +2470,11 @@ bool static ConnectTip(CValidationState& state, CBlockIndex* pindexNew, CBlock*
UpdateTip(pindexNew);
// Tell wallet about transactions that went from mempool
// to conflicted:
- BOOST_FOREACH (const CTransaction& tx, txConflicted) {
+ for (const CTransaction& tx : txConflicted) {
SyncWithWallets(tx, NULL);
}
// ... and about transactions that got confirmed:
- BOOST_FOREACH (const CTransaction& tx, pblock->vtx) {
+ for (const CTransaction& tx : pblock->vtx) {
SyncWithWallets(tx, pblock);
}
@@ -2552,10 +2536,10 @@ bool DisconnectBlockAndInputs(CValidationState& state, CTransaction txLock)
// Queue memory transactions to resurrect.
// We only do this for blocks after the last checkpoint (reorganisation before that
// point should only happen with -reindex/-loadblock, or a misbehaving peer.
- BOOST_FOREACH (const CTransaction& tx, block.vtx) {
+ for (const CTransaction& tx : block.vtx) {
if (!tx.IsCoinBase()) {
- BOOST_FOREACH (const CTxIn& in1, txLock.vin) {
- BOOST_FOREACH (const CTxIn& in2, tx.vin) {
+ for (const CTxIn& in1 : txLock.vin) {
+ for (const CTxIn& in2 : tx.vin) {
if (in1.prevout == in2.prevout) foundConflictingTx = true;
}
}
@@ -2576,7 +2560,7 @@ bool DisconnectBlockAndInputs(CValidationState& state, CTransaction txLock)
if (vDisconnect.size() > 0) {
LogPrintf("REORGANIZE: Disconnect Conflicting Blocks %lli blocks; %s..\n", vDisconnect.size(), pindexNew->GetBlockHash().ToString());
- BOOST_FOREACH (CBlockIndex* pindex, vDisconnect) {
+ for (CBlockIndex* pindex : vDisconnect) {
LogPrintf(" -- disconnect %s\n", pindex->GetBlockHash().ToString());
DisconnectTip(state);
}
@@ -2662,9 +2646,11 @@ static void PruneBlockIndexCandidates()
* Try to make some progress towards making pindexMostWork the active block.
* pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
*/
-static bool ActivateBestChainStep(CValidationState& state, CBlockIndex* pindexMostWork, CBlock* pblock)
+static bool ActivateBestChainStep(CValidationState& state, CBlockIndex* pindexMostWork, CBlock* pblock, bool fAlreadyChecked)
{
AssertLockHeld(cs_main);
+ if (pblock == NULL)
+ fAlreadyChecked = false;
bool fInvalidFound = false;
const CBlockIndex* pindexOldTip = chainActive.Tip();
const CBlockIndex* pindexFork = chainActive.FindFork(pindexMostWork);
@@ -2694,7 +2680,7 @@ static bool ActivateBestChainStep(CValidationState& state, CBlockIndex* pindexMo
// Connect new blocks.
BOOST_REVERSE_FOREACH (CBlockIndex* pindexConnect, vpindexToConnect) {
- if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) {
+ if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL, fAlreadyChecked)) {
if (state.IsInvalid()) {
// The block violates a consensus rule.
if (!state.CorruptionPossible())
@@ -2732,7 +2718,7 @@ static bool ActivateBestChainStep(CValidationState& state, CBlockIndex* pindexMo
* or an activated best chain. pblock is either NULL or a pointer to a block
* that is already loaded (to avoid loading it again from disk).
*/
-bool ActivateBestChain(CValidationState& state, CBlock* pblock)
+bool ActivateBestChain(CValidationState& state, CBlock* pblock, bool fAlreadyChecked)
{
CBlockIndex* pindexNewTip = NULL;
CBlockIndex* pindexMostWork = NULL;
@@ -2753,7 +2739,7 @@ bool ActivateBestChain(CValidationState& state, CBlock* pblock)
if (pindexMostWork == NULL || pindexMostWork == chainActive.Tip())
return true;
- if (!ActivateBestChainStep(state, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL))
+ if (!ActivateBestChainStep(state, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : NULL, fAlreadyChecked))
return false;
pindexNewTip = chainActive.Tip();
@@ -2769,12 +2755,22 @@ bool ActivateBestChain(CValidationState& state, CBlock* pblock)
int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate();
{
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes)
+ for (CNode* pnode : vNodes)
if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
pnode->PushInventory(CInv(MSG_BLOCK, hashNewTip));
}
// Notify external listeners about the new tip.
+ // Note: uiInterface, should switch main signals.
uiInterface.NotifyBlockTip(hashNewTip);
+ GetMainSignals().UpdatedBlockTip(pindexNewTip);
+
+ unsigned size = 0;
+ if (pblock)
+ size = GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION);
+ // If the size is over 1 MB notify external listeners, and it is within the last 5 minutes
+ if (size > MAX_BLOCK_SIZE && pblock->GetBlockTime() > GetAdjustedTime() - 300) {
+ uiInterface.NotifyBlockSize(static_cast(size), hashNewTip);
+ }
}
} while (pindexMostWork != chainActive.Tip());
CheckBlockIndex();
@@ -2909,7 +2905,7 @@ CBlockIndex* AddToBlockIndex(const CBlock& block)
pindexNew->SetStakeModifier(nStakeModifier, fGeneratedStakeModifier);
pindexNew->nStakeModifierChecksum = GetStakeModifierChecksum(pindexNew);
if (!CheckStakeModifierCheckpoints(pindexNew->nHeight, pindexNew->nStakeModifierChecksum))
- LogPrintf("AddToBlockIndex() : Rejected by stake modifier checkpoint height=%d, modifier=%s \n", pindexNew->nHeight, boost::lexical_cast(nStakeModifier));
+ LogPrintf("AddToBlockIndex() : Rejected by stake modifier checkpoint height=%d, modifier=%s \n", pindexNew->nHeight, std::to_string(nStakeModifier));
}
pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew);
pindexNew->RaiseValidity(BLOCK_VALID_TREE);
@@ -3097,7 +3093,8 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
// because we receive the wrong transactions for it.
// Size limits
- if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
+ unsigned int nMaxBlockSize = MAX_BLOCK_SIZE;
+ if (block.vtx.empty() || block.vtx.size() > nMaxBlockSize || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > nMaxBlockSize)
return state.DoS(100, error("CheckBlock() : size limits failed"),
REJECT_INVALID, "bad-blk-length");
@@ -3169,31 +3166,10 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
}
}
- // ----------- swiftTX transaction scanning -----------
- if (IsSporkActive(SPORK_2_SWIFTTX_BLOCK_FILTERING)) {
- BOOST_FOREACH (const CTransaction& tx, block.vtx) {
- if (!tx.IsCoinBase()) {
- //only reject blocks when it's based on complete consensus
- BOOST_FOREACH (const CTxIn& in, tx.vin) {
- if (mapLockedInputs.count(in.prevout)) {
- if (mapLockedInputs[in.prevout] != tx.GetHash()) {
- mapRejectedBlocks.insert(make_pair(block.GetHash(), GetTime()));
- LogPrintf("CheckBlock() : found conflicting transaction with transaction lock %s %s\n", mapLockedInputs[in.prevout].ToString(), tx.GetHash().ToString());
- return state.DoS(0, error("CheckBlock() : found conflicting transaction with transaction lock"),
- REJECT_INVALID, "conflicting-tx-ix");
- }
- }
- }
- }
- }
- } else {
- LogPrintf("CheckBlock() : skipping transaction locking checks\n");
- }
-
// masternode payments
CBlockIndex* pindexPrev = chainActive.Tip();
+ int nHeight = 0;
if (pindexPrev != NULL) {
- int nHeight = 0;
if (pindexPrev->GetBlockHash() == block.hashPrevBlock) {
nHeight = pindexPrev->nHeight + 1;
} else { //out of order
@@ -3221,14 +3197,16 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
}
// Check transactions
- BOOST_FOREACH (const CTransaction& tx, block.vtx)
+ for (const CTransaction& tx : block.vtx)
if (!CheckTransaction(tx, state))
return error("CheckBlock() : CheckTransaction failed");
unsigned int nSigOps = 0;
- BOOST_FOREACH (const CTransaction& tx, block.vtx) {
+ for (const CTransaction& tx : block.vtx) {
nSigOps += GetLegacySigOpCount(tx);
}
+
+ unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE / 50;
if (nSigOps > MAX_BLOCK_SIGOPS)
return state.DoS(100, error("CheckBlock() : out-of-bounds SigOpCount"),
REJECT_INVALID, "bad-blk-sigops", true);
@@ -3250,11 +3228,11 @@ bool CheckWork(const CBlock block, CBlockIndex* const pindexPrev)
uint256 hashProofOfStake;
uint256 hash = block.GetHash();
- if (!CheckProofOfStake(block, hashProofOfStake)) {
+ if(!CheckProofOfStake(block, hashProofOfStake)) {
LogPrintf("WARNING: ProcessBlock(): check proof-of-stake failed for block %s\n", hash.ToString().c_str());
return false;
}
- if (!mapProofOfStake.count(hash)) // add to mapProofOfStake
+ if(!mapProofOfStake.count(hash)) // add to mapProofOfStake
mapProofOfStake.insert(make_pair(hash, hashProofOfStake));
}
@@ -3273,8 +3251,9 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
int nHeight = pindexPrev->nHeight + 1;
//If this is a reorg, check that it is not too deep
- if (chainActive.Height() - nHeight >= Params().MaxReorganizationDepth())
- return state.DoS(1, error("%s: forked chain older than max reorganization depth (height %d)", __func__, nHeight));
+ int nMaxReorgDepth = GetArg("-maxreorg", Params().MaxReorganizationDepth());
+ if (chainActive.Height() - nHeight >= nMaxReorgDepth)
+ return state.DoS(1, error("%s: forked chain older than max reorganization depth (height %d)", __func__, chainActive.Height() - nHeight));
// Check timestamp against prev
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast()) {
@@ -3315,11 +3294,11 @@ bool IsBlockHashInChain(const uint256& hashBlock)
return chainActive.Contains(mapBlockIndex[hashBlock]);
}
-bool IsTransactionInChain(uint256 txId, int& nHeightTx)
+bool IsTransactionInChain(const uint256& txId, int& nHeightTx, CTransaction& tx)
{
uint256 hashBlock;
- CTransaction tx;
- GetTransaction(txId, tx, hashBlock, true);
+ if (!GetTransaction(txId, tx, hashBlock, true))
+ return false;
if (!IsBlockHashInChain(hashBlock))
return false;
@@ -3327,6 +3306,12 @@ bool IsTransactionInChain(uint256 txId, int& nHeightTx)
return true;
}
+bool IsTransactionInChain(const uint256& txId, int& nHeightTx)
+{
+ CTransaction tx;
+ return IsTransactionInChain(txId, nHeightTx, tx);
+}
+
bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex* const pindexPrev)
{
const int nHeight = !pindexPrev ? 0 : pindexPrev->nHeight + 1;
@@ -3417,7 +3402,7 @@ bool AcceptBlockHeader(const CBlock& block, CValidationState& state, CBlockIndex
return true;
}
-bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, CDiskBlockPos* dbp)
+bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, CDiskBlockPos* dbp, bool fAlreadyCheckedBlock)
{
AssertLockHeld(cs_main);
@@ -3449,16 +3434,26 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
if (block.GetHash() != Params().HashGenesisBlock() && !CheckWork(block, pindexPrev))
return false;
+ bool isPoS = false;
+ if (block.IsProofOfStake()) {
+ isPoS = true;
+ uint256 hashProofOfStake = 0;
+ uint256 hash = block.GetHash();
+ if(!mapProofOfStake.count(hash)) // add to mapProofOfStake
+ mapProofOfStake.insert(make_pair(hash, hashProofOfStake));
+ }
+
if (!AcceptBlockHeader(block, state, &pindex))
return false;
if (pindex->nStatus & BLOCK_HAVE_DATA) {
// TODO: deal better with duplicate blocks.
// return state.DoS(20, error("AcceptBlock() : already have block %d %s", pindex->nHeight, pindex->GetBlockHash().ToString()), REJECT_DUPLICATE, "duplicate");
+ LogPrintf("AcceptBlock() : already have block %d %s", pindex->nHeight, pindex->GetBlockHash().ToString());
return true;
}
- if ((!CheckBlock(block, state)) || !ContextualCheckBlock(block, state, pindex->pprev)) {
+ if ((!fAlreadyCheckedBlock && !CheckBlock(block, state)) || !ContextualCheckBlock(block, state, pindex->pprev)) {
if (state.IsInvalid() && !state.CorruptionPossible()) {
pindex->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(pindex);
@@ -3467,6 +3462,111 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex,
}
int nHeight = pindex->nHeight;
+ int splitHeight = -1;
+
+ if (isPoS) {
+ LOCK(cs_main);
+
+ CCoinsViewCache coins(pcoinsTip);
+
+ if (!coins.HaveInputs(block.vtx[1])) {
+
+ LOCK(cs_mapstake);
+
+ // the inputs are spent at the chain tip so we should look at the recently spent outputs
+ for (CTxIn in : block.vtx[1].vin) {
+ auto it = mapStakeSpent.find(in.prevout);
+ if (it == mapStakeSpent.end()) {
+ return false;
+ }
+ if (it->second < pindexPrev->nHeight) {
+ return false;
+ }
+ }
+ }
+
+ // Blocks arrives in order, so if prev block is not the tip then we are on a fork.
+ // Extra info: duplicated blocks are skipping this checks, so we don't have to worry about those here.
+ bool isBlockFromFork = pindexPrev != nullptr && chainActive.Tip() != pindexPrev;
+
+ // Coin stake
+ CTransaction &stakeTxIn = block.vtx[1];
+
+ // Inputs
+ std::vector lnoInputs;
+
+ for (const CTxIn& stakeIn : stakeTxIn.vin) {
+ lnoInputs.push_back(stakeIn);
+ }
+ const bool hasLNOInputs = !lnoInputs.empty();
+ // Check for serial double spent on the same block, TODO: Move this to the proper method..
+
+ for (const CTransaction& tx : block.vtx) {
+ for (const CTxIn& in: tx.vin) {
+
+ if(tx.IsCoinStake()) continue;
+ if(hasLNOInputs)
+ // Check if coinstake input is double spent inside the same block
+ for (const CTxIn& pivIn : lnoInputs){
+ if(pivIn.prevout == in.prevout){
+ // double spent coinstake input inside block
+ return error("%s: double spent coinstake input inside block", __func__);
+ }
+ }
+ }
+ }
+
+ // Check whether is a fork or not
+ if (isBlockFromFork) {
+
+ // Start at the block we're adding on to
+ CBlockIndex *prev = pindexPrev;
+
+ CBlock bl;
+ if (!ReadBlockFromDisk(bl, prev))
+ return error("%s: previous block %s not on disk", __func__, prev->GetBlockHash().GetHex());
+
+ int readBlock = 0;
+ // Go backwards on the forked chain up to the split
+ while (!chainActive.Contains(prev)) {
+
+ // Increase amount of read blocks
+ readBlock++;
+ // Check if the forked chain is longer than the max reorg limit
+ if (readBlock == Params().MaxReorganizationDepth()) {
+ // TODO: Remove this chain from disk.
+ return error("%s: forked chain longer than maximum reorg limit", __func__);
+ }
+
+ // Loop through every input from said block
+ for (const CTransaction &t : bl.vtx) {
+ for (const CTxIn &in: t.vin) {
+ // Loop through every input of the staking tx
+ for (const CTxIn &stakeIn : lnoInputs) {
+ // if it's already spent
+
+ // First regular staking check
+ if (hasLNOInputs) {
+ if (stakeIn.prevout == in.prevout) {
+ return state.DoS(100, error("%s: input already spent on a previous block",
+ __func__));
+ }
+
+ }
+ }
+ }
+ }
+
+ // Prev block
+ prev = prev->pprev;
+ if (!ReadBlockFromDisk(bl, prev))
+ // Previous block not on disk
+ return error("%s: previous block %s not on disk", __func__, prev->GetBlockHash().GetHex());
+
+ }
+ }
+
+ }
// Write block to history file
try {
@@ -3555,13 +3655,6 @@ bool ProcessNewBlock(CValidationState& state, CNode* pfrom, CBlock* pblock, CDis
int64_t nStartTime = GetTimeMillis();
bool checked = CheckBlock(*pblock, state);
- // ppcoin: check proof-of-stake
- // Limited duplicity on stake: prevents block flood attack
- // Duplicate stake allowed only when there is orphan child block
- //if (pblock->IsProofOfStake() && setStakeSeen.count(pblock->GetProofOfStake())/* && !mapOrphanBlocksByPrev.count(hash)*/)
- // return error("ProcessNewBlock() : duplicate proof-of-stake (%s, %d) for block %s", pblock->GetProofOfStake().first.ToString().c_str(), pblock->GetProofOfStake().second, pblock->GetHash().ToString().c_str());
-
- // NovaCoin: check proof-of-stake block signature
if (!pblock->CheckBlockSignature())
return error("ProcessNewBlock() : bad proof-of-stake block signature");
@@ -3575,25 +3668,44 @@ bool ProcessNewBlock(CValidationState& state, CNode* pfrom, CBlock* pblock, CDis
}
{
- LOCK(cs_main); // Replaces the former TRY_LOCK loop because busy waiting wastes too much resources
+ LOCK(cs_main); // Replaces the former TRY_LOCK loop because busy waiting wastes too much resources
- MarkBlockAsReceived(pblock->GetHash());
+ MarkBlockAsReceived (pblock->GetHash ());
if (!checked) {
- return error("%s : CheckBlock FAILED for block %s", __func__, pblock->GetHash().GetHex());
+ return error ("%s : CheckBlock FAILED for block %s", __func__, pblock->GetHash().GetHex());
}
// Store to disk
- CBlockIndex* pindex = NULL;
- bool ret = AcceptBlock(*pblock, state, &pindex, dbp);
+ CBlockIndex* pindex = nullptr;
+ bool ret = AcceptBlock (*pblock, state, &pindex, dbp, checked);
if (pindex && pfrom) {
- mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId();
- }
- CheckBlockIndex();
- if (!ret)
+ mapBlockSource[pindex->GetBlockHash ()] = pfrom->GetId ();
+ }
+ CheckBlockIndex ();
+ if (!ret) {
+ // Check spamming
+ if(pindex && pfrom && GetBoolArg("-blockspamfilter", DEFAULT_BLOCK_SPAM_FILTER)) {
+ CNodeState *nodestate = State(pfrom->GetId());
+ if(nodestate != nullptr) {
+ nodestate->nodeBlocks.onBlockReceived(pindex->nHeight);
+ bool nodeStatus = true;
+ // UpdateState will return false if the node is attacking us or update the score and return true.
+ nodeStatus = nodestate->nodeBlocks.updateState(state, nodeStatus);
+ int nDoS = 0;
+ if (state.IsInvalid(nDoS)) {
+ if (nDoS > 0)
+ Misbehaving(pfrom->GetId(), nDoS);
+ nodeStatus = false;
+ }
+ if (!nodeStatus)
+ return error("%s : AcceptBlock FAILED - block spam protection", __func__);
+ }
+ }
return error("%s : AcceptBlock FAILED", __func__);
+ }
}
- if (!ActivateBestChain(state, pblock))
+ if (!ActivateBestChain(state, pblock, checked))
return error("%s : ActivateBestChain failed", __func__);
if (!fLiteMode) {
@@ -3613,8 +3725,8 @@ bool ProcessNewBlock(CValidationState& state, CNode* pfrom, CBlock* pblock, CDis
pwalletMain->AutoCombineDust();
}
- LogPrintf("%s : ACCEPTED in %ld milliseconds with size=%d\n", __func__, GetTimeMillis() - nStartTime,
- pblock->GetSerializeSize(SER_DISK, CLIENT_VERSION));
+ LogPrintf("%s : ACCEPTED Block %ld in %ld milliseconds with size=%d\n", __func__, GetHeight(), GetTimeMillis() - nStartTime,
+ pblock->GetSerializeSize(SER_DISK, CLIENT_VERSION));
return true;
}
@@ -3622,7 +3734,11 @@ bool ProcessNewBlock(CValidationState& state, CNode* pfrom, CBlock* pblock, CDis
bool TestBlockValidity(CValidationState& state, const CBlock& block, CBlockIndex* const pindexPrev, bool fCheckPOW, bool fCheckMerkleRoot)
{
AssertLockHeld(cs_main);
- assert(pindexPrev == chainActive.Tip());
+ assert(pindexPrev);
+ if (pindexPrev != chainActive.Tip()) {
+ LogPrintf("%s : No longer working on chain tip\n", __func__);
+ return false;
+ }
CCoinsViewCache viewNew(pcoinsTip);
CBlockIndex indexDummy(block);
@@ -3733,7 +3849,7 @@ CBlockIndex* InsertBlockIndex(uint256 hash)
return pindexNew;
}
-bool static LoadBlockIndexDB()
+bool static LoadBlockIndexDB(string& strError)
{
if (!pblocktree->LoadBlockIndexGuts())
return false;
@@ -3743,12 +3859,12 @@ bool static LoadBlockIndexDB()
// Calculate nChainWork
vector > vSortedByHeight;
vSortedByHeight.reserve(mapBlockIndex.size());
- for (const PAIRTYPE(uint256, CBlockIndex*) & item : mapBlockIndex) {
+ for (const std::pair& item : mapBlockIndex) {
CBlockIndex* pindex = item.second;
vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex));
}
sort(vSortedByHeight.begin(), vSortedByHeight.end());
- BOOST_FOREACH (const PAIRTYPE(int, CBlockIndex*) & item, vSortedByHeight) {
+ for (const PAIRTYPE(int, CBlockIndex*) & item : vSortedByHeight) {
CBlockIndex* pindex = item.second;
pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex);
if (pindex->nStatus & BLOCK_HAVE_DATA) {
@@ -3793,7 +3909,7 @@ bool static LoadBlockIndexDB()
// Check presence of blk files
LogPrintf("Checking all blk files are present...\n");
set setBlkDataFiles;
- for (const PAIRTYPE(uint256, CBlockIndex*) & item : mapBlockIndex) {
+ for (const std::pair& item : mapBlockIndex) {
CBlockIndex* pindex = item.second;
if (pindex->nStatus & BLOCK_HAVE_DATA) {
setBlkDataFiles.insert(pindex->nFile);
@@ -3812,83 +3928,69 @@ bool static LoadBlockIndexDB()
LogPrintf("%s: Last shutdown was prepared: %s\n", __func__, fLastShutdownWasPrepared);
//Check for inconsistency with block file info and internal state
- if (!fLastShutdownWasPrepared && !GetBoolArg("-forcestart", false) && !GetBoolArg("-reindex", false) && (vSortedByHeight.size() != vinfoBlockFile[nLastBlockFile].nHeightLast + 1) && (vinfoBlockFile[nLastBlockFile].nHeightLast != 0)) {
- //The database is in a state where a block has been accepted and written to disk, but not
- //all of the block has perculated through the code. The block and the index should both be
- //intact (although assertions are added if they are not), and the block will be reprocessed
- //to ensure all data will be accounted for.
- LogPrintf("%s: Inconsistent State Detected mapBlockIndex.size()=%d blockFileBlocks=%d\n", __func__, vSortedByHeight.size(), vinfoBlockFile[nLastBlockFile].nHeightLast + 1);
- LogPrintf("%s: lastIndexPos=%d blockFileSize=%d\n", __func__, vSortedByHeight[vSortedByHeight.size() - 1].second->GetBlockPos().nPos,
- vinfoBlockFile[nLastBlockFile].nSize);
-
- //try reading the block from the last index we have
- bool isFixed = true;
- string strError = "";
- LogPrintf("%s: Attempting to re-add last block that was recorded to disk\n", __func__);
-
- //get the last block that was properly recorded to the block info file
- CBlockIndex* pindexLastMeta = vSortedByHeight[vinfoBlockFile[nLastBlockFile].nHeightLast + 1].second;
-
- //fix Assertion `hashPrevBlock == view.GetBestBlock()' failed. By adjusting height to the last recorded by coinsview
- CBlockIndex* pindexCoinsView = mapBlockIndex[pcoinsTip->GetBestBlock()];
- for(unsigned int i = vinfoBlockFile[nLastBlockFile].nHeightLast + 1; i < vSortedByHeight.size(); i++)
- {
- pindexLastMeta = vSortedByHeight[i].second;
- if(pindexLastMeta->nHeight > pindexCoinsView->nHeight)
- break;
- }
-
- LogPrintf("%s: Last block properly recorded: #%d %s\n", __func__, pindexLastMeta->nHeight, pindexLastMeta->GetBlockHash().ToString().c_str());
-
- CBlock lastMetaBlock;
- if (!ReadBlockFromDisk(lastMetaBlock, pindexLastMeta)) {
- isFixed = false;
- strError = strprintf("failed to read block %d from disk", pindexLastMeta->nHeight);
- }
+ if (!fLastShutdownWasPrepared && !GetBoolArg("-forcestart", false) && !GetBoolArg("-reindex", false)) {
+ unsigned int nHeightLastBlockFile = vinfoBlockFile[nLastBlockFile].nHeightLast + 1;
+ if (vSortedByHeight.size() > nHeightLastBlockFile && pcoinsTip->GetBestBlock() != vSortedByHeight[nHeightLastBlockFile].second->GetBlockHash()) {
+ //The database is in a state where a block has been accepted and written to disk, but the
+ //transaction database (pcoinsTip) was not flushed to disk, and is therefore not in sync with
+ //the block index database.
+
+ if (!mapBlockIndex.count(pcoinsTip->GetBestBlock())) {
+ strError = "The wallet has been not been closed gracefully, causing the transaction database to be out of sync with the block database";
+ return false;
+ }
+ LogPrintf("%s : pcoinstip synced to block height %d, block index height %d\n", __func__,
+ mapBlockIndex[pcoinsTip->GetBestBlock()]->nHeight, vSortedByHeight.size());
+
+ //get the index associated with the point in the chain that pcoinsTip is synced to
+ CBlockIndex* pindexLastMeta = vSortedByHeight[vinfoBlockFile[nLastBlockFile].nHeightLast + 1].second;
+ CBlockIndex* pindex = vSortedByHeight[0].second;
+ unsigned int nSortedPos = 0;
+ for (unsigned int i = 0; i < vSortedByHeight.size(); i++) {
+ nSortedPos = i;
+ if (vSortedByHeight[i].first == mapBlockIndex[pcoinsTip->GetBestBlock()]->nHeight + 1) {
+ pindex = vSortedByHeight[i].second;
+ break;
+ }
+ }
- //set the chain to the block before lastMeta so that the meta block will be seen as new
- chainActive.SetTip(pindexLastMeta->pprev);
+ // Start at the last block that was successfully added to the txdb (pcoinsTip) and manually add all transactions that occurred for each block up until
+ // the best known block from the block index db.
+ CCoinsViewCache view(pcoinsTip);
+ while (nSortedPos < vSortedByHeight.size()) {
+ CBlock block;
+ if (!ReadBlockFromDisk(block, pindex)) {
+ strError = "The wallet has been not been closed gracefully and has caused corruption of blocks stored to disk. Data directory is in an unusable state";
+ return false;
+ }
- //Process the lastMetaBlock again, using the known location on disk
- CDiskBlockPos blockPos = pindexLastMeta->GetBlockPos();
- CValidationState state;
- ProcessNewBlock(state, NULL, &lastMetaBlock, &blockPos);
+ vector vtxundo;
+ vtxundo.reserve(block.vtx.size() - 1);
+ uint256 hashBlock = block.GetHash();
+ for (unsigned int i = 0; i < block.vtx.size(); i++) {
+ CValidationState state;
+ CTxUndo undoDummy;
+ if (i > 0)
+ vtxundo.push_back(CTxUndo());
+ UpdateCoins(block.vtx[i], state, view, i == 0 ? undoDummy : vtxundo.back(), pindex->nHeight);
+ view.SetBestBlock(hashBlock);
+ }
- //ensure that everything is as it should be
- if (pcoinsTip->GetBestBlock() != vSortedByHeight[vSortedByHeight.size() - 1].second->GetBlockHash()) {
- isFixed = false;
- strError = "pcoinsTip best block is not correct";
- }
+ if (pindex->nHeight >= pindexLastMeta->nHeight)
+ break;
- //properly account for all of the blocks that were not in the meta data. If this is not done the file
- //positioning will be wrong and blocks will be overwritten and later cause serialization errors
- CBlockIndex *pindexLast = vSortedByHeight[vSortedByHeight.size() - 1].second;
- CBlock lastBlock;
- if (!ReadBlockFromDisk(lastBlock, pindexLast)) {
- isFixed = false;
- strError = strprintf("failed to read block %d from disk", pindexLast->nHeight);
- }
- vinfoBlockFile[nLastBlockFile].nHeightLast = pindexLast->nHeight;
- vinfoBlockFile[nLastBlockFile].nSize = pindexLast->GetBlockPos().nPos + ::GetSerializeSize(lastBlock, SER_DISK, CLIENT_VERSION);;
- setDirtyFileInfo.insert(nLastBlockFile);
- FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
+ pindex = vSortedByHeight[++nSortedPos].second;
+ }
- //Print out file info again
- pblocktree->ReadLastBlockFile(nLastBlockFile);
- vinfoBlockFile.resize(nLastBlockFile + 1);
- LogPrintf("%s: last block file = %i\n", __func__, nLastBlockFile);
- for (int nFile = 0; nFile <= nLastBlockFile; nFile++) {
- pblocktree->ReadBlockFileInfo(nFile, vinfoBlockFile[nFile]);
- }
- LogPrintf("%s: last block file info: %s\n", __func__, vinfoBlockFile[nLastBlockFile].ToString());
+ // Save the updates to disk
+ if (!view.Flush() || !pcoinsTip->Flush())
+ LogPrintf("%s : failed to flush view\n", __func__);
- if (!isFixed) {
- strError = "Failed reading from database. " + strError + ". The block database is in an inconsistent state and may cause issues in the future."
- "To force start use -forcestart";
- uiInterface.ThreadSafeMessageBox(strError, "", CClientUIInterface::MSG_ERROR);
- abort();
+ LogPrintf("%s: Last block properly recorded: #%d %s\n", __func__, pindexLastMeta->nHeight,
+ pindexLastMeta->GetBlockHash().ToString().c_str());
+ LogPrintf("%s : pcoinstip=%d %s\n", __func__, mapBlockIndex[pcoinsTip->GetBestBlock()]->nHeight,
+ pcoinsTip->GetBestBlock().GetHex());
}
- LogPrintf("Passed corruption fix\n");
}
// Check whether we need to continue reindexing
@@ -3996,7 +4098,7 @@ bool CVerifyDB::VerifyDB(CCoinsView* coinsview, int nCheckLevel, int nCheckDepth
CBlock block;
if (!ReadBlockFromDisk(block, pindex))
return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
- if (!ConnectBlock(block, state, pindex, coins))
+ if (!ConnectBlock(block, state, pindex, coins, false))
return error("VerifyDB() : *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
}
}
@@ -4008,16 +4110,37 @@ bool CVerifyDB::VerifyDB(CCoinsView* coinsview, int nCheckLevel, int nCheckDepth
void UnloadBlockIndex()
{
- mapBlockIndex.clear();
+ LOCK(cs_main);
setBlockIndexCandidates.clear();
chainActive.SetTip(NULL);
pindexBestInvalid = NULL;
+ pindexBestHeader = NULL;
+ mempool.clear();
+ mapOrphanTransactions.clear();
+ mapOrphanTransactionsByPrev.clear();
+ nSyncStarted = 0;
+ mapBlocksUnlinked.clear();
+ vinfoBlockFile.clear();
+ nLastBlockFile = 0;
+ nBlockSequenceId = 1;
+ mapBlockSource.clear();
+ mapBlocksInFlight.clear();
+ nQueuedValidatedHeaders = 0;
+ nPreferredDownload = 0;
+ setDirtyBlockIndex.clear();
+ setDirtyFileInfo.clear();
+ mapNodeState.clear();
+
+ for (BlockMap::value_type& entry : mapBlockIndex) {
+ delete entry.second;
+ }
+ mapBlockIndex.clear();
}
-bool LoadBlockIndex()
+bool LoadBlockIndex(string& strError)
{
// Load block index from databases
- if (!fReindex && !LoadBlockIndexDB())
+ if (!fReindex && !LoadBlockIndexDB(strError))
return false;
return true;
}
@@ -4072,7 +4195,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos* dbp)
int nLoaded = 0;
try {
// This takes over fileIn and calls fclose() on it in the CBufferedFile destructor
- CBufferedFile blkdat(fileIn, 2 * MAX_BLOCK_SIZE, MAX_BLOCK_SIZE + 8, SER_DISK, CLIENT_VERSION);
+ CBufferedFile blkdat(fileIn, 2 * MAX_BLOCKFILE_SIZE, MAX_BLOCKFILE_SIZE + 8, SER_DISK, CLIENT_VERSION);
uint64_t nRewind = blkdat.GetPos();
while (!blkdat.eof()) {
boost::this_thread::interruption_point();
@@ -4091,7 +4214,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos* dbp)
continue;
// read size
blkdat >> nSize;
- if (nSize < 80 || nSize > MAX_BLOCK_SIZE)
+ if (nSize < 80 || nSize > MAX_BLOCKFILE_SIZE)
continue;
} catch (const std::exception&) {
// no valid block header found; don't complain
@@ -4318,7 +4441,7 @@ string GetWarnings(string strFor)
string strRPC;
if (!CLIENT_VERSION_IS_RELEASE)
- strStatusBar = _("This is a pre-release test build - use at your own risk - do not use for mining or merchant applications");
+ strStatusBar = _("This is a pre-release test build - use at your own risk - do not use for mining, staking or merchant applications");
if (GetBoolArg("-testsafemode", false))
strStatusBar = strRPC = "testsafemode enabled";
@@ -4340,7 +4463,7 @@ string GetWarnings(string strFor)
// Alerts
{
LOCK(cs_mapAlerts);
- BOOST_FOREACH (PAIRTYPE(const uint256, CAlert) & item, mapAlerts) {
+ for (PAIRTYPE(const uint256, CAlert) & item : mapAlerts) {
const CAlert& alert = item.second;
if (alert.AppliesToMe() && alert.nPriority > nPriority) {
nPriority = alert.nPriority;
@@ -4410,26 +4533,21 @@ void static ProcessGetData(CNode* pfrom)
vector vNotFound;
+ LOCK(cs_main);
+
while (it != pfrom->vRecvGetData.end()) {
// Don't bother if send buffer is too full to respond anyway
if (pfrom->nSendSize >= SendBufferSize())
break;
const CInv& inv = *it;
+ {
+ boost::this_thread::interruption_point();
+ it++;
- boost::this_thread::interruption_point();
- it++;
-
- if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK) {
-
- CBlock block;
- bool send = false;
-
- {
- LOCK(cs_main);
-
+ if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK) {
+ bool send = false;
BlockMap::iterator mi = mapBlockIndex.find(inv.hash);
-
if (mi != mapBlockIndex.end()) {
if (chainActive.Contains(mi->second)) {
send = true;
@@ -4437,166 +4555,158 @@ void static ProcessGetData(CNode* pfrom)
// To prevent fingerprinting attacks, only send blocks outside of the active
// chain if they are valid, and no more than a max reorg depth than the best header
// chain we know about.
- send = mi->second->IsValid(BLOCK_VALID_SCRIPTS)
- && pindexBestHeader
- && (chainActive.Height() - mi->second->nHeight < Params().MaxReorganizationDepth());
-
- if(!send)
+ send = mi->second->IsValid(BLOCK_VALID_SCRIPTS) && (pindexBestHeader != NULL) &&
+ (chainActive.Height() - mi->second->nHeight < Params().MaxReorganizationDepth());
+ if (!send) {
LogPrintf("ProcessGetData(): ignoring request from peer=%i for old block that isn't in the main chain\n", pfrom->GetId());
+ }
+ }
+ }
+ // Don't send not-validated blocks
+ if (send && (mi->second->nStatus & BLOCK_HAVE_DATA)) {
+ // Send block from disk
+ CBlock block;
+ if (!ReadBlockFromDisk(block, (*mi).second))
+ assert(!"cannot load block from disk");
+ if (inv.type == MSG_BLOCK)
+ pfrom->PushMessage("block", block);
+ else // MSG_FILTERED_BLOCK)
+ {
+ LOCK(pfrom->cs_filter);
+ if (pfrom->pfilter) {
+ CMerkleBlock merkleBlock(block, *pfrom->pfilter);
+ pfrom->PushMessage("merkleblock", merkleBlock);
+ // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
+ // This avoids hurting performance by pointlessly requiring a round-trip
+ // Note that there is currently no way for a node to request any single transactions we didnt send here -
+ // they must either disconnect and retry or request the full block.
+ // Thus, the protocol spec specified allows for us to provide duplicate txn here,
+ // however we MUST always provide at least what the remote peer needs
+ typedef std::pair PairType;
+ for (PairType& pair : merkleBlock.vMatchedTxn)
+ if (!pfrom->setInventoryKnown.count(CInv(MSG_TX, pair.second)))
+ pfrom->PushMessage("tx", block.vtx[pair.first]);
+ }
+ // else
+ // no response
}
- // Don't send not-validated blocks
- send = send && (mi->second->nStatus & BLOCK_HAVE_DATA);
-
- if(send) {
-
- // Send block from disk
- if (!ReadBlockFromDisk(block, mi->second))
- assert(!"cannot load block from disk");
+ // Trigger them to send a getblocks request for the next batch of inventory
+ if (inv.hash == pfrom->hashContinue) {
+ // Bypass PushInventory, this must send even if redundant,
+ // and we want it right after the last block so they don't
+ // wait for other stuff first.
+ vector vInv;
+ vInv.push_back(CInv(MSG_BLOCK, chainActive.Tip()->GetBlockHash()));
+ pfrom->PushMessage("inv", vInv);
+ pfrom->hashContinue = 0;
}
}
- }
-
- if(send) {
- if (inv.type == MSG_BLOCK)
- pfrom->PushMessage("block", block);
- else // MSG_FILTERED_BLOCK)
+ } else if (inv.IsKnownType()) {
+ // Send stream from relay memory
+ bool pushed = false;
{
- LOCK(pfrom->cs_filter);
- if (pfrom->pfilter) {
- CMerkleBlock merkleBlock(block, *pfrom->pfilter);
- pfrom->PushMessage("merkleblock", merkleBlock);
- // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
- // This avoids hurting performance by pointlessly requiring a round-trip
- // Note that there is currently no way for a node to request any single transactions we didnt send here -
- // they must either disconnect and retry or request the full block.
- // Thus, the protocol spec specified allows for us to provide duplicate txn here,
- // however we MUST always provide at least what the remote peer needs
- typedef std::pair PairType;
- BOOST_FOREACH (PairType& pair, merkleBlock.vMatchedTxn)
- if (!pfrom->setInventoryKnown.count(CInv(MSG_TX, pair.second)))
- pfrom->PushMessage("tx", block.vtx[pair.first]);
+ LOCK(cs_mapRelay);
+ map::iterator mi = mapRelay.find(inv);
+ if (mi != mapRelay.end()) {
+ pfrom->PushMessage(inv.GetCommand(), (*mi).second);
+ pushed = true;
}
- // else
- // no response
- }
-
- // Trigger them to send a getblocks request for the next batch of inventory
- if (inv.hash == pfrom->hashContinue) {
- // Bypass PushInventory, this must send even if redundant,
- // and we want it right after the last block so they don't
- // wait for other stuff first.
- vector vInv;
- vInv.push_back(CInv(MSG_BLOCK, chainActive.Tip()->GetBlockHash()));
- pfrom->PushMessage("inv", vInv);
- pfrom->hashContinue = 0;
- }
- }
- } else if (inv.IsKnownType()) {
- // Send stream from relay memory
- bool pushed = false;
- {
- LOCK(cs_mapRelay);
- map::iterator mi = mapRelay.find(inv);
- if (mi != mapRelay.end()) {
- pfrom->PushMessage(inv.GetCommand(), (*mi).second);
- pushed = true;
}
- }
- if (!pushed && inv.type == MSG_TX) {
- CTransaction tx;
- if (mempool.lookup(inv.hash, tx)) {
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss.reserve(1000);
- ss << tx;
- pfrom->PushMessage("tx", ss);
- pushed = true;
+ if (!pushed && inv.type == MSG_TX) {
+ CTransaction tx;
+ if (mempool.lookup(inv.hash, tx)) {
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss.reserve(1000);
+ ss << tx;
+ pfrom->PushMessage("tx", ss);
+ pushed = true;
+ }
}
- }
- if (!pushed && inv.type == MSG_TXLOCK_VOTE) {
- if (mapTxLockVote.count(inv.hash)) {
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss.reserve(1000);
- ss << mapTxLockVote[inv.hash];
- pfrom->PushMessage("txlvote", ss);
- pushed = true;
+ if (!pushed && inv.type == MSG_TXLOCK_VOTE) {
+ if (mapTxLockVote.count(inv.hash)) {
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss.reserve(1000);
+ ss << mapTxLockVote[inv.hash];
+ pfrom->PushMessage("txlvote", ss);
+ pushed = true;
+ }
}
- }
- if (!pushed && inv.type == MSG_TXLOCK_REQUEST) {
- if (mapTxLockReq.count(inv.hash)) {
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss.reserve(1000);
- ss << mapTxLockReq[inv.hash];
- pfrom->PushMessage("ix", ss);
- pushed = true;
+ if (!pushed && inv.type == MSG_TXLOCK_REQUEST) {
+ if (mapTxLockReq.count(inv.hash)) {
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss.reserve(1000);
+ ss << mapTxLockReq[inv.hash];
+ pfrom->PushMessage("ix", ss);
+ pushed = true;
+ }
}
- }
- if (!pushed && inv.type == MSG_SPORK) {
- if (mapSporks.count(inv.hash)) {
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss.reserve(1000);
- ss << mapSporks[inv.hash];
- pfrom->PushMessage("spork", ss);
- pushed = true;
+ if (!pushed && inv.type == MSG_SPORK) {
+ if (mapSporks.count(inv.hash)) {
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss.reserve(1000);
+ ss << mapSporks[inv.hash];
+ pfrom->PushMessage("spork", ss);
+ pushed = true;
+ }
}
- }
-
- if (!pushed && inv.type == MSG_MASTERNODE_WINNER) {
+ if (!pushed && inv.type == MSG_MASTERNODE_WINNER) {
auto mnw = masternodePayments.mapMasternodePayeeVotes.find(inv.hash);
if(mnw != masternodePayments.mapMasternodePayeeVotes.cend()) {
CDataStream ss{SER_NETWORK, PROTOCOL_VERSION};
- ss.reserve(1000);
+ ss.reserve(1000);
ss << mnw->second;
pfrom->PushMessage("mnw", ss);
- pushed = true;
+ pushed = true;
+ }
}
- }
- if (!pushed && inv.type == MSG_MASTERNODE_ANNOUNCE) {
- if (mnodeman.mapSeenMasternodeBroadcast.count(inv.hash)) {
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss.reserve(1000);
- ss << mnodeman.mapSeenMasternodeBroadcast[inv.hash];
- pfrom->PushMessage("mnb", ss);
- pushed = true;
+ if (!pushed && inv.type == MSG_MASTERNODE_ANNOUNCE) {
+ if (mnodeman.mapSeenMasternodeBroadcast.count(inv.hash)) {
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss.reserve(1000);
+ ss << mnodeman.mapSeenMasternodeBroadcast[inv.hash];
+ pfrom->PushMessage("mnb", ss);
+ pushed = true;
+ }
}
- }
- if (!pushed && inv.type == MSG_MASTERNODE_PING) {
- if (mnodeman.mapSeenMasternodePing.count(inv.hash)) {
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss.reserve(1000);
- ss << mnodeman.mapSeenMasternodePing[inv.hash];
- pfrom->PushMessage("mnp", ss);
- pushed = true;
+ if (!pushed && inv.type == MSG_MASTERNODE_PING) {
+ if (mnodeman.mapSeenMasternodePing.count(inv.hash)) {
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss.reserve(1000);
+ ss << mnodeman.mapSeenMasternodePing[inv.hash];
+ pfrom->PushMessage("mnp", ss);
+ pushed = true;
+ }
}
- }
- if (!pushed && inv.type == MSG_DSTX) {
- if (mapObfuscationBroadcastTxes.count(inv.hash)) {
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss.reserve(1000);
- ss << mapObfuscationBroadcastTxes[inv.hash].tx << mapObfuscationBroadcastTxes[inv.hash].vin << mapObfuscationBroadcastTxes[inv.hash].vchSig << mapObfuscationBroadcastTxes[inv.hash].sigTime;
+ if (!pushed && inv.type == MSG_DSTX) {
+ if (mapObfuscationBroadcastTxes.count(inv.hash)) {
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss.reserve(1000);
+ ss << mapObfuscationBroadcastTxes[inv.hash].tx << mapObfuscationBroadcastTxes[inv.hash].vin << mapObfuscationBroadcastTxes[inv.hash].vchSig << mapObfuscationBroadcastTxes[inv.hash].sigTime;
- pfrom->PushMessage("dstx", ss);
- pushed = true;
+ pfrom->PushMessage("dstx", ss);
+ pushed = true;
+ }
}
- }
- if (!pushed) {
- vNotFound.push_back(inv);
+ if (!pushed) {
+ vNotFound.push_back(inv);
+ }
}
- }
- // Track requests for our stuff.
- g_signals.Inventory(inv.hash);
+ // Track requests for our stuff.
+ GetMainSignals().Inventory(inv.hash);
- if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK)
- break;
+ if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK)
+ break;
+ }
}
pfrom->vRecvGetData.erase(pfrom->vRecvGetData.begin(), it);
@@ -4613,6 +4723,7 @@ void static ProcessGetData(CNode* pfrom)
}
}
+bool fRequestedSporksIDB = false;
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived)
{
RandAddSeedPerfmon();
@@ -4627,10 +4738,17 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Each connection can only send one version message
if (pfrom->nVersion != 0) {
pfrom->PushMessage("reject", strCommand, REJECT_DUPLICATE, string("Duplicate version message"));
+ LOCK(cs_main);
Misbehaving(pfrom->GetId(), 1);
return false;
}
+ if (!fRequestedSporksIDB) {
+ LogPrintf("asking peer for sporks\n");
+ pfrom->PushMessage("getsporks");
+ fRequestedSporksIDB = true;
+ }
+
int64_t nTime;
CAddress addrMe;
CAddress addrFrom;
@@ -4684,9 +4802,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (fListen && !IsInitialBlockDownload()) {
CAddress addr = GetLocalAddress(&pfrom->addr);
if (addr.IsRoutable()) {
+ LogPrintf("ProcessMessages: advertizing address %s\n", addr.ToString());
pfrom->PushAddress(addr);
} else if (IsPeerAddrLocalGood(pfrom)) {
addr.SetIP(pfrom->addrLocal);
+ LogPrintf("ProcessMessages: advertizing address %s\n", addr.ToString());
pfrom->PushAddress(addr);
}
}
@@ -4707,7 +4827,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Relay alerts
{
LOCK(cs_mapAlerts);
- BOOST_FOREACH (PAIRTYPE(const uint256, CAlert) & item, mapAlerts)
+ for (PAIRTYPE(const uint256, CAlert) & item : mapAlerts)
item.second.RelayTo(pfrom);
}
@@ -4722,17 +4842,25 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->nStartingHeight, addrMe.ToString(), pfrom->id,
remoteAddr);
- AddTimeData(pfrom->addr, nTime);
+ int64_t nTimeOffset = nTime - GetTime();
+ pfrom->nTimeOffset = nTimeOffset;
+ AddTimeData(pfrom->addr, nTimeOffset);
}
-
else if (pfrom->nVersion == 0) {
// Must have a version message before anything else
+ LOCK(cs_main);
Misbehaving(pfrom->GetId(), 1);
return false;
}
+ else if (pfrom->DisconnectOldProtocol(ActiveProtocol(), strCommand)) {
+ // Instantly disconnect old protocol
+ return false;
+ }
+
+
else if (strCommand == "verack") {
pfrom->SetRecvVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
@@ -4743,7 +4871,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
-
else if (strCommand == "addr") {
vector vAddr;
vRecv >> vAddr;
@@ -4752,6 +4879,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (pfrom->nVersion < CADDR_TIME_VERSION && addrman.size() > 1000)
return true;
if (vAddr.size() > 1000) {
+ LOCK(cs_main);
Misbehaving(pfrom->GetId(), 20);
return error("message addr size() = %u", vAddr.size());
}
@@ -4760,7 +4888,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
vector vAddrOk;
int64_t nNow = GetAdjustedTime();
int64_t nSince = nNow - 10 * 60;
- BOOST_FOREACH (CAddress& addr, vAddr) {
+ for (CAddress& addr : vAddr) {
boost::this_thread::interruption_point();
if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60)
@@ -4780,7 +4908,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
uint256 hashRand = hashSalt ^ (hashAddr << 32) ^ ((GetTime() + hashAddr) / (24 * 60 * 60));
hashRand = Hash(BEGIN(hashRand), END(hashRand));
multimap mapMix;
- BOOST_FOREACH (CNode* pnode, vNodes) {
+ for (CNode* pnode : vNodes) {
if (pnode->nVersion < CADDR_TIME_VERSION)
continue;
unsigned int nPointer;
@@ -4807,22 +4935,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
else if (strCommand == "inv") {
+
vector vInv;
vRecv >> vInv;
if (vInv.size() > MAX_INV_SZ) {
+ LOCK(cs_main);
Misbehaving(pfrom->GetId(), 20);
return error("message inv size() = %u", vInv.size());
}
- std::vector vToFetch;
-
- for(const auto& inv : vInv) {
+ LOCK(cs_main);
- LOCK(cs_main);
+ std::vector vToFetch;
+ for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) {
+ const CInv& inv = vInv[nInv];
boost::this_thread::interruption_point();
pfrom->AddInventoryKnown(inv);
-
bool fAlreadyHave = AlreadyHave(inv);
LogPrint("net", "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id);
@@ -4839,7 +4968,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
// Track requests for our stuff
- g_signals.Inventory(inv.hash);
+ GetMainSignals().Inventory(inv.hash);
if (pfrom->nSendSize > (SendBufferSize() * 2)) {
Misbehaving(pfrom->GetId(), 50);
@@ -4856,6 +4985,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
vector vInv;
vRecv >> vInv;
if (vInv.size() > MAX_INV_SZ) {
+ LOCK(cs_main);
Misbehaving(pfrom->GetId(), 20);
return error("message getdata size() = %u", vInv.size());
}
@@ -4885,7 +5015,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (pindex)
pindex = chainActive.Next(pindex);
int nLimit = 500;
- LogPrintf("getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop == uint256(0) ? "end" : hashStop.ToString(), nLimit, pfrom->id);
+ LogPrint("net", "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop == uint256(0) ? "end" : hashStop.ToString(), nLimit, pfrom->id);
for (; pindex; pindex = chainActive.Next(pindex)) {
if (pindex->GetBlockHash() == hashStop) {
LogPrint("net", " getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
@@ -4966,7 +5096,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return true;
}
- std::string strMessage = tx.GetHash().ToString() + boost::lexical_cast(sigTime);
+ std::string strMessage = tx.GetHash().ToString() + std::to_string(sigTime);
std::string errorMessage = "";
if (!obfuScationSigner.VerifyMessage(pmn->pubKeyMasternode, vchSig, strMessage, errorMessage)) {
@@ -5008,21 +5138,21 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
vWorkQueue.push_back(inv.hash);
LogPrint("mempool", "AcceptToMemoryPool: peer=%d %s : accepted %s (poolsz %u)\n",
- pfrom->id, pfrom->cleanSubVer,
- tx.GetHash().ToString(),
- mempool.mapTx.size());
+ pfrom->id, pfrom->cleanSubVer,
+ tx.GetHash().ToString(),
+ mempool.mapTx.size());
// Recursively process any orphan transactions that depended on this one
set setMisbehaving;
- for (unsigned int i = 0; i < vWorkQueue.size(); i++) {
+ for(unsigned int i = 0; i < vWorkQueue.size(); i++) {
map >::iterator itByPrev = mapOrphanTransactionsByPrev.find(vWorkQueue[i]);
- if (itByPrev == mapOrphanTransactionsByPrev.end())
+ if(itByPrev == mapOrphanTransactionsByPrev.end())
continue;
- for (set::iterator mi = itByPrev->second.begin();
- mi != itByPrev->second.end();
- ++mi) {
- const uint256& orphanHash = *mi;
- const CTransaction& orphanTx = mapOrphanTransactions[orphanHash].tx;
+ for(set::iterator mi = itByPrev->second.begin();
+ mi != itByPrev->second.end();
+ ++mi) {
+ const uint256 &orphanHash = *mi;
+ const CTransaction &orphanTx = mapOrphanTransactions[orphanHash].tx;
NodeId fromPeer = mapOrphanTransactions[orphanHash].fromPeer;
bool fMissingInputs2 = false;
// Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan
@@ -5031,16 +5161,16 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
CValidationState stateDummy;
- if (setMisbehaving.count(fromPeer))
+ if(setMisbehaving.count(fromPeer))
continue;
- if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2)) {
+ if(AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2)) {
LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString());
RelayTransaction(orphanTx);
vWorkQueue.push_back(orphanHash);
vEraseQueue.push_back(orphanHash);
- } else if (!fMissingInputs2) {
+ } else if(!fMissingInputs2) {
int nDos = 0;
- if (stateDummy.IsInvalid(nDos) && nDos > 0) {
+ if(stateDummy.IsInvalid(nDos) && nDos > 0) {
// Punish peer that gave us an invalid orphan tx
Misbehaving(fromPeer, nDos);
setMisbehaving.insert(fromPeer);
@@ -5055,7 +5185,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
- BOOST_FOREACH (uint256 hash, vEraseQueue)
+ for (uint256 hash : vEraseQueue)
EraseOrphanTx(hash);
} else if (fMissingInputs) {
AddOrphanTx(tx, pfrom->GetId());
@@ -5083,7 +5213,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
LogPrint("mempool", "%s from peer=%d %s was not accepted into the memory pool: %s\n", tx.GetHash().ToString(),
pfrom->id, pfrom->cleanSubVer,
state.GetRejectReason());
- pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
+ pfrom->PushMessage("reject", strCommand, (unsigned char)state.GetRejectCode(),
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
if (nDoS > 0)
Misbehaving(pfrom->GetId(), nDoS);
@@ -5098,6 +5228,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks.
unsigned int nCount = ReadCompactSize(vRecv);
if (nCount > MAX_HEADERS_RESULTS) {
+ LOCK(cs_main);
Misbehaving(pfrom->GetId(), 20);
return error("headers message size = %u", nCount);
}
@@ -5114,7 +5245,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return true;
}
CBlockIndex* pindexLast = NULL;
- BOOST_FOREACH (const CBlockHeader& header, headers) {
+ for (const CBlockHeader& header : headers) {
CValidationState state;
if (pindexLast != NULL && header.hashPrevBlock != pindexLast->GetBlockHash()) {
Misbehaving(pfrom->GetId(), 20);
@@ -5175,12 +5306,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (!mapBlockIndex.count(block.GetHash())) {
ProcessNewBlock(state, pfrom, &block);
int nDoS;
- if (state.IsInvalid(nDoS)) {
- pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
- state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
- if (nDoS > 0) {
+ if(state.IsInvalid(nDoS)) {
+ pfrom->PushMessage("reject", strCommand, (unsigned char)state.GetRejectCode(),
+ state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
+ if(nDoS > 0) {
TRY_LOCK(cs_main, lockMain);
- if (lockMain) Misbehaving(pfrom->GetId(), nDoS);
+ if(lockMain) Misbehaving(pfrom->GetId(), nDoS);
}
}
//disconnect this node if its old protocol version
@@ -5200,7 +5331,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
else if ((strCommand == "getaddr") && (pfrom->fInbound)) {
pfrom->vAddrToSend.clear();
vector vAddr = addrman.GetAddr();
- BOOST_FOREACH (const CAddress& addr, vAddr)
+ for (const CAddress& addr : vAddr)
pfrom->PushAddress(addr);
}
@@ -5211,7 +5342,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
std::vector vtxid;
mempool.queryHashes(vtxid);
vector vInv;
- BOOST_FOREACH (uint256& hash, vtxid) {
+ for (uint256& hash : vtxid) {
CInv inv(MSG_TX, hash);
CTransaction tx;
bool fInMemPool = mempool.lookup(hash, tx);
@@ -5284,10 +5415,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
} else {
sProblem = "Unsolicited pong without ping";
}
- } else {
- // This is most likely a bug in another implementation somewhere, cancel this ping
- bPingFinished = true;
- sProblem = "Short payload";
}
if (!(sProblem.empty())) {
@@ -5316,7 +5443,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->setKnown.insert(alertHash);
{
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes)
+ for (CNode* pnode : vNodes)
alert.RelayTo(pnode);
}
} else {
@@ -5326,6 +5453,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// This isn't a Misbehaving(100) (immediate ban) because the
// peer might be an older or different implementation with
// a different signature key, etc.
+ LOCK(cs_main);
Misbehaving(pfrom->GetId(), 10);
}
}
@@ -5336,6 +5464,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
strCommand == "filteradd" ||
strCommand == "filterclear")) {
LogPrintf("bloom message=%s\n", strCommand);
+ LOCK(cs_main);
Misbehaving(pfrom->GetId(), 100);
}
@@ -5343,10 +5472,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
CBloomFilter filter;
vRecv >> filter;
- if (!filter.IsWithinSizeConstraints())
+ if (!filter.IsWithinSizeConstraints()) {
// There is no excuse for sending a too-large filter
+ LOCK(cs_main);
Misbehaving(pfrom->GetId(), 100);
- else {
+ } else {
LOCK(pfrom->cs_filter);
delete pfrom->pfilter;
pfrom->pfilter = new CBloomFilter(filter);
@@ -5363,13 +5493,16 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Nodes must NEVER send a data item > 520 bytes (the max size for a script data object,
// and thus, the maximum size any matched object can have) in a filteradd message
if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE) {
+ LOCK(cs_main);
Misbehaving(pfrom->GetId(), 100);
} else {
LOCK(pfrom->cs_filter);
if (pfrom->pfilter)
pfrom->pfilter->insert(vData);
- else
+ else {
+ LOCK(cs_main);
Misbehaving(pfrom->GetId(), 100);
+ }
}
}
@@ -5409,26 +5542,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
obfuScationPool.ProcessMessageObfuscation(pfrom, strCommand, vRecv);
mnodeman.ProcessMessage(pfrom, strCommand, vRecv);
masternodePayments.ProcessMessageMasternodePayments(pfrom, strCommand, vRecv);
- ProcessMessageSwiftTX(pfrom, strCommand, vRecv);
ProcessSpork(pfrom, strCommand, vRecv);
masternodeSync.ProcessMessage(pfrom, strCommand, vRecv);
}
+
return true;
}
// Note: whenever a protocol update is needed toggle between both implementations (comment out the formerly active one)
// so we can leave the existing clients untouched (old SPORK will stay on so they don't see even older clients).
// Those old clients won't react to the changes of the other (new) SPORK because at the time of their implementation
-//
-
+// it was the one which was commented out
int ActiveProtocol()
{
- if(Params().F2ActivationTime() < GetAdjustedTime())
+ if (IsSporkActive(SPORK_8_NEW_PROTOCOL_ENFORCEMENT))
return MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT;
-// if (IsSporkActive(SPORK_X_NEW_PROTOCOL_ENFORCEMENT_X))
-// return MIN_PEER_PROTO_VERSION_AFTER_ENFORCEMENT;
return MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT;
}
@@ -5464,10 +5594,16 @@ bool ProcessMessages(CNode* pfrom)
// get next message
CNetMessage& msg = *it;
- //if (fDebug)
- // LogPrintf("ProcessMessages(message %u msgsz, %u bytes, complete:%s)\n",
- // msg.hdr.nMessageSize, msg.vRecv.size(),
- // msg.complete() ? "Y" : "N");
+ if (fDebug)
+ LogPrintf("ProcessMessages(message %u msgsz, %u bytes, complete:%s)\n",
+ msg.hdr.nMessageSize, msg.vRecv.size(),
+ msg.complete() ? "Y" : "N");
+
+ /////////////////////////////////////////////////
+ CMessageHeader& hdr = msg.hdr;
+ string strCommand = hdr.GetCommand();
+ if (fDebug) LogPrintf("\e[32m%s\e[0m\n", strCommand.c_str());
+ /////////////////////////////////////////////////
// end, if an incomplete message is found
if (!msg.complete())
@@ -5484,19 +5620,18 @@ bool ProcessMessages(CNode* pfrom)
}
// Read header
- CMessageHeader& hdr = msg.hdr;
if (!hdr.IsValid()) {
LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id);
continue;
}
- string strCommand = hdr.GetCommand();
+ strCommand = hdr.GetCommand();
// Message size
unsigned int nMessageSize = hdr.nMessageSize;
// Checksum
CDataStream& vRecv = msg.vRecv;
- uint256 hash = Hash(vRecv.begin(), vRecv.begin() + nMessageSize);
+ const uint256& hash = msg.GetMessageHash();
unsigned int nChecksum = 0;
memcpy(&nChecksum, &hash, sizeof(nChecksum));
if (nChecksum != hdr.nChecksum) {
@@ -5507,6 +5642,16 @@ bool ProcessMessages(CNode* pfrom)
// Process message
bool fRet = false;
+ /////////////////////////////////////////////////
+ if (fDebug) {
+ char msgbuf[65536] = {0};
+ unsigned int msglen = vRecv.size();
+ if (msglen>65536) msglen = 65535;
+ memcpy(msgbuf, vRecv.str().c_str(), msglen);
+ for (unsigned int i = 0; i < msglen; i++) printf("%02hhx", msgbuf[i]);
+ printf("\n");
+ }
+ /////////////////////////////////////////////////
try {
fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime);
boost::this_thread::interruption_point();
@@ -5545,211 +5690,227 @@ bool ProcessMessages(CNode* pfrom)
bool SendMessages(CNode* pto, bool fSendTrickle)
{
- // Don't send anything until we get their version message
- if (pto->nVersion == 0)
- return true;
+ // Don't send anything until we get their version message
+ if (pto->nVersion == 0)
+ return true;
- //
- // Message: ping
- //
- bool pingSend = false;
- if (pto->fPingQueued) {
- // RPC ping request by user
- pingSend = true;
- }
- if (pto->nPingNonceSent == 0 && pto->nPingUsecStart + PING_INTERVAL * 1000000 < GetTimeMicros()) {
- // Ping automatically sent as a latency probe & keepalive.
- pingSend = true;
- }
- if (pingSend) {
- uint64_t nonce = 0;
- while (nonce == 0) {
- GetRandBytes((unsigned char*)&nonce, sizeof(nonce));
- }
- pto->fPingQueued = false;
- pto->nPingUsecStart = GetTimeMicros();
- if (pto->nVersion > BIP0031_VERSION) {
- pto->nPingNonceSent = nonce;
- pto->PushMessage("ping", nonce);
- } else {
- // Peer is too old to support ping command with nonce, pong will never arrive.
- pto->nPingNonceSent = 0;
- pto->PushMessage("ping");
+ //
+ // Message: ping
+ //
+ bool pingSend = false;
+ if (pto->fPingQueued) {
+ // RPC ping request by user
+ pingSend = true;
+ }
+ if (pto->nPingNonceSent == 0 && pto->nPingUsecStart + PING_INTERVAL * 1000000 < GetTimeMicros()) {
+ // Ping automatically sent as a latency probe & keepalive.
+ pingSend = true;
+ }
+ if (pingSend) {
+ uint64_t nonce = 0;
+ while (nonce == 0) {
+ GetRandBytes((unsigned char*)&nonce, sizeof(nonce));
+ }
+ pto->fPingQueued = false;
+ pto->nPingUsecStart = GetTimeMicros();
+ if (pto->nVersion > BIP0031_VERSION) {
+ pto->nPingNonceSent = nonce;
+ pto->PushMessage("ping", nonce);
+ } else {
+ // Peer is too old to support ping command with nonce, pong will never arrive.
+ pto->nPingNonceSent = 0;
+ pto->PushMessage("ping");
+ }
}
- }
- TRY_LOCK(cs_main, lockMain); // Acquire cs_main for IsInitialBlockDownload() and CNodeState()
- if (!lockMain)
- return true;
+ TRY_LOCK(cs_main, lockMain); // Acquire cs_main for IsInitialBlockDownload() and CNodeState()
+ if (!lockMain)
+ return true;
- //
- // Message: addr
- //
- if (fSendTrickle) {
- vector vAddr;
- vAddr.reserve(pto->vAddrToSend.size());
- BOOST_FOREACH (const CAddress& addr, pto->vAddrToSend) {
- // returns true if wasn't already contained in the set
- if (pto->setAddrKnown.insert(addr).second) {
- vAddr.push_back(addr);
- // receiver rejects addr messages larger than 1000
- if (vAddr.size() >= 1000) {
- pto->PushMessage("addr", vAddr);
- vAddr.clear();
+ // Address refresh broadcast
+ static int64_t nLastRebroadcast;
+ if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60)) {
+ LOCK(cs_vNodes);
+ for (CNode* pnode : vNodes) {
+ // Periodically clear setAddrKnown to allow refresh broadcasts
+ if (nLastRebroadcast)
+ pnode->setAddrKnown.clear();
+
+ // Rebroadcast our address
+ AdvertiseLocal(pnode);
+ }
+ if (!vNodes.empty())
+ nLastRebroadcast = GetTime();
+ }
+
+ //
+ // Message: addr
+ //
+ if (fSendTrickle) {
+ vector vAddr;
+ vAddr.reserve(pto->vAddrToSend.size());
+ for (const CAddress& addr : pto->vAddrToSend) {
+ // returns true if wasn't already contained in the set
+ if (pto->setAddrKnown.insert(addr).second) {
+ vAddr.push_back(addr);
+ // receiver rejects addr messages larger than 1000
+ if (vAddr.size() >= 1000) {
+ pto->PushMessage("addr", vAddr);
+ vAddr.clear();
+ }
}
}
+ pto->vAddrToSend.clear();
+ if (!vAddr.empty())
+ pto->PushMessage("addr", vAddr);
}
- pto->vAddrToSend.clear();
- if (!vAddr.empty())
- pto->PushMessage("addr", vAddr);
- }
- CNodeState& state = *State(pto->GetId());
- if (state.fShouldBan) {
- if (pto->fWhitelisted)
- LogPrintf("Warning: not punishing whitelisted peer %s!\n", pto->addr.ToString());
- else {
- pto->fDisconnect = true;
- if (pto->addr.IsLocal())
- LogPrintf("Warning: not banning local peer %s!\n", pto->addr.ToString());
+ CNodeState& state = *State(pto->GetId());
+ if (state.fShouldBan) {
+ if (pto->fWhitelisted)
+ LogPrintf("Warning: not punishing whitelisted peer %s!\n", pto->addr.ToString());
else {
- CNode::Ban(pto->addr);
+ pto->fDisconnect = true;
+ if (pto->addr.IsLocal())
+ LogPrintf("Warning: not banning local peer %s!\n", pto->addr.ToString());
+ else {
+ CNode::Ban(pto->addr, BanReasonNodeMisbehaving);
+ }
+ }
+ state.fShouldBan = false;
+ }
+
+ for (const CBlockReject& reject : state.rejects)
+ pto->PushMessage("reject", (string) "block", reject.chRejectCode, reject.strRejectReason, reject.hashBlock);
+ state.rejects.clear();
+
+ // Start block sync
+ if (pindexBestHeader == NULL)
+ pindexBestHeader = chainActive.Tip();
+ bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->fClient && !pto->fOneShot); // Download if this is a nice peer, or we have no nice peers and this one might do.
+ if (!state.fSyncStarted && !pto->fClient && fFetch /*&& !fImporting*/ && !fReindex) {
+ // Only actively request headers from a single peer, unless we're close to end of initial download.
+ if (nSyncStarted == 0 || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - 6 * 60 * 60) { // NOTE: was "close to today" and 24h in Bitcoin
+ state.fSyncStarted = true;
+ nSyncStarted++;
+ //CBlockIndex *pindexStart = pindexBestHeader->pprev ? pindexBestHeader->pprev : pindexBestHeader;
+ //LogPrint("net", "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->id, pto->nStartingHeight);
+ //pto->PushMessage("getheaders", chainActive.GetLocator(pindexStart), uint256(0));
+ pto->PushMessage("getblocks", chainActive.GetLocator(chainActive.Tip()), uint256(0));
}
}
- state.fShouldBan = false;
- }
-
- BOOST_FOREACH (const CBlockReject& reject, state.rejects)
- pto->PushMessage("reject", (string) "block", reject.chRejectCode, reject.strRejectReason, reject.hashBlock);
- state.rejects.clear();
- // Start block sync
- if (pindexBestHeader == NULL)
- pindexBestHeader = chainActive.Tip();
- bool fFetch = state.fPreferredDownload || (nPreferredDownload == 0 && !pto->fClient && !pto->fOneShot); // Download if this is a nice peer, or we have no nice peers and this one might do.
- if (!state.fSyncStarted && !pto->fClient && fFetch /*&& !fImporting*/ && !fReindex) {
- // Only actively request headers from a single peer, unless we're close to end of initial download.
- if (nSyncStarted == 0 || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - 6 * 60 * 60) { // NOTE: was "close to today" and 24h in Bitcoin
- state.fSyncStarted = true;
- nSyncStarted++;
- //CBlockIndex *pindexStart = pindexBestHeader->pprev ? pindexBestHeader->pprev : pindexBestHeader;
- //LogPrint("net", "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->id, pto->nStartingHeight);
- //pto->PushMessage("getheaders", chainActive.GetLocator(pindexStart), uint256(0));
- pto->PushMessage("getblocks", chainActive.GetLocator(chainActive.Tip()), uint256(0));
+ // Resend wallet transactions that haven't gotten in a block yet
+ // Except during reindex, importing and IBD, when old wallet
+ // transactions become unconfirmed and spams other nodes.
+ if (!fReindex /*&& !fImporting && !IsInitialBlockDownload()*/) {
+ GetMainSignals().Broadcast();
}
- }
- // Resend wallet transactions that haven't gotten in a block yet
- // Except during reindex, importing and IBD, when old wallet
- // transactions become unconfirmed and spams other nodes.
- if (!fReindex /*&& !fImporting && !IsInitialBlockDownload()*/) {
- g_signals.Broadcast();
- }
+ //
+ // Message: inventory
+ //
+ vector vInv;
+ vector vInvWait;
+ {
+ LOCK(pto->cs_inventory);
+ vInv.reserve(pto->vInventoryToSend.size());
+ vInvWait.reserve(pto->vInventoryToSend.size());
+ for (const CInv& inv : pto->vInventoryToSend) {
+ if (pto->setInventoryKnown.count(inv))
+ continue;
- //
- // Message: inventory
- //
- vector vInv;
- vector vInvWait;
- {
- LOCK(pto->cs_inventory);
- vInv.reserve(pto->vInventoryToSend.size());
- vInvWait.reserve(pto->vInventoryToSend.size());
- BOOST_FOREACH (const CInv& inv, pto->vInventoryToSend) {
- if (pto->setInventoryKnown.count(inv))
- continue;
+ // trickle out tx inv to protect privacy
+ if (inv.type == MSG_TX && !fSendTrickle) {
+ // 1/4 of tx invs blast to all immediately
+ static uint256 hashSalt;
+ if (hashSalt == 0)
+ hashSalt = GetRandHash();
+ uint256 hashRand = inv.hash ^ hashSalt;
+ hashRand = Hash(BEGIN(hashRand), END(hashRand));
+ bool fTrickleWait = ((hashRand & 3) != 0);
- // trickle out tx inv to protect privacy
- if (inv.type == MSG_TX && !fSendTrickle) {
- // 1/4 of tx invs blast to all immediately
- static uint256 hashSalt;
- if (hashSalt == 0)
- hashSalt = GetRandHash();
- uint256 hashRand = inv.hash ^ hashSalt;
- hashRand = Hash(BEGIN(hashRand), END(hashRand));
- bool fTrickleWait = ((hashRand & 3) != 0);
-
- if (fTrickleWait) {
- vInvWait.push_back(inv);
- continue;
+ if (fTrickleWait) {
+ vInvWait.push_back(inv);
+ continue;
+ }
}
- }
- // returns true if wasn't already contained in the set
- if (pto->setInventoryKnown.insert(inv).second) {
- vInv.push_back(inv);
- if (vInv.size() >= 1000) {
- pto->PushMessage("inv", vInv);
- vInv.clear();
+ // returns true if wasn't already contained in the set
+ if (pto->setInventoryKnown.insert(inv).second) {
+ vInv.push_back(inv);
+ if (vInv.size() >= 1000) {
+ pto->PushMessage("inv", vInv);
+ vInv.clear();
+ }
}
}
+ pto->vInventoryToSend = vInvWait;
+ }
+ if (!vInv.empty())
+ pto->PushMessage("inv", vInv);
+
+ // Detect whether we're stalling
+ int64_t nNow = GetTimeMicros();
+ if (!pto->fDisconnect && state.nStallingSince && state.nStallingSince < nNow - 1000000 * BLOCK_STALLING_TIMEOUT) {
+ // Stalling only triggers when the block download window cannot move. During normal steady state,
+ // the download window should be much larger than the to-be-downloaded set of blocks, so disconnection
+ // should only happen during initial block download.
+ LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->id);
+ pto->fDisconnect = true;
+ }
+ // In case there is a block that has been in flight from this peer for (2 + 0.5 * N) times the block interval
+ // (with N the number of validated blocks that were in flight at the time it was requested), disconnect due to
+ // timeout. We compensate for in-flight blocks to prevent killing off peers due to our own downstream link
+ // being saturated. We only count validated in-flight blocks so peers can't advertize nonexisting block hashes
+ // to unreasonably increase our timeout.
+ if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0 && state.vBlocksInFlight.front().nTime < nNow - 500000 * Params().TargetSpacing() * (4 + state.vBlocksInFlight.front().nValidatedQueuedBefore)) {
+ LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", state.vBlocksInFlight.front().hash.ToString(), pto->id);
+ pto->fDisconnect = true;
}
- pto->vInventoryToSend = vInvWait;
- }
- if (!vInv.empty())
- pto->PushMessage("inv", vInv);
-
- // Detect whether we're stalling
- int64_t nNow = GetTimeMicros();
- if (!pto->fDisconnect && state.nStallingSince && state.nStallingSince < nNow - 1000000 * BLOCK_STALLING_TIMEOUT) {
- // Stalling only triggers when the block download window cannot move. During normal steady state,
- // the download window should be much larger than the to-be-downloaded set of blocks, so disconnection
- // should only happen during initial block download.
- LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->id);
- pto->fDisconnect = true;
- }
- // In case there is a block that has been in flight from this peer for (2 + 0.5 * N) times the block interval
- // (with N the number of validated blocks that were in flight at the time it was requested), disconnect due to
- // timeout. We compensate for in-flight blocks to prevent killing off peers due to our own downstream link
- // being saturated. We only count validated in-flight blocks so peers can't advertize nonexisting block hashes
- // to unreasonably increase our timeout.
- if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0 && state.vBlocksInFlight.front().nTime < nNow - 500000 * Params().TargetSpacing() * (4 + state.vBlocksInFlight.front().nValidatedQueuedBefore)) {
- LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", state.vBlocksInFlight.front().hash.ToString(), pto->id);
- pto->fDisconnect = true;
- }
- //
- // Message: getdata (blocks)
- //
- vector vGetData;
- if (!pto->fDisconnect && !pto->fClient && fFetch && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
- vector vToDownload;
- NodeId staller = -1;
- FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller);
- BOOST_FOREACH (CBlockIndex* pindex, vToDownload) {
- vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash()));
- MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), pindex);
- LogPrintf("Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(),
- pindex->nHeight, pto->id);
- }
- if (state.nBlocksInFlight == 0 && staller != -1) {
- if (State(staller)->nStallingSince == 0) {
- State(staller)->nStallingSince = nNow;
- LogPrint("net", "Stall started peer=%d\n", staller);
+ //
+ // Message: getdata (blocks)
+ //
+ vector vGetData;
+ if (!pto->fDisconnect && !pto->fClient && fFetch && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
+ vector vToDownload;
+ NodeId staller = -1;
+ FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller);
+ for (CBlockIndex* pindex : vToDownload) {
+ vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash()));
+ MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), pindex);
+ LogPrintf("Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(),
+ pindex->nHeight, pto->id);
+ }
+ if (state.nBlocksInFlight == 0 && staller != -1) {
+ if (State(staller)->nStallingSince == 0) {
+ State(staller)->nStallingSince = nNow;
+ LogPrint("net", "Stall started peer=%d\n", staller);
+ }
}
}
- }
- //
- // Message: getdata (non-blocks)
- //
- while (!pto->fDisconnect && !pto->mapAskFor.empty() && pto->mapAskFor.begin()->first <= nNow) {
- const CInv& inv = pto->mapAskFor.begin()->second;
- if (!AlreadyHave(inv)) {
- if (fDebug)
- LogPrint("net", "Requesting %s peer=%d\n", inv.ToString(), pto->id);
- vGetData.push_back(inv);
- if (vGetData.size() >= 1000) {
- pto->PushMessage("getdata", vGetData);
- vGetData.clear();
+ //
+ // Message: getdata (non-blocks)
+ //
+ while (!pto->fDisconnect && !pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow) {
+ const CInv& inv = (*pto->mapAskFor.begin()).second;
+ if (!AlreadyHave(inv)) {
+ if (fDebug)
+ LogPrint("net", "Requesting %s peer=%d\n", inv.ToString(), pto->id);
+ vGetData.push_back(inv);
+ if (vGetData.size() >= 1000) {
+ pto->PushMessage("getdata", vGetData);
+ vGetData.clear();
+ }
}
+ pto->mapAskFor.erase(pto->mapAskFor.begin());
}
- pto->mapAskFor.erase(pto->mapAskFor.begin());
- }
- if (!vGetData.empty())
- pto->PushMessage("getdata", vGetData);
+ if (!vGetData.empty())
+ pto->PushMessage("getdata", vGetData);
- return true;
+ return true;
}
diff --git a/src/main.h b/src/main.h
index 50e88f6..9c3ddc1 100644
--- a/src/main.h
+++ b/src/main.h
@@ -2,7 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -43,6 +43,7 @@
class CBlockIndex;
class CBlockTreeDB;
+class CSporkDB;
class CBloomFilter;
class CInv;
class CScriptCheck;
@@ -102,6 +103,17 @@ static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111;
/** Enable bloom filter */
static const bool DEFAULT_PEERBLOOMFILTERS = true;
+static const bool DEFAULT_PEERBLOOMFILTERS_ZC = false;
+
+/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
+static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
+
+/** Default for -blockspamfilter, use header spam filter */
+static const bool DEFAULT_BLOCK_SPAM_FILTER = true;
+/** Default for -blockspamfiltermaxsize, maximum size of the list of indexes in the block spam filter */
+static const unsigned int DEFAULT_BLOCK_SPAM_FILTER_MAX_SIZE = COINBASE_MATURITY;
+/** Default for -blockspamfiltermaxavg, maximum average size of an index occurrence in the block spam filter */
+static const unsigned int DEFAULT_BLOCK_SPAM_FILTER_MAX_AVG = 10;
/** "reject" message codes */
static const unsigned char REJECT_MALFORMED = 0x01;
@@ -137,6 +149,8 @@ extern bool fCheckBlockIndex;
extern unsigned int nCoinCacheSize;
extern CFeeRate minRelayTxFee;
extern bool fAlerts;
+extern bool fVerifyingBlocks;
+extern bool fClearSpendCache;
extern bool fLargeWorkForkFound;
extern bool fLargeWorkInvalidChainFound;
@@ -195,7 +209,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos* dbp = NULL);
/** Initialize a new block tree database + block data on disk */
bool InitBlockIndex();
/** Load the block tree and coins database from disk */
-bool LoadBlockIndex();
+bool LoadBlockIndex(std::string& strError);
/** Unload database information */
void UnloadBlockIndex();
/** See whether the protocol update is enforced for connected nodes */
@@ -221,7 +235,9 @@ bool IsInitialBlockDownload();
/** Format a string that describes several potential problems detected by the core */
std::string GetWarnings(std::string strFor);
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
-bool GetTransaction(const uint256& hash, CTransaction& tx, uint256& hashBlock, bool fAllowSlow = false);
+bool GetTransaction(const uint256& hash, CTransaction& tx, uint256& hashBlock, bool fAllowSlow = false, CBlockIndex* blockIndex = nullptr);
+/** Retrieve an output (from memory pool, or from disk, if possible) */
+bool GetOutput(const uint256& hash, unsigned int index, CValidationState& state, CTxOut& out);
/** Find the best known block, and make it the tip of the block chain */
bool DisconnectBlocksAndReprocess(int blocks);
@@ -230,7 +246,7 @@ bool DisconnectBlocksAndReprocess(int blocks);
double ConvertBitsToDouble(unsigned int nBits);
int64_t GetMasternodePayment(int nHeight, uint32_t nTime, unsigned mnlevel, int64_t blockValue);
-bool ActivateBestChain(CValidationState& state, CBlock* pblock = NULL);
+bool ActivateBestChain(CValidationState& state, CBlock* pblock = NULL, bool fAlreadyChecked = false);
CAmount GetBlockValue(int nHeight, uint32_t nTime);
/** Create a new block index entry for a given block hash */
@@ -342,6 +358,8 @@ void UpdateCoins(const CTransaction& tx, CValidationState& state, CCoinsViewCach
/** Context-independent validity checks */
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
+bool IsTransactionInChain(const uint256& txId, int& nHeightTx, CTransaction& tx);
+bool IsTransactionInChain(const uint256& txId, int& nHeightTx);
/**
* Check if transaction will be final in the next block to be created.
@@ -431,7 +449,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
bool DisconnectBlocksAndReprocess(int blocks);
/** Apply the effects of this block (with given index) on the UTXO set represented by coins */
-bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false);
+bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck, bool fAlreadyChecked = false);
/** Context-independent validity checks */
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true);
@@ -446,7 +464,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
bool TestBlockValidity(CValidationState& state, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
/** Store block on disk. If dbp is provided, the file is known to already reside on disk */
-bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** pindex, CDiskBlockPos* dbp = NULL);
+bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** pindex, CDiskBlockPos* dbp = NULL, bool fAlreadyCheckedBlock = false);
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex = NULL);
@@ -608,26 +626,13 @@ extern CCoinsViewCache* pcoinsTip;
/** Global variable that points to the active block tree (protected by cs_main) */
extern CBlockTreeDB* pblocktree;
+/** Global variable that points to the spork database (protected by cs_main) */
+extern CSporkDB* pSporkDB;
+
struct CBlockTemplate {
CBlock block;
std::vector vTxFees;
std::vector vTxSigOps;
};
-/*
-class CValidationInterface
-{
-protected:
- virtual void SyncTransaction(const CTransaction& tx, const CBlock* pblock){};
- virtual void EraseFromWallet(const uint256& hash){};
- virtual void SetBestChain(const CBlockLocator& locator){};
- virtual bool UpdatedTransaction(const uint256& hash) { return false; };
- virtual void Inventory(const uint256& hash){};
- virtual void ResendWalletTransactions(){};
- virtual void BlockChecked(const CBlock&, const CValidationState&){};
- friend void ::RegisterValidationInterface(CValidationInterface*);
- friend void ::UnregisterValidationInterface(CValidationInterface*);
- friend void ::UnregisterAllValidationInterfaces();
-};
-*/
#endif // BITCOIN_MAIN_H
diff --git a/src/masternode-payments.cpp b/src/masternode-payments.cpp
index 8fa8e13..04c7613 100644
--- a/src/masternode-payments.cpp
+++ b/src/masternode-payments.cpp
@@ -1,7 +1,7 @@
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
// Copyright (c) 2017-2018 The Bulwark developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -28,19 +28,19 @@ CCriticalSection cs_mapMasternodePayeeVotes;
bool IsBlockValueValid(const CBlock& block, CAmount nExpectedValue, CAmount nMinted)
{
CBlockIndex* pindexPrev = chainActive.Tip();
- if (!pindexPrev) return true;
+ if (pindexPrev == NULL) return true;
int nHeight = 0;
if (pindexPrev->GetBlockHash() == block.hashPrevBlock) {
nHeight = pindexPrev->nHeight + 1;
} else { //out of order
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
- if (mi != mapBlockIndex.end() && mi->second)
- nHeight = mi->second->nHeight + 1;
+ if (mi != mapBlockIndex.end() && (*mi).second)
+ nHeight = (*mi).second->nHeight + 1;
}
- if (!nHeight) {
- LogPrintf("IsBlockValueValid() : WARNING: Couldn't find previous block\n");
+ if (nHeight == 0) {
+ LogPrintf("masternode", "IsBlockValueValid() : WARNING: Couldn't find previous block\n");
}
if (nMinted > nExpectedValue) {
@@ -58,7 +58,7 @@ bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight)
}
// disable mn payments checks till fork activation
- if(Params().F2ActivationTime() <= block.nTime)
+ if(Params().F3Activation() >= nBlockHeight)
return true;
const CTransaction& txNew = (nBlockHeight > Params().LAST_POW_BLOCK() ? block.vtx[1] : block.vtx[0]);
@@ -106,7 +106,7 @@ CAmount CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, uint32_t
payee = GetScriptForDestination(winningNode->pubKeyCollateralAddress.GetID());
}
- CAmount masternodePayment = GetMasternodePayment(pindexPrev->nHeight, nTime, mnlevel, block_value);
+ CAmount masternodePayment = GetMasternodePayment(pindexPrev->nHeight + 1, nTime, mnlevel, block_value);
if(!masternodePayment)
continue;
@@ -123,6 +123,7 @@ CAmount CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, uint32_t
}
return mn_payments_total;
+
}
int CMasternodePayments::GetMinMasternodePaymentsProto()
@@ -136,6 +137,25 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
if (fLiteMode) return; //disable all Obfuscation/Masternode related functionality
+ if (strCommand == "mnget") { //Masternode Payments Request Sync
+
+ int nCountNeeded;
+ vRecv >> nCountNeeded;
+
+ if (Params().NetworkID() == CBaseChainParams::MAIN) {
+
+ if (pfrom->HasFulfilledRequest("mnget")) {
+ LogPrintf("mnget - peer already asked me for the list\n");
+ Misbehaving(pfrom->GetId(), 20);
+ return;
+ }
+ }
+
+ pfrom->FulfilledRequest("mnget");
+ masternodePayments.Sync(pfrom, nCountNeeded);
+ LogPrint("mnpayments", "mnget - Sent Masternode winners to peer %i\n", pfrom->GetId());
+ } else
+
if (strCommand == "mnw") { //Masternode Payments Declare Winner
//this is required in litemodef
CMasternodePaymentWinner winner;
@@ -169,15 +189,15 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
return;
}
- std::string strError = "";
- if (!winner.IsValid(pfrom, strError)) {
- // if(strError != "") LogPrintf("mnw - invalid message - %s\n", strError);
+ int nFirstBlock = nHeight - mnodeman.CountEnabled(winner.payeeLevel) / 100 * 125;
+ if (winner.nBlockHeight < nFirstBlock || winner.nBlockHeight > nHeight + 20) {
+ LogPrint("mnpayments", "mnw - winner out of range - FirstBlock %d Height %d bestHeight %d\n", nFirstBlock, winner.nBlockHeight, nHeight);
return;
}
- int nFirstBlock = nHeight - mnodeman.CountEnabled(winner.payeeLevel) * 125 / 100;
- if (winner.nBlockHeight < nFirstBlock || winner.nBlockHeight > nHeight + 20) {
- LogPrint("mnpayments", "mnw - winner out of range - FirstBlock %d Height %d bestHeight %d\n", nFirstBlock, winner.nBlockHeight, nHeight);
+ std::string strError = "";
+ if (!winner.IsValid(pfrom, strError)) {
+ // if(strError != "") LogPrintf("mnw - invalid message - %s\n", strError);
return;
}
@@ -208,17 +228,15 @@ bool CMasternodePaymentWinner::Sign(CKey& keyMasternode, CPubKey& pubKeyMasterno
std::string errorMessage;
std::string strMasterNodeSignMessage;
- std::string strMessage = vinMasternode.prevout.ToStringShort() +
- boost::lexical_cast(nBlockHeight) +
- payee.ToString();
+ std::string strMessage = vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + payee.ToString();
if (!obfuScationSigner.SignMessage(strMessage, errorMessage, vchSig, keyMasternode)) {
- LogPrintf("CMasternodePing::Sign() - Error: %s\n", errorMessage.c_str());
+ LogPrint("masternode","CMasternodePing::Sign() - Error: %s\n", errorMessage.c_str());
return false;
}
if (!obfuScationSigner.VerifyMessage(pubKeyMasternode, vchSig, strMessage, errorMessage)) {
- LogPrintf("CMasternodePing::Sign() - Error: %s\n", errorMessage.c_str());
+ LogPrint("masternode","CMasternodePing::Sign() - Error: %s\n", errorMessage.c_str());
return false;
}
@@ -236,7 +254,8 @@ bool CMasternodePayments::GetBlockPayee(int nBlockHeight, unsigned mnlevel, CScr
}
// Is this masternode scheduled to get paid soon?
-bool CMasternodePayments::IsScheduled(CMasternode& mn, int nSameLevelMNCount, int nNotBlockHeight) const
+// -- Only look ahead up to 8 blocks to allow for propagation of the latest 2 winners
+bool CMasternodePayments::IsScheduled(CMasternode& mn, int nNotBlockHeight)
{
LOCK(cs_mapMasternodeBlocks);
@@ -244,7 +263,7 @@ bool CMasternodePayments::IsScheduled(CMasternode& mn, int nSameLevelMNCount, in
{
TRY_LOCK(cs_main, locked);
- if(!locked)
+ if (!locked)
return false;
auto chain_tip = chainActive.Tip();
@@ -257,7 +276,7 @@ bool CMasternodePayments::IsScheduled(CMasternode& mn, int nSameLevelMNCount, in
CScript mnpayee = GetScriptForDestination(mn.pubKeyCollateralAddress.GetID());
- for(int64_t h_upper_bound = nHeight + 10, h = h_upper_bound - std::min(10, nSameLevelMNCount - 1); h < h_upper_bound; ++h) {
+ for(int64_t h = nHeight; h <= nHeight + 8; ++h) {
if(h == nNotBlockHeight)
continue;
@@ -283,7 +302,7 @@ bool CMasternodePayments::CanVote(const COutPoint& outMasternode, int nBlockHeig
{
LOCK(cs_mapMasternodePayeeVotes);
- uint256 key = ((outMasternode.hash + outMasternode.n) << 4) + mnlevel;
+ uint256 key = outMasternode.hash + outMasternode.n + mnlevel;
auto ins_res = mapMasternodesLastVote.emplace(key, nBlockHeight);
@@ -291,7 +310,7 @@ bool CMasternodePayments::CanVote(const COutPoint& outMasternode, int nBlockHeig
auto& last_vote = ins_res.first->second;
- if(last_vote >= nBlockHeight)
+ if(last_vote <= nBlockHeight)
return false;
last_vote = nBlockHeight;
@@ -391,7 +410,7 @@ bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew, uint3
strPayeesPossible += "," + address2;
}
- LogPrintf("CMasternodePayments::IsTransactionValid - Missing required payment to %s\n", strPayeesPossible.c_str());
+ LogPrint("masternode","CMasternodePayments::IsTransactionValid - Missing required payment to %s\n", strPayeesPossible.c_str());
return false;
}
@@ -450,22 +469,22 @@ void CMasternodePayments::CleanPaymentList()
int nHeight;
{
TRY_LOCK(cs_main, locked);
- if (!locked || !chainActive.Tip()) return;
+ if (!locked || chainActive.Tip() == NULL) return;
nHeight = chainActive.Tip()->nHeight;
}
//keep up to five cycles for historical sake
- int nLimit = std::max(mnodeman.size() * 125 / 100, 1000);
+ int nLimit = std::max(int(mnodeman.size() * 1.25), 1000);
std::map::iterator it = mapMasternodePayeeVotes.begin();
while (it != mapMasternodePayeeVotes.end()) {
- CMasternodePaymentWinner winner = it->second;
+ CMasternodePaymentWinner winner = (*it).second;
if (nHeight - winner.nBlockHeight > nLimit) {
LogPrint("mnpayments", "CMasternodePayments::CleanPaymentList - Removing old Masternode payment - block %d\n", winner.nBlockHeight);
- masternodeSync.mapSeenSyncMNW.erase(it->first);
+ masternodeSync.mapSeenSyncMNW.erase((*it).first);
+ mapMasternodePayeeVotes.erase(it++);
mapMasternodeBlocks.erase(winner.nBlockHeight);
- it = mapMasternodePayeeVotes.erase(it);
} else {
++it;
}
@@ -478,14 +497,14 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError)
if (!pmn) {
strError = strprintf("Unknown Masternode %s", vinMasternode.prevout.hash.ToString());
- LogPrintf("CMasternodePaymentWinner::IsValid - %s\n", strError);
+ LogPrint("masternode","CMasternodePaymentWinner::IsValid - %s\n", strError);
mnodeman.AskForMN(pnode, vinMasternode);
return false;
}
if (pmn->protocolVersion < ActiveProtocol()) {
strError = strprintf("Masternode protocol too old %d - req %d", pmn->protocolVersion, ActiveProtocol());
- LogPrintf("CMasternodePaymentWinner::IsValid - %s\n", strError);
+ LogPrint("masternode","CMasternodePaymentWinner::IsValid - %s\n", strError);
return false;
}
@@ -493,7 +512,7 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError)
if(n == -1) {
strError = strprintf("Unknown Masternode (rank==-1) %s", vinMasternode.prevout.hash.ToString());
- LogPrintf("CMasternodePaymentWinner::IsValid - %s\n", strError);
+ LogPrint("masternode","CMasternodePaymentWinner::IsValid - %s\n", strError);
return false;
}
@@ -502,7 +521,7 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError)
// We don't want to print all of these messages, or punish them unless they're way off
if (n > MNPAYMENTS_SIGNATURES_TOTAL * 2) {
strError = strprintf("Masternode not in the top %d (%d)", MNPAYMENTS_SIGNATURES_TOTAL * 2, n);
- LogPrintf("CMasternodePaymentWinner::IsValid - %s\n", strError);
+ LogPrint("masternode","CMasternodePaymentWinner::IsValid - %s\n", strError);
if (masternodeSync.IsSynced()) Misbehaving(pnode->GetId(), 20);
}
return false;
@@ -516,14 +535,12 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
if(!fMasterNode)
return false;
- auto nWinnerBlockHeight = nBlockHeight + 10;
-
//reference node - hybrid mode
- if(nWinnerBlockHeight <= nLastBlockHeight)
+ if(nBlockHeight <= nLastBlockHeight)
return false;
- int n = mnodeman.GetMasternodeRank(activeMasternode.vin, nWinnerBlockHeight - 100, ActiveProtocol());
+ int n = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight - 100, ActiveProtocol());
if(n == -1) {
LogPrint("mnpayments", "CMasternodePayments::ProcessBlock - Unknown Masternode\n");
@@ -535,7 +552,7 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
return false;
}
- LogPrintf("CMasternodePayments::ProcessBlock() Start nHeight %d - vin %s. \n", nWinnerBlockHeight, activeMasternode.vin.prevout.hash.ToString());
+ LogPrint("masternode","CMasternodePayments::ProcessBlock() Start nHeight %d - vin %s. \n", nBlockHeight, activeMasternode.vin.prevout.hash.ToString());
// pay to the oldest MN that still had no payment but its input is old enough and it was active long enough
std::string errorMessage;
@@ -543,7 +560,7 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
CKey keyMasternode;
if (!obfuScationSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode)) {
- LogPrintf("CMasternodePayments::ProcessBlock() - Error upon calling SetKey: %s\n", errorMessage.c_str());
+ LogPrint("masternode","CMasternodePayments::ProcessBlock() - Error upon calling SetKey: %s\n", errorMessage.c_str());
return false;
}
@@ -553,32 +570,32 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
unsigned nCount = 0;
- auto pmn = mnodeman.GetNextMasternodeInQueueForPayment(nWinnerBlockHeight, mnlevel, true, nCount);
+ auto pmn = mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, mnlevel, true, nCount);
if(!pmn) {
- LogPrintf("CMasternodePayments::ProcessBlock() Failed to find masternode level %d to pay \n", mnlevel);
+ LogPrint("masternode","CMasternodePayments::ProcessBlock() Failed to find masternode level %d to pay \n", mnlevel);
continue;
}
auto payee = GetScriptForDestination(pmn->pubKeyCollateralAddress.GetID());
- CMasternodePaymentWinner newWinner{activeMasternode.vin};
- newWinner.nBlockHeight = nWinnerBlockHeight;
+ CMasternodePaymentWinner newWinner{activeMasternode.vin};
+ newWinner.nBlockHeight = nBlockHeight;
newWinner.AddPayee(payee, mnlevel);
CTxDestination address1;
ExtractDestination(payee, address1);
CBitcoinAddress address2{address1};
- LogPrintf("CMasternodePayments::ProcessBlock() Winner payee %s nHeight %d level %d. \n", address2.ToString().c_str(), newWinner.nBlockHeight, mnlevel);
+ LogPrint("masternode","CMasternodePayments::ProcessBlock() Winner payee %s nHeight %d level %d. \n", address2.ToString().c_str(), newWinner.nBlockHeight, mnlevel);
- LogPrintf("CMasternodePayments::ProcessBlock() - Signing Winner level %d\n", mnlevel);
+ LogPrint("masternode","CMasternodePayments::ProcessBlock() - Signing Winner level %d\n", mnlevel);
if(!newWinner.Sign(keyMasternode, pubKeyMasternode))
continue;
- LogPrintf("CMasternodePayments::ProcessBlock() - AddWinningMasternode level %d\n", mnlevel);
+ LogPrint("masternode","CMasternodePayments::ProcessBlock() - AddWinningMasternode level %d\n", mnlevel);
if(!AddWinningMasternode(newWinner))
continue;
@@ -593,7 +610,7 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
winner.Relay();
}
- nLastBlockHeight = nWinnerBlockHeight;
+ nLastBlockHeight = nBlockHeight;
return true;
}
@@ -608,20 +625,18 @@ bool CMasternodePaymentWinner::SignatureValid()
{
CMasternode* pmn = mnodeman.Find(vinMasternode);
- if (!pmn)
- return false;
-
- std::string strMessage = vinMasternode.prevout.ToStringShort() +
- boost::lexical_cast(nBlockHeight) +
- payee.ToString();
+ if (pmn != NULL) {
+ std::string strMessage = vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + payee.ToString();
- std::string errorMessage;
+ std::string errorMessage = "";
+ if (!obfuScationSigner.VerifyMessage(pmn->pubKeyMasternode, vchSig, strMessage, errorMessage)) {
+ return error("CMasternodePaymentWinner::SignatureValid() - Got bad Masternode address signature %s\n", vinMasternode.prevout.hash.ToString());
+ }
- if (!obfuScationSigner.VerifyMessage(pmn->pubKeyMasternode, vchSig, strMessage, errorMessage)) {
- return error("CMasternodePaymentWinner::SignatureValid() - Got bad Masternode address signature %s\n", vinMasternode.prevout.hash.ToString());
- }
+ return true;
+}
- return true;
+ return false;
}
void CMasternodePayments::Sync(CNode* node, int nCountNeeded)
@@ -631,39 +646,30 @@ void CMasternodePayments::Sync(CNode* node, int nCountNeeded)
int nHeight;
{
TRY_LOCK(cs_main, locked);
- if(!locked || !chainActive.Tip())
- return;
-
+ if (!locked || chainActive.Tip() == NULL) return;
nHeight = chainActive.Tip()->nHeight;
}
auto mn_counts = mnodeman.CountEnabledByLevels();
-
unsigned max_mn_count = 0u;
- for(auto& count : mn_counts)
- max_mn_count = std::max(max_mn_count, count.second * 125 / 100);
-
- if(max_mn_count > nCountNeeded)
- max_mn_count = nCountNeeded;
+ for(auto& count : mn_counts) {
+ max_mn_count = std::max(max_mn_count, unsigned(count.second * 1.25));
+ count.second = unsigned(count.second * 1.25) + 1;
+ }
+ if(max_mn_count > nCountNeeded) max_mn_count = nCountNeeded;
int nInvCount = 0;
for(const auto& vote : mapMasternodePayeeVotes) {
-
- const auto& winner = vote.second;
-
- bool push = winner.nBlockHeight >= nHeight - max_mn_count
- && winner.nBlockHeight <= nHeight + 20;
-
- if(!push)
- continue;
-
- node->PushInventory(CInv(MSG_MASTERNODE_WINNER, winner.GetHash()));
- ++nInvCount;
- }
-
- node->PushMessage("ssc", MASTERNODE_SYNC_MNW, nInvCount);
+ const auto& winner = vote.second;
+ bool push = winner.nBlockHeight >= nHeight - max_mn_count && winner.nBlockHeight <= nHeight + 20;
+ if(!push)
+ continue;
+ node->PushInventory(CInv(MSG_MASTERNODE_WINNER, winner.GetHash()));
+ ++nInvCount;
+ }
+ node->PushMessage("ssc", MASTERNODE_SYNC_MNW, nInvCount);
}
std::string CMasternodePayments::ToString() const
diff --git a/src/masternode-payments.h b/src/masternode-payments.h
index 66c4487..dd806e8 100644
--- a/src/masternode-payments.h
+++ b/src/masternode-payments.h
@@ -242,7 +242,7 @@ class CMasternodePayments
bool GetBlockPayee(int nBlockHeight, unsigned mnlevel, CScript& payee);
bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight, uint32_t nTime);
- bool IsScheduled(CMasternode& mn, int nSameLevelMNCount, int nNotBlockHeight) const;
+ bool IsScheduled(CMasternode& mn, int nNotBlockHeight);
bool CanVote(const COutPoint& outMasternode, int nBlockHeight, unsigned mnlevel);
int GetMinMasternodePaymentsProto();
diff --git a/src/masternode-sync.cpp b/src/masternode-sync.cpp
index 357c6e2..1369139 100644
--- a/src/masternode-sync.cpp
+++ b/src/masternode-sync.cpp
@@ -49,8 +49,8 @@ bool CMasternodeSync::IsBlockchainSynced()
if (!lockMain) return false;
CBlockIndex* pindex = chainActive.Tip();
+ if (pindex == NULL) return false;
- if (!pindex) return false;
if (pindex->nTime + 60 * 60 < GetTime())
return false;
@@ -126,7 +126,7 @@ void CMasternodeSync::GetNextAsset()
RequestedMasternodeAssets = MASTERNODE_SYNC_MNW;
break;
case (MASTERNODE_SYNC_MNW):
- LogPrintf("CMasternodeSync::GetNextAsset - Sync has finished\n");
+ LogPrint("masternode","CMasternodeSync::GetNextAsset - Sync has finished\n");
RequestedMasternodeAssets = MASTERNODE_SYNC_FINISHED;
break;
}
@@ -217,19 +217,11 @@ void CMasternodeSync::Process()
LogPrint("masternode", "CMasternodeSync::Process() - tick %d RequestedMasternodeAssets %d\n", tick, RequestedMasternodeAssets);
- if (RequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL)
- GetNextAsset();
+ if (RequestedMasternodeAssets == MASTERNODE_SYNC_INITIAL) GetNextAsset();
// sporks synced but blockchain is not, wait until we're almost at a recent block to continue
- bool wait_blockchain_sync = Params().NetworkID() != CBaseChainParams::REGTEST
- && !IsBlockchainSynced()
- && RequestedMasternodeAssets > MASTERNODE_SYNC_SPORKS;
-
- if(wait_blockchain_sync)
- {
- nAssetSyncStarted = GetTime();
- return;
- }
+ if (Params().NetworkID() != CBaseChainParams::REGTEST &&
+ !IsBlockchainSynced() && RequestedMasternodeAssets > MASTERNODE_SYNC_SPORKS) return;
TRY_LOCK(cs_vNodes, lockRecv);
if (!lockRecv) return;
@@ -252,18 +244,13 @@ void CMasternodeSync::Process()
//set to synced
if (RequestedMasternodeAssets == MASTERNODE_SYNC_SPORKS) {
- if (pnode->HasFulfilledRequest("getspork"))
- continue;
-
- if (RequestedMasternodeAttempt >= MASTERNODE_SYNC_THRESHOLD) {
- GetNextAsset();
- return;
- }
-
+ if (pnode->HasFulfilledRequest("getspork")) continue;
pnode->FulfilledRequest("getspork");
pnode->PushMessage("getsporks"); //get current network sporks
+ if (RequestedMasternodeAttempt >= 2) GetNextAsset();
RequestedMasternodeAttempt++;
+
return;
}
@@ -275,9 +262,7 @@ void CMasternodeSync::Process()
return;
}
- if (pnode->HasFulfilledRequest("mnsync"))
- continue;
-
+ if (pnode->HasFulfilledRequest("mnsync")) continue;
pnode->FulfilledRequest("mnsync");
// timeout
@@ -295,29 +280,20 @@ void CMasternodeSync::Process()
return;
}
- if (RequestedMasternodeAttempt >= MASTERNODE_SYNC_THRESHOLD * 3)
- return;
-
- if(!mnodeman.DsegUpdate(pnode))
- continue;
-
- ++RequestedMasternodeAttempt;
+ if (RequestedMasternodeAttempt >= MASTERNODE_SYNC_THRESHOLD * 3) return;
+ mnodeman.DsegUpdate(pnode);
+ RequestedMasternodeAttempt++;
return;
}
if (RequestedMasternodeAssets == MASTERNODE_SYNC_MNW) {
-
if (lastMasternodeWinner > 0 && lastMasternodeWinner < GetTime() - MASTERNODE_SYNC_TIMEOUT * 2 && RequestedMasternodeAttempt >= MASTERNODE_SYNC_THRESHOLD) { //hasn't received a new item in the last five seconds, so we'll move to the
GetNextAsset();
- // Try to activate our masternode if possible
- activeMasternode.ManageStatus();
return;
}
- if (pnode->HasFulfilledRequest("mnwsync"))
- continue;
-
+ if (pnode->HasFulfilledRequest("mnwsync")) continue;
pnode->FulfilledRequest("mnwsync");
// timeout
@@ -331,25 +307,36 @@ void CMasternodeSync::Process()
nCountFailures++;
} else {
GetNextAsset();
- // Try to activate our masternode if possible
- activeMasternode.ManageStatus();
}
return;
}
- if (RequestedMasternodeAttempt >= MASTERNODE_SYNC_THRESHOLD * 3)
- return;
+ if (RequestedMasternodeAttempt >= MASTERNODE_SYNC_THRESHOLD * 3) return;
- if (!chainActive.Tip())
- return;
+ CBlockIndex* pindexPrev = chainActive.Tip();
+ if (pindexPrev == NULL) return;
- if(!mnodeman.WinnersUpdate(pnode))
- continue;
+ int nMnCount = mnodeman.CountEnabled();
+ pnode->PushMessage("mnget", nMnCount); //sync payees
+ RequestedMasternodeAttempt++;
- ++RequestedMasternodeAttempt;
+ return;
+ }
+ }
+ if (pnode->nVersion >= ActiveProtocol()) {
+ if ((RequestedMasternodeAttempt >= MASTERNODE_SYNC_THRESHOLD * 3 || GetTime() - nAssetSyncStarted > MASTERNODE_SYNC_TIMEOUT * 5)) {
+ GetNextAsset();
+ activeMasternode.ManageStatus();
return;
}
+ if (RequestedMasternodeAttempt >= MASTERNODE_SYNC_THRESHOLD * 3) return;
+
+ if(!mnodeman.WinnersUpdate(pnode)) continue;
+
+ RequestedMasternodeAttempt++;
+
+ return;
}
}
}
diff --git a/src/masternode.cpp b/src/masternode.cpp
index 4285286..b143e12 100644
--- a/src/masternode.cpp
+++ b/src/masternode.cpp
@@ -1,6 +1,6 @@
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,6 +10,7 @@
#include "obfuscation.h"
#include "sync.h"
#include "util.h"
+#include "spork.h"
#include
@@ -254,9 +255,7 @@ int64_t CMasternode::SecondsSincePayment()
int64_t CMasternode::GetLastPaid()
{
CBlockIndex* pindexPrev = chainActive.Tip();
-
- if (!pindexPrev)
- return 0;
+ if (pindexPrev == NULL) return false;
CScript mnpayee;
mnpayee = GetScriptForDestination(pubKeyCollateralAddress.GetID());
@@ -266,12 +265,14 @@ int64_t CMasternode::GetLastPaid()
ss << sigTime;
uint256 hash = ss.GetHash();
- // use a deterministic offset to break a tie -- 1.5 minutes
- int64_t nOffset = hash.GetCompact(false) % 90;
+ // use a deterministic offset to break a tie -- 2.5 minutes
+ int64_t nOffset = hash.GetCompact(false) % 150;
- const CBlockIndex* BlockReading = pindexPrev;
+ if (chainActive.Tip() == NULL) return false;
- int nMnCount = mnodeman.CountEnabled(Level()) * 125 / 100;
+ const CBlockIndex* BlockReading = chainActive.Tip();
+
+ int nMnCount = mnodeman.CountEnabled(Level()) * 1.25;
int n = 0;
for (unsigned int i = 1; BlockReading && BlockReading->nHeight > 0; i++) {
if (n >= nMnCount) {
@@ -285,16 +286,40 @@ int64_t CMasternode::GetLastPaid()
to converge on the same payees quickly, then keep the same schedule.
*/
if (masternodePayments.mapMasternodeBlocks[BlockReading->nHeight].HasPayeeWithVotes(mnpayee, 2)) {
- return BlockReading->nTime - nOffset;
+ return BlockReading->nTime + nOffset;
}
}
+ if (BlockReading->pprev == NULL) {
+ assert(BlockReading);
+ break;
+ }
BlockReading = BlockReading->pprev;
}
return 0;
}
+std::string CMasternode::GetStatus()
+{
+ switch (nActiveState) {
+ case CMasternode::MASTERNODE_PRE_ENABLED:
+ return "PRE_ENABLED";
+ case CMasternode::MASTERNODE_ENABLED:
+ return "ENABLED";
+ case CMasternode::MASTERNODE_EXPIRED:
+ return "EXPIRED";
+ case CMasternode::MASTERNODE_OUTPOINT_SPENT:
+ return "OUTPOINT_SPENT";
+ case CMasternode::MASTERNODE_REMOVE:
+ return "REMOVE";
+ case CMasternode::MASTERNODE_POSE_BAN:
+ return "POSE_BAN";
+ default:
+ return "UNKNOWN";
+ }
+}
+
bool CMasternode::IsValidNetAddr()
{
// TODO: regtest is fine with any addresses for now,
@@ -303,30 +328,37 @@ bool CMasternode::IsValidNetAddr()
(IsReachable(addr) && addr.IsRoutable());
}
-unsigned CMasternode::Level(CAmount vin_val)
+unsigned CMasternode::Level(CAmount vin_val, int blockHeight)
{
- switch(vin_val) {
- case 1000 * COIN: return 1;
- case 3000 * COIN: return 2;
- case 5000 * COIN: return 3;
+ if (blockHeight >= 0 && blockHeight < 682500) {
+ switch(vin_val) {
+ case 1000 * COIN: return 1;
+ case 3000 * COIN: return 2;
+ case 5000 * COIN: return 3;
+ }
+ } else if (blockHeight >= 682500) {
+ switch(vin_val) {
+ case 5000 * COIN: return 1;
+ case 10000 * COIN: return 2;
+ case 50000 * COIN: return 3;
+ }
}
-
return 0;
}
-unsigned CMasternode::Level(const CTxIn& vin)
+unsigned CMasternode::Level(const CTxIn& vin, int blockHeight)
{
CAmount vin_val;
if(!IsDepositCoins(vin, vin_val))
return LevelValue::UNSPECIFIED;
- return Level(vin_val);
+ return Level(vin_val, blockHeight);
}
bool CMasternode::IsDepositCoins(CAmount vin_val)
{
- return Level(vin_val);
+ return Level(vin_val, chainActive.Height());
}
bool CMasternode::IsDepositCoins(const CTxIn& vin, CAmount& vin_val)
@@ -413,19 +445,19 @@ bool CMasternodeBroadcast::Create(std::string strService, std::string strKeyMast
//need correct blocks to send ping
if (!fOffline && !masternodeSync.IsBlockchainSynced()) {
strErrorRet = "Sync in progress. Must wait until sync is complete to start Masternode";
- LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
+ LogPrint("masternode","CMasternodeBroadcast::Create -- %s\n", strErrorRet);
return false;
}
if (!obfuScationSigner.GetKeysFromSecret(strKeyMasternode, keyMasternodeNew, pubKeyMasternodeNew)) {
strErrorRet = strprintf("Invalid masternode key %s", strKeyMasternode);
- LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
+ LogPrint("masternode","CMasternodeBroadcast::Create -- %s\n", strErrorRet);
return false;
}
if (!pwalletMain->GetMasternodeVinAndKeys(txin, pubKeyCollateralAddressNew, keyCollateralAddressNew, strTxHash, strOutputIndex)) {
strErrorRet = strprintf("Could not allocate txin %s:%s for masternode %s", strTxHash, strOutputIndex, strService);
- LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
+ LogPrint("masternode","CMasternodeBroadcast::Create -- %s\n", strErrorRet);
return false;
}
@@ -447,7 +479,7 @@ bool CMasternodeBroadcast::Create(CTxIn txin, CService service, CKey keyCollater
if(mnode && mnode->vin != txin)
{
strErrorRet = strprintf("Duplicate Masternode address: %s", service.ToString());
- LogPrintf("CMasternodeBroadcast::Create -- ActiveMasternode::Register() - %s\n", strErrorRet);
+ LogPrint("masternode","CMasternodeBroadcast::Create -- ActiveMasternode::Register() - %s\n", strErrorRet);
mnbRet = CMasternodeBroadcast();
return false;
}
@@ -460,7 +492,7 @@ bool CMasternodeBroadcast::Create(CTxIn txin, CService service, CKey keyCollater
CMasternodePing mnp(txin);
if (!mnp.Sign(keyMasternodeNew, pubKeyMasternodeNew)) {
strErrorRet = strprintf("Failed to sign ping, masternode=%s", txin.prevout.hash.ToString());
- LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
+ LogPrint("masternode","CMasternodeBroadcast::Create -- %s\n", strErrorRet);
mnbRet = CMasternodeBroadcast();
return false;
}
@@ -469,7 +501,7 @@ bool CMasternodeBroadcast::Create(CTxIn txin, CService service, CKey keyCollater
if (!mnbRet.IsValidNetAddr()) {
strErrorRet = strprintf("Invalid IP address %s, masternode=%s", mnbRet.addr.ToStringIP (), txin.prevout.hash.ToString());
- LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
+ LogPrint("masternode","CMasternodeBroadcast::Create -- %s\n", strErrorRet);
mnbRet = CMasternodeBroadcast();
return false;
}
@@ -477,7 +509,7 @@ bool CMasternodeBroadcast::Create(CTxIn txin, CService service, CKey keyCollater
mnbRet.lastPing = mnp;
if (!mnbRet.Sign(keyCollateralAddressNew)) {
strErrorRet = strprintf("Failed to sign broadcast, masternode=%s", txin.prevout.hash.ToString());
- LogPrintf("CMasternodeBroadcast::Create -- %s\n", strErrorRet);
+ LogPrint("masternode","CMasternodeBroadcast::Create -- %s\n", strErrorRet);
mnbRet = CMasternodeBroadcast();
return false;
}
@@ -508,7 +540,7 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
{
// make sure signature isn't in the future (past is OK)
if (sigTime > GetAdjustedTime() + 60 * 60) {
- LogPrintf("mnb - Signature rejected, too far into the future %s\n", vin.prevout.hash.ToString());
+ LogPrint("masternode","mnb - Signature rejected, too far into the future %s\n", vin.prevout.hash.ToString());
nDos = 1;
return false;
}
@@ -518,7 +550,7 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
std::string strMessage = addr.ToString() + boost::lexical_cast(sigTime) + vchPubKey + vchPubKey2 + boost::lexical_cast(protocolVersion);
if (protocolVersion < masternodePayments.GetMinMasternodePaymentsProto()) {
- LogPrintf("mnb - ignoring outdated Masternode %s protocol version %d\n", vin.prevout.hash.ToString(), protocolVersion);
+ LogPrint("masternode","mnb - ignoring outdated Masternode %s protocol version %d\n", vin.prevout.hash.ToString(), protocolVersion);
return false;
}
@@ -526,7 +558,7 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
pubkeyScript = GetScriptForDestination(pubKeyCollateralAddress.GetID());
if (pubkeyScript.size() != 25) {
- LogPrintf("mnb - pubkey the wrong size\n");
+ LogPrint("masternode","mnb - pubkey the wrong size\n");
nDos = 100;
return false;
}
@@ -535,20 +567,20 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
pubkeyScript2 = GetScriptForDestination(pubKeyMasternode.GetID());
if (pubkeyScript2.size() != 25) {
- LogPrintf("mnb - pubkey2 the wrong size\n");
+ LogPrint("masternode","mnb - pubkey2 the wrong size\n");
nDos = 100;
return false;
}
if (!vin.scriptSig.empty()) {
- LogPrintf("mnb - Ignore Not Empty ScriptSig %s\n", vin.prevout.hash.ToString());
+ LogPrint("masternode","mnb - Ignore Not Empty ScriptSig %s\n", vin.prevout.hash.ToString());
return false;
}
std::string errorMessage = "";
if (!obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, strMessage, errorMessage)) {
- LogPrintf("mnb - Got bad Masternode address signature\n");
+ LogPrint("masternode","mnb - Got bad Masternode address signature\n");
nDos = 100;
return false;
}
@@ -565,7 +597,7 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
// this broadcast older than we have, it's bad.
if (pmn->sigTime > sigTime) {
- LogPrintf("mnb - Bad sigTime %d for Masternode %s (existing broadcast is at %d)\n",
+ LogPrint("masternode","mnb - Bad sigTime %d for Masternode %s (existing broadcast is at %d)\n",
sigTime, vin.prevout.hash.ToString(), pmn->sigTime);
return false;
}
@@ -642,7 +674,7 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS)
LogPrint("masternode", "mnb - Accepted Masternode entry\n");
if (GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS) {
- LogPrintf("mnb - Input must have at least %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS);
+ LogPrint("masternode","mnb - Input must have at least %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS);
// maybe we miss few blocks, let this mnb to be checked again later
mnodeman.mapSeenMasternodeBroadcast.erase(GetHash());
masternodeSync.mapSeenSyncMNB.erase(GetHash());
@@ -659,7 +691,7 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS)
CBlockIndex* pMNIndex = mi->second; // block for 1000 XDNA tx -> 1 confirmation
CBlockIndex* pConfIndex = chainActive[pMNIndex->nHeight + MASTERNODE_MIN_CONFIRMATIONS - 1]; // block where tx got MASTERNODE_MIN_CONFIRMATIONS
if (pConfIndex->GetBlockTime() > sigTime) {
- LogPrintf("mnb - Bad sigTime %d for Masternode %s (%i conf block is at %d)\n",
+ LogPrint("masternode","mnb - Bad sigTime %d for Masternode %s (%i conf block is at %d)\n",
sigTime, vin.prevout.hash.ToString(), MASTERNODE_MIN_CONFIRMATIONS, pConfIndex->GetBlockTime()
);
@@ -667,7 +699,7 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDoS)
}
}
- LogPrintf("mnb - Got NEW Masternode entry - %s - %lli \n", vin.prevout.hash.ToString(), sigTime);
+ LogPrint("masternode","mnb - Got NEW Masternode entry - %s - %lli \n", vin.prevout.hash.ToString(), sigTime);
CMasternode mn(*this);
mnodeman.Add(mn);
@@ -705,18 +737,49 @@ bool CMasternodeBroadcast::Sign(CKey& keyCollateralAddress)
std::string strMessage = addr.ToString() + boost::lexical_cast(sigTime) + vchPubKey + vchPubKey2 + boost::lexical_cast(protocolVersion);
if (!obfuScationSigner.SignMessage(strMessage, errorMessage, sig, keyCollateralAddress)) {
- LogPrintf("CMasternodeBroadcast::Sign() - Error: %s\n", errorMessage);
+ LogPrint("masternode","CMasternodeBroadcast::Sign() - Error: %s\n", errorMessage);
return false;
}
if (!obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, strMessage, errorMessage)) {
- LogPrintf("CMasternodeBroadcast::Sign() - Error: %s\n", errorMessage);
+ LogPrint("masternode","CMasternodeBroadcast::Sign() - Error: %s\n", errorMessage);
return false;
}
return true;
}
+bool CMasternodeBroadcast::VerifySignature()
+{
+ std::string errorMessage;
+
+ if(!obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, GetNewStrMessage(), errorMessage)
+ && !obfuScationSigner.VerifyMessage(pubKeyCollateralAddress, sig, GetOldStrMessage(), errorMessage))
+ return error("CMasternodeBroadcast::VerifySignature() - Error: %s", errorMessage);
+
+ return true;
+}
+
+std::string CMasternodeBroadcast::GetOldStrMessage()
+{
+ std::string strMessage;
+
+ std::string vchPubKey(pubKeyCollateralAddress.begin(), pubKeyCollateralAddress.end());
+ std::string vchPubKey2(pubKeyMasternode.begin(), pubKeyMasternode.end());
+ strMessage = addr.ToString() + std::to_string(sigTime) + vchPubKey + vchPubKey2 + std::to_string(protocolVersion);
+
+ return strMessage;
+}
+
+std:: string CMasternodeBroadcast::GetNewStrMessage()
+{
+ std::string strMessage;
+
+ strMessage = addr.ToString() + std::to_string(sigTime) + pubKeyCollateralAddress.GetID().ToString() + pubKeyMasternode.GetID().ToString() + std::to_string(protocolVersion);
+
+ return strMessage;
+}
+
CMasternodePing::CMasternodePing()
{
vin = CTxIn();
@@ -743,12 +806,12 @@ bool CMasternodePing::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode)
std::string strMessage = vin.ToString() + blockHash.ToString() + boost::lexical_cast(sigTime);
if (!obfuScationSigner.SignMessage(strMessage, errorMessage, vchSig, keyMasternode)) {
- LogPrintf("CMasternodePing::Sign() - Error: %s\n", errorMessage);
+ LogPrint("masternode","CMasternodePing::Sign() - Error: %s\n", errorMessage);
return false;
}
if (!obfuScationSigner.VerifyMessage(pubKeyMasternode, vchSig, strMessage, errorMessage)) {
- LogPrintf("CMasternodePing::Sign() - Error: %s\n", errorMessage);
+ LogPrint("masternode","CMasternodePing::Sign() - Error: %s\n", errorMessage);
return false;
}
@@ -758,13 +821,13 @@ bool CMasternodePing::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode)
bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireEnabled)
{
if (sigTime > GetAdjustedTime() + 60 * 60) {
- LogPrintf("CMasternodePing::CheckAndUpdate - Signature rejected, too far into the future %s\n", vin.prevout.hash.ToString());
+ LogPrint("masternode","CMasternodePing::CheckAndUpdate - Signature rejected, too far into the future %s\n", vin.prevout.hash.ToString());
nDos = 1;
return false;
}
if (sigTime <= GetAdjustedTime() - 60 * 60) {
- LogPrintf("CMasternodePing::CheckAndUpdate - Signature rejected, too far into the past %s - %d %d \n", vin.prevout.hash.ToString(), sigTime, GetAdjustedTime());
+ LogPrint("masternode","CMasternodePing::CheckAndUpdate - Signature rejected, too far into the past %s - %d %d \n", vin.prevout.hash.ToString(), sigTime, GetAdjustedTime());
nDos = 1;
return false;
}
@@ -773,6 +836,7 @@ bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireEnabled)
// see if we have this Masternode
CMasternode* pmn = mnodeman.Find(vin);
+
if (pmn != NULL && pmn->protocolVersion >= masternodePayments.GetMinMasternodePaymentsProto()) {
if (fRequireEnabled && !pmn->IsEnabled()) return false;
@@ -784,7 +848,7 @@ bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireEnabled)
std::string errorMessage = "";
if (!obfuScationSigner.VerifyMessage(pmn->pubKeyMasternode, vchSig, strMessage, errorMessage)) {
- LogPrintf("CMasternodePing::CheckAndUpdate - Got bad Masternode address signature %s\n", vin.prevout.hash.ToString());
+ LogPrint("masternode","CMasternodePing::CheckAndUpdate - Got bad Masternode address signature %s\n", vin.prevout.hash.ToString());
nDos = 33;
return false;
}
@@ -792,14 +856,14 @@ bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireEnabled)
BlockMap::iterator mi = mapBlockIndex.find(blockHash);
if (mi != mapBlockIndex.end() && (*mi).second) {
if ((*mi).second->nHeight < chainActive.Height() - 24) {
- LogPrintf("CMasternodePing::CheckAndUpdate - Masternode %s block hash %s is too old\n", vin.prevout.hash.ToString(), blockHash.ToString());
+ LogPrint("masternode","CMasternodePing::CheckAndUpdate - Masternode %s block hash %s is too old\n", vin.prevout.hash.ToString(), blockHash.ToString());
// Do nothing here (no Masternode update, no mnping relay)
// Let this node to be visible but fail to accept mnping
return false;
}
} else {
- if (fDebug) LogPrintf("CMasternodePing::CheckAndUpdate - Masternode %s block hash %s is unknown\n", vin.prevout.hash.ToString(), blockHash.ToString());
+ if (fDebug) LogPrint("masternode","CMasternodePing::CheckAndUpdate - Masternode %s block hash %s is unknown\n", vin.prevout.hash.ToString(), blockHash.ToString());
// maybe we stuck so we shouldn't ban this node, just fail to accept it
// TODO: or should we also request this block?
@@ -815,6 +879,13 @@ bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireEnabled)
mnodeman.mapSeenMasternodeBroadcast[hash].lastPing = *this;
}
+ if (IsSporkActive(SPORK_7_MN_REBROADCAST_ENFORCEMENT)) {
+ //dirty hack //
+ pmn->UpdateFromNewBroadcast(mnb);
+ mnb.Relay();
+ //////////////
+ }
+
pmn->Check(true);
if (!pmn->IsEnabled()) return false;
diff --git a/src/masternode.h b/src/masternode.h
index 70f8d2b..c5007bf 100644
--- a/src/masternode.h
+++ b/src/masternode.h
@@ -1,6 +1,6 @@
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -16,11 +16,11 @@
#include "util.h"
#define MASTERNODE_MIN_CONFIRMATIONS 15
-#define MASTERNODE_MIN_MNP_SECONDS (4 * 60)
+#define MASTERNODE_MIN_MNP_SECONDS (10 * 60)
#define MASTERNODE_MIN_MNB_SECONDS (5 * 60)
-#define MASTERNODE_PING_SECONDS (4 * 60)
-#define MASTERNODE_EXPIRATION_SECONDS (9 * 60)
-#define MASTERNODE_REMOVAL_SECONDS (10 * 60)
+#define MASTERNODE_PING_SECONDS (5 * 60)
+#define MASTERNODE_EXPIRATION_SECONDS (120 * 60)
+#define MASTERNODE_REMOVAL_SECONDS (130 * 60)
#define MASTERNODE_CHECK_SECONDS 5
using namespace std;
@@ -62,6 +62,7 @@ class CMasternodePing
bool CheckAndUpdate(int& nDos, bool fRequireEnabled = true);
bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode);
+ bool VerifySignature(CPubKey& pubKeyMasternode, int &nDos);
void Relay();
uint256 GetHash()
@@ -80,7 +81,6 @@ class CMasternodePing
// by swapping the members of two classes,
// the two classes are effectively swapped
swap(first.vin, second.vin);
-
swap(first.blockHash, second.blockHash);
swap(first.sigTime, second.sigTime);
swap(first.vchSig, second.vchSig);
@@ -114,10 +114,14 @@ class CMasternode
public:
enum state {
+ MASTERNODE_PRE_ENABLED,
MASTERNODE_ENABLED,
MASTERNODE_EXPIRED,
+ MASTERNODE_OUTPOINT_SPENT,
MASTERNODE_REMOVE,
+ MASTERNODE_POSE_BAN,
MASTERNODE_VIN_SPENT,
+ MASTERNODE_POS_ERROR
};
enum LevelValue : unsigned {
@@ -139,11 +143,12 @@ class CMasternode
bool unitTest;
bool allowFreeTx;
int protocolVersion;
+ int nActiveState;
int64_t nLastDsq; //the dsq count from the last dsq broadcast of this node
CMasternodePing lastPing;
- static unsigned Level(CAmount vin_val);
- static unsigned Level(const CTxIn& vin);
+ static unsigned Level(CAmount vin_val, int blockHeight);
+ static unsigned Level(const CTxIn& vin, int blockHeight);
static bool IsDepositCoins(CAmount);
static bool IsDepositCoins(const CTxIn& vin, CAmount& vin_val);
@@ -220,6 +225,13 @@ class CMasternode
bool UpdateFromNewBroadcast(CMasternodeBroadcast& mnb);
+ inline uint64_t SliceHash(uint256& hash, int slice)
+ {
+ uint64_t n = 0;
+ memcpy(&n, &hash + slice * 64, 64);
+ return n;
+ }
+
void Check(bool forceCheck = false);
bool IsBroadcastedWithin(int seconds)
@@ -240,26 +252,25 @@ class CMasternode
lastPing = CMasternodePing();
}
- bool IsEnabled() const
+ bool IsEnabled()
{
return activeState == MASTERNODE_ENABLED;
}
int GetMasternodeInputAge()
{
- auto chain_tip = chainActive.Tip();
-
- if (!chain_tip)
- return 0;
+ if (chainActive.Tip() == NULL) return 0;
- if (!cacheInputAge) {
+ if (cacheInputAge == 0) {
cacheInputAge = GetInputAge(vin);
- cacheInputAgeBlock = chain_tip->nHeight;
+ cacheInputAgeBlock = chainActive.Tip()->nHeight;
}
- return cacheInputAge + (chain_tip->nHeight - cacheInputAgeBlock);
+ return cacheInputAge + (chainActive.Tip()->nHeight - cacheInputAgeBlock);
}
+ std::string GetStatus();
+
std::string Status()
{
std::string strStatus = "ACTIVE";
@@ -268,13 +279,14 @@ class CMasternode
if (activeState == CMasternode::MASTERNODE_EXPIRED) strStatus = "EXPIRED";
if (activeState == CMasternode::MASTERNODE_VIN_SPENT) strStatus = "VIN_SPENT";
if (activeState == CMasternode::MASTERNODE_REMOVE) strStatus = "REMOVE";
+ if (activeState == CMasternode::MASTERNODE_POS_ERROR) strStatus = "POS_ERROR";
return strStatus;
}
unsigned Level()
{
- return Level(deposit);
+ return Level(deposit, chainActive.Height());
}
int64_t GetLastPaid();
@@ -296,7 +308,10 @@ class CMasternodeBroadcast : public CMasternode
bool CheckAndUpdate(int& nDoS);
bool CheckInputsAndAdd(int& nDos);
bool Sign(CKey& keyCollateralAddress);
+ bool VerifySignature();
void Relay();
+ std::string GetOldStrMessage();
+ std::string GetNewStrMessage();
ADD_SERIALIZE_METHODS;
diff --git a/src/masternodeconfig.h b/src/masternodeconfig.h
index 59df088..ddd7d98 100644
--- a/src/masternodeconfig.h
+++ b/src/masternodeconfig.h
@@ -107,7 +107,7 @@ class CMasternodeConfig
int getCount()
{
int c = -1;
- BOOST_FOREACH (CMasternodeEntry e, entries) {
+ for (CMasternodeEntry e : entries) {
if (e.getAlias() != "") c++;
}
return c;
diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp
index cb93925..92c2a4b 100644
--- a/src/masternodeman.cpp
+++ b/src/masternodeman.cpp
@@ -1,6 +1,6 @@
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -78,8 +78,8 @@ bool CMasternodeDB::Write(const CMasternodeMan& mnodemanToSave)
// FileCommit(fileout);
fileout.fclose();
- LogPrintf("Written info to mncache.dat %dms\n", GetTimeMillis() - nStart);
- LogPrintf(" %s\n", mnodemanToSave.ToString());
+ LogPrint("masternode","Written info to mncache.dat %dms\n", GetTimeMillis() - nStart);
+ LogPrint("masternode"," %s\n", mnodemanToSave.ToString());
return true;
}
@@ -153,13 +153,13 @@ CMasternodeDB::ReadResult CMasternodeDB::Read(CMasternodeMan& mnodemanToLoad, bo
return IncorrectFormat;
}
- LogPrintf("Loaded info from mncache.dat %dms\n", GetTimeMillis() - nStart);
- LogPrintf(" %s\n", mnodemanToLoad.ToString());
+ LogPrint("masternode","Loaded info from mncache.dat %dms\n", GetTimeMillis() - nStart);
+ LogPrint("masternode"," %s\n", mnodemanToLoad.ToString());
if (!fDryRun) {
- LogPrintf("Masternode manager - cleaning....\n");
+ LogPrint("masternode","Masternode manager - cleaning....\n");
mnodemanToLoad.CheckAndRemove(true);
- LogPrintf("Masternode manager - result:\n");
- LogPrintf(" %s\n", mnodemanToLoad.ToString());
+ LogPrint("masternode","Masternode manager - result:\n");
+ LogPrint("masternode"," %s\n", mnodemanToLoad.ToString());
}
return Ok;
@@ -172,24 +172,24 @@ void DumpMasternodes()
CMasternodeDB mndb;
CMasternodeMan tempMnodeman;
- LogPrintf("Verifying mncache.dat format...\n");
+ LogPrint("masternode","Verifying mncache.dat format...\n");
CMasternodeDB::ReadResult readResult = mndb.Read(tempMnodeman, true);
// there was an error and it was not an error on file opening => do not proceed
if (readResult == CMasternodeDB::FileError)
- LogPrintf("Missing masternode cache file - mncache.dat, will try to recreate\n");
+ LogPrint("masternode","Missing masternode cache file - mncache.dat, will try to recreate\n");
else if (readResult != CMasternodeDB::Ok) {
- LogPrintf("Error reading mncache.dat: ");
+ LogPrint("masternode","Error reading mncache.dat: ");
if (readResult == CMasternodeDB::IncorrectFormat)
- LogPrintf("magic is ok but data has invalid format, will try to recreate\n");
+ LogPrint("masternode","magic is ok but data has invalid format, will try to recreate\n");
else {
- LogPrintf("file format is unknown or invalid, please fix it manually\n");
+ LogPrint("masternode","file format is unknown or invalid, please fix it manually\n");
return;
}
}
- LogPrintf("Writting info to mncache.dat...\n");
+ LogPrint("masternode","Writting info to mncache.dat...\n");
mndb.Write(mnodeman);
- LogPrintf("Masternode dump finished %dms\n", GetTimeMillis() - nStart);
+ LogPrint("masternode","Masternode dump finished %dms\n", GetTimeMillis() - nStart);
}
CMasternodeMan::CMasternodeMan()
@@ -210,7 +210,6 @@ CValidationState CMasternodeMan::GetInputCheckingTx(const CTxIn& vin, CMutableTr
CMutableTransaction chk_tx;
chk_tx.vin.push_back(vin);
-// chk_tx.vout.push_back(CTxOut(9999.99 * COIN, obfuScationPool.collateralPubKey));
chk_tx.vout.push_back(CTxOut(deposit - 0.01 * COIN, obfuScationPool.collateralPubKey));
tx = chk_tx;
@@ -218,19 +217,21 @@ CValidationState CMasternodeMan::GetInputCheckingTx(const CTxIn& vin, CMutableTr
return state;
}
-bool CMasternodeMan::Add(const CMasternode& mn)
+bool CMasternodeMan::Add(CMasternode& mn)
{
LOCK(cs);
- if(!mn.IsEnabled())
+ if (!mn.IsEnabled())
return false;
- if(Find(mn.vin))
- return false;
+ CMasternode* pmn = Find(mn.vin);
+ if (pmn == NULL) {
+ LogPrint("masternode", "CMasternodeMan: Adding new Masternode %s - %i now\n", mn.vin.prevout.hash.ToString(), size() + 1);
+ vMasternodes.push_back(mn);
+ return true;
+ }
- LogPrint("masternode", "CMasternodeMan: Adding new Masternode %s - %i now\n", mn.vin.prevout.hash.ToString(), size() + 1);
- vMasternodes.push_back(mn);
- return true;
+ return false;
}
std::vector CMasternodeMan::GetFullMasternodeMap()
@@ -259,7 +260,7 @@ void CMasternodeMan::Check()
{
LOCK(cs);
- BOOST_FOREACH (CMasternode& mn, vMasternodes) {
+ for (CMasternode& mn : vMasternodes) {
mn.Check();
}
}
@@ -437,7 +438,7 @@ int CMasternodeMan::stable_size(unsigned mnlevel)
if(!mn.IsEnabled())
continue; // Skip not-enabled masternodes
- ++nStable_size;
+ nStable_size++;
}
return nStable_size;
@@ -461,15 +462,15 @@ unsigned CMasternodeMan::CountEnabled(unsigned mnlevel, int protocolVersion)
});
}
-std::map CMasternodeMan::CountEnabledByLevels(int protocolVersion)
+std::map CMasternodeMan::CountEnabledByLevels(int protocolVersion)
{
if(protocolVersion == -1)
protocolVersion = masternodePayments.GetMinMasternodePaymentsProto();
- std::map result;
+ std::map result;
for(unsigned l = CMasternode::LevelValue::MIN; l <= CMasternode::LevelValue::MAX; ++l)
- result.emplace(l, 0u);
+ result.emplace(l, 0);
for(auto& mn : vMasternodes)
{
@@ -490,7 +491,7 @@ void CMasternodeMan::CountNetworks(int protocolVersion, int& ipv4, int& ipv6, in
{
protocolVersion = protocolVersion == -1 ? masternodePayments.GetMinMasternodePaymentsProto() : protocolVersion;
- BOOST_FOREACH (CMasternode& mn, vMasternodes) {
+ for (CMasternode& mn : vMasternodes) {
mn.Check();
std::string strHost;
int port;
@@ -549,14 +550,7 @@ bool CMasternodeMan::WinnersUpdate(CNode* node)
}
}
- auto mn_counts = mnodeman.CountEnabledByLevels();
-
- unsigned max_mn_count = 0u;
-
- for(const auto& count : mn_counts)
- max_mn_count = std::max(max_mn_count, count.second);
-
- node->PushMessage("mnget", max_mn_count);
+ node->PushMessage("mnget", mnodeman.CountEnabled());
int64_t askAgain = GetTime() + MASTERNODES_DSEG_SECONDS;
mWeAskedForWinnerMasternodeList[node->addr] = askAgain;
return true;
@@ -567,7 +561,7 @@ CMasternode* CMasternodeMan::Find(const CScript& payee)
LOCK(cs);
CScript payee2;
- BOOST_FOREACH (CMasternode& mn, vMasternodes) {
+ for (CMasternode& mn : vMasternodes) {
payee2 = GetScriptForDestination(mn.pubKeyCollateralAddress.GetID());
if (payee2 == payee)
return &mn;
@@ -579,7 +573,7 @@ CMasternode* CMasternodeMan::Find(const CTxIn& vin)
{
LOCK(cs);
- BOOST_FOREACH (CMasternode& mn, vMasternodes) {
+ for (CMasternode& mn : vMasternodes) {
if (mn.vin.prevout == vin.prevout)
return &mn;
}
@@ -591,7 +585,7 @@ CMasternode* CMasternodeMan::Find(const CPubKey& pubKeyMasternode)
{
LOCK(cs);
- BOOST_FOREACH (CMasternode& mn, vMasternodes) {
+ for (CMasternode& mn : vMasternodes) {
if (mn.pubKeyMasternode == pubKeyMasternode)
return &mn;
}
@@ -617,38 +611,39 @@ CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight
{
LOCK(cs);
+ CMasternode* pBestMasternode = nullptr;
std::vector > vecMasternodeLastPaid;
/*
Make a vector with all of the last paid times
*/
- int nMnCount = CountEnabled(mnlevel);
+ auto nMnCount = CountEnabled(mnlevel);
for(CMasternode& mn : vMasternodes) {
- if(mn.Level() != mnlevel)
- continue;
+ mn.Check();
- //check protocol version
- if(mn.protocolVersion < masternodePayments.GetMinMasternodePaymentsProto())
+ if (!mn.IsEnabled())
continue;
- mn.Check();
+ if(mn.Level() != mnlevel)
+ continue;
- if(!mn.IsEnabled())
+ //check protocol version
+ if (mn.protocolVersion < masternodePayments.GetMinMasternodePaymentsProto())
continue;
- //it's in the list -- so let's skip it
- if(masternodePayments.IsScheduled(mn, nMnCount, nBlockHeight))
+ //it's in the list (up to 8 entries ahead of current block to allow propagation) -- so let's skip it
+ if (masternodePayments.IsScheduled(mn, nBlockHeight))
continue;
//it's too new, wait for a cycle
- if(fFilterSigTime && mn.sigTime + (nMnCount * 2.6 * 60) > GetAdjustedTime())
+ if (fFilterSigTime && mn.sigTime + (nMnCount * 2.6 * 60) > GetAdjustedTime())
continue;
//make sure it has as many confirmations as there are masternodes
- if(mn.GetMasternodeInputAge() < nMnCount)
+ if (mn.GetMasternodeInputAge() < nMnCount)
continue;
vecMasternodeLastPaid.emplace_back(mn.SecondsSincePayment(), mn.vin);
@@ -664,31 +659,24 @@ CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight
sort(vecMasternodeLastPaid.rbegin(), vecMasternodeLastPaid.rend(), CompareLastPaid());
// Look at 1/10 of the oldest nodes (by last payment), calculate their scores and pay the best one
- // -- This doesn't look at who is being paid in the scheduled blocks, allowing for double payments very rarely
-
- int nCountTenth = nMnCount / 10;
+ // -- This doesn't look at who is being paid in the +8-10 blocks, allowing for double payments very rarely
+ // -- 1/100 payments should be a double payment on mainnet - (1/(3000/10))*2
+ // -- (chance per block * chances before IsScheduled will fire)
+ int nTenthNetwork = CountEnabled(mnlevel) / 10;
+ int nCountTenth = 0;
uint256 nHigh = 0;
-
- CMasternode* pBestMasternode = nullptr;
-
- for(const auto& s : vecMasternodeLastPaid) {
-
+ BOOST_FOREACH (PAIRTYPE(int64_t, CTxIn) & s, vecMasternodeLastPaid) {
CMasternode* pmn = Find(s.second);
-
- if(!pmn)
- continue;
+ if (!pmn) break;
uint256 n = pmn->CalculateScore(1, nBlockHeight - 100);
-
- if(n > nHigh) {
+ if (n > nHigh) {
nHigh = n;
pBestMasternode = pmn;
}
-
- if(--nCountTenth > 0)
- break;
+ nCountTenth++;
+ if (nCountTenth >= nTenthNetwork) break;
}
-
return pBestMasternode;
}
@@ -826,13 +814,13 @@ std::vector > CMasternodeMan::GetMasternodeRanks(int64_t
if (!GetBlockHash(hash, nBlockHeight)) return vecMasternodeRanks;
// scan for winner
- BOOST_FOREACH (CMasternode& mn, vMasternodes) {
+ for (CMasternode& mn : vMasternodes) {
mn.Check();
if (mn.protocolVersion < minProtocol) continue;
if (!mn.IsEnabled()) {
- vecMasternodeScores.push_back(make_pair(9999, mn));
+ vecMasternodeScores.push_back(make_pair(40555, mn));
continue;
}
@@ -858,7 +846,7 @@ CMasternode* CMasternodeMan::GetMasternodeByRank(int nRank, int64_t nBlockHeight
std::vector > vecMasternodeScores;
// scan for winner
- BOOST_FOREACH (CMasternode& mn, vMasternodes) {
+ for (CMasternode& mn : vMasternodes) {
if (mn.protocolVersion < minProtocol) continue;
if (fOnlyActive) {
mn.Check();
@@ -890,9 +878,9 @@ void CMasternodeMan::ProcessMasternodeConnections()
if (Params().NetworkID() == CBaseChainParams::REGTEST) return;
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes) {
+ for (CNode* pnode : vNodes) {
if (pnode->fObfuScationMaster) {
- if (obfuScationPool.pSubmittedToMasternode && pnode->addr == obfuScationPool.pSubmittedToMasternode->addr)
+ if (obfuScationPool.pSubmittedToMasternode != NULL && pnode->addr == obfuScationPool.pSubmittedToMasternode->addr)
continue;
LogPrintf("Closing Masternode connection peer=%i \n", pnode->GetId());
@@ -921,7 +909,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
if(pmn->IsEnabled())
{
- LogPrintf("mnb - More than one vin used for single IP address\n");
+ LogPrint("masternode","mnb - More than one vin used for single IP address\n");
Misbehaving(pfrom->GetId(), 100);
return;
}
@@ -946,7 +934,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
// make sure the vout that was signed is related to the transaction that spawned the Masternode
// - this is expensive, so it's only done once per Masternode
if (!obfuScationSigner.IsVinAssociatedWithPubkey(mnb.vin, mnb.pubKeyCollateralAddress)) {
- LogPrintf("mnb - Got mismatched pubkey and vin\n");
+ LogPrint("masternode","mnb - Got mismatched pubkey and vin\n");
Misbehaving(pfrom->GetId(), 33);
return;
}
@@ -958,7 +946,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
addrman.Add(CAddress(mnb.addr), pfrom->addr, 2 * 60 * 60);
masternodeSync.AddedMasternodeList(mnb.GetHash());
} else {
- LogPrintf("mnb - Rejected Masternode entry %s\n", mnb.vin.prevout.hash.ToString());
+ LogPrint("masternode","mnb - Rejected Masternode entry %s\n", mnb.vin.prevout.hash.ToString());
if (nDoS > 0) {
Misbehaving(pfrom->GetId(), nDoS);
return;
@@ -987,7 +975,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
// if nothing significant failed, search existing Masternode list
CMasternode* pmn = Find(mnp.vin);
// if it's known, don't ask for the mnb, just return
- if (pmn) return;
+ if (pmn != NULL) return;
}
// something significant is broken or mn is unknown,
@@ -1023,7 +1011,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
int nInvCount = 0;
- BOOST_FOREACH (CMasternode& mn, vMasternodes) {
+ for (CMasternode& mn : vMasternodes) {
if (mn.addr.IsRFC1918()) continue; //local network
if (mn.IsEnabled()) {
@@ -1094,20 +1082,18 @@ void CMasternodeMan::Remove(CTxIn vin)
void CMasternodeMan::UpdateMasternodeList(CMasternodeBroadcast mnb)
{
- LOCK(cs);
mapSeenMasternodePing.insert(std::make_pair(mnb.lastPing.GetHash(), mnb.lastPing));
mapSeenMasternodeBroadcast.insert(std::make_pair(mnb.GetHash(), mnb));
+ masternodeSync.AddedMasternodeList(mnb.GetHash());
- LogPrintf("CMasternodeMan::UpdateMasternodeList -- masternode=%s addr=%s\n", mnb.vin.prevout.ToStringShort(), mnb.addr.ToString());
+ LogPrint("masternode","CMasternodeMan::UpdateMasternodeList -- masternode=%s addr=%s\n", mnb.vin.prevout.ToStringShort(), mnb.addr.ToString());
CMasternode* pmn = Find(mnb.vin);
-
- if (!pmn) {
- if (Add(CMasternode{mnb}))
- masternodeSync.AddedMasternodeList(mnb.GetHash());
-
- } else if (pmn->UpdateFromNewBroadcast(mnb)) {
- masternodeSync.AddedMasternodeList(mnb.GetHash());
+ if (pmn == NULL) {
+ CMasternode mn(mnb);
+ Add(mn);
+ } else {
+ pmn->UpdateFromNewBroadcast(mnb);
}
}
@@ -1115,7 +1101,7 @@ std::string CMasternodeMan::ToString() const
{
std::ostringstream info;
- info << "Masternodes: " << vMasternodes.size() << ", peers who asked us for Masternode list: " << (int)mAskedUsForMasternodeList.size() << ", peers we asked for Masternode list: " << (int)mWeAskedForMasternodeList.size() << ", entries in Masternode list we asked for: " << mWeAskedForMasternodeListEntry.size() << ", nDsqCount: " << nDsqCount;
+ info << "Masternodes: " << (int)vMasternodes.size() << ", peers who asked us for Masternode list: " << (int)mAskedUsForMasternodeList.size() << ", peers we asked for Masternode list: " << (int)mWeAskedForMasternodeList.size() << ", entries in Masternode list we asked for: " << (int)mWeAskedForMasternodeListEntry.size() << ", nDsqCount: " << (int)nDsqCount;
return info.str();
}
diff --git a/src/masternodeman.h b/src/masternodeman.h
index fb03b4f..4dfd083 100644
--- a/src/masternodeman.h
+++ b/src/masternodeman.h
@@ -14,6 +14,7 @@
#include "sync.h"
#include "util.h"
+#define MASTERNODES_DUMP_SECONDS (15 * 60)
#define MASTERNODES_DSEG_SECONDS (3 * 60 * 60)
using namespace std;
@@ -102,7 +103,7 @@ class CMasternodeMan
static CValidationState GetInputCheckingTx(const CTxIn& vin, CMutableTransaction&);
/// Add an entry
- bool Add(const CMasternode& mn);
+ bool Add(CMasternode& mn);
///return all MN's
std::vector GetFullMasternodeMap();
@@ -120,7 +121,7 @@ class CMasternodeMan
void Clear();
unsigned CountEnabled(unsigned mnlevel = CMasternode::LevelValue::UNSPECIFIED, int protocolVersion = -1);
- std::map CountEnabledByLevels(int protocolVersion = -1);
+ std::map CountEnabledByLevels(int protocolVersion = -1);
void CountNetworks(int protocolVersion, int& ipv4, int& ipv6, int& onion);
diff --git a/src/miner.cpp b/src/miner.cpp
index c9addb6..a0a5017 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -2,7 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -20,9 +20,10 @@
#include "util.h"
#include "utilmoneystr.h"
#ifdef ENABLE_WALLET
-#include "wallet.h"
+#include "wallet/wallet.h"
#endif
#include "masternode-payments.h"
+#include "spork.h"
#include
#include
@@ -105,7 +106,12 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
txNew.vin[0].prevout.SetNull();
txNew.vout.resize(1);
txNew.vout[0].SetEmpty();
-// txNew.vout[0].scriptPubKey = scriptPubKeyIn;
+
+ LogPrintf("CreateNewBlock() : chainActive.Height() = %s \n", chainActive.Height());
+ if (chainActive.Height() >= Params().LAST_POW_BLOCK()) {
+ txNew.vout[0].scriptPubKey = scriptPubKeyIn;
+
+ }
pblock->vtx.push_back(txNew);
@@ -132,7 +138,10 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
unsigned int nTxNewTime = 0;
if (pwallet->CreateCoinStake(*pwallet, pblock->nTime, pblock->nBits, nSearchTime - nLastCoinStakeSearchTime, txCoinStake, nTxNewTime)) {
pblock->nTime = nTxNewTime;
-// pblock->vtx[0].vout[0].SetEmpty();
+
+ LogPrintf("CreateNewBlock() if fProofOfStake: chainActive.Height() = %s \n", chainActive.Height());
+ pblock->vtx[0].vout[0].SetEmpty();
+
pblock->vtx.push_back(CTransaction(txCoinStake));
fStakeFound = true;
}
@@ -187,7 +196,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
double dPriority = 0;
CAmount nTotalIn = 0;
bool fMissingInputs = false;
- BOOST_FOREACH (const CTxIn& txin, tx.vin) {
+ for (const CTxIn& txin : tx.vin) {
// Read prev transaction
if (!view.HaveCoins(txin.prevout.hash)) {
// This should never happen; all transactions in the memory
@@ -321,7 +330,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
// Add transactions that depend on this one to the priority queue
if (mapDependers.count(hash)) {
- BOOST_FOREACH (COrphan* porphan, mapDependers[hash]) {
+ for (COrphan* porphan : mapDependers[hash]) {
if (!porphan->setDependsOn.empty()) {
porphan->setDependsOn.erase(hash);
if (porphan->setDependsOn.empty()) {
@@ -333,34 +342,29 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
}
}
- if (!fProofOfStake)
- UpdateTime(pblock, pindexPrev);
-
- CAmount block_value = GetBlockValue(nHeight, pblock->nTime);
-
txNew.vin[0].scriptSig = CScript() << nHeight << OP_0;
-
+ CAmount block_value = GetBlockValue(nHeight, pblock->nTime);
// Compute final transaction.
if (!fProofOfStake) {
+
txNew.vout[0].nValue = block_value + nFees;
txNew.vout[0].scriptPubKey = scriptPubKeyIn;
pblocktemplate->vTxFees[0] = -nFees;
- }
- pblock->vtx[0] = txNew;
+ pblock->vtx[0] = txNew;
- if(nHeight > 1) { // exclude premine
+ if(nHeight > 1) { // exclude premine
- auto reward_tx_idx = fProofOfStake ? 1 : 0;
+ auto reward_tx_idx = fProofOfStake ? 1 : 0;
- CMutableTransaction txReward{pblock->vtx[reward_tx_idx]};
+ CMutableTransaction txReward{pblock->vtx[reward_tx_idx]};
- auto reward_out_idx = txReward.vout.size() - 1;
+ auto reward_out_idx = txReward.vout.size() - 1;
// Masternode payments
auto mn_reward = masternodePayments.FillBlockPayee(txReward, pblock->nTime, block_value, fProofOfStake);
- txReward.vout[reward_out_idx].nValue -= mn_reward;
+ txReward.vout[reward_out_idx].nValue -= mn_reward;
// XDNA fees
CScript scriptDevPubKeyIn = CScript{} << Params().xDNADevKey() << OP_CHECKSIG;
@@ -376,6 +380,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
pblock->vtx[reward_tx_idx] = txReward;
}
+ }
nLastBlockTx = nBlockTx;
nLastBlockSize = nBlockSize;
@@ -383,15 +388,20 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, CWallet* pwallet,
// Fill in header
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
+ if (!fProofOfStake)
+ UpdateTime(pblock, pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock->nTime);
pblock->nNonce = 0;
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
CValidationState state;
+ LogPrintf("CreateNewBlock() if CValidationState: chainActive.Height() = %s \n", chainActive.Height());
+ if (chainActive.Height() < Params().LAST_POW_BLOCK()) {
if (!TestBlockValidity(state, *pblock, pindexPrev, false, false)) {
LogPrintf("CreateNewBlock() : TestBlockValidity failed\n");
mempool.clear();
return nullptr;
+ }
}
}
@@ -499,8 +509,15 @@ void BitcoinMiner(CWallet* pwallet, bool fProofOfStake)
}
//todo: check nTime < GMT: Thursday, 18 August 2016 г., 01:00:00
- while (chainActive.Tip()->nTime < 1471482000 || vNodes.empty() || pwallet->IsLocked() || !fMintableCoins || nReserveBalance >= pwallet->GetBalance() || !masternodeSync.IsSynced()) {
+ while (vNodes.empty() || pwallet->IsLocked() || !fMintableCoins || (pwallet->GetBalance() > 0 && nReserveBalance >= pwallet->GetBalance()) || !masternodeSync.IsSynced()) {
nLastCoinStakeSearchInterval = 0;
+ if (!fMintableCoins) {
+ if (GetTime() - nMintableLastCheck > 1 * 60) // 1 minute check time
+ {
+ nMintableLastCheck = GetTime();
+ fMintableCoins = pwallet->MintableCoins();
+ }
+ }
MilliSleep(5000);
if (!fGenerateBitcoins && !fProofOfStake)
continue;
@@ -554,7 +571,6 @@ void BitcoinMiner(CWallet* pwallet, bool fProofOfStake)
//
// Search
//
-
int64_t nStart = GetTime();
uint256 hashTarget = uint256().SetCompact(pblock->nBits);
while (true) {
diff --git a/src/net.cpp b/src/net.cpp
index b7b3f4d..0cd345c 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -2,7 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -19,7 +19,9 @@
#include "obfuscation.h"
#include "primitives/transaction.h"
#include "ui_interface.h"
-#include "wallet.h"
+#ifdef ENABLE_WALLET
+#include "wallet/wallet.h"
+#endif // ENABLE_WALLET
#ifdef WIN32
#include
@@ -78,7 +80,6 @@ bool fListen = true;
uint64_t nLocalServices = NODE_NETWORK;
CCriticalSection cs_mapLocalHost;
map mapLocalHost;
-static bool vfReachable[NET_MAX] = {};
static bool vfLimited[NET_MAX] = {};
static CNode* pnodeLocalHost = NULL;
uint64_t nLocalHostNonce = 0;
@@ -86,6 +87,7 @@ static std::vector vhListenSocket;
CAddrMan addrman;
int nMaxConnections = 125;
bool fAddressesInitialized = false;
+std::string strSubVersion;
vector vNodes;
CCriticalSection cs_vNodes;
@@ -238,14 +240,6 @@ void AdvertiseLocal(CNode* pnode)
}
}
-void SetReachable(enum Network net, bool fFlag)
-{
- LOCK(cs_mapLocalHost);
- vfReachable[net] = fFlag;
- if (net == NET_IPV6 && fFlag)
- vfReachable[NET_IPV4] = true;
-}
-
// learn a new local address
bool AddLocal(const CService& addr, int nScore)
{
@@ -268,7 +262,6 @@ bool AddLocal(const CService& addr, int nScore)
info.nScore = nScore + (fAlready ? 1 : 0);
info.nPort = addr.GetPort();
}
- SetReachable(addr.GetNetwork());
}
return true;
@@ -331,7 +324,7 @@ bool IsLocal(const CService& addr)
bool IsReachable(enum Network net)
{
LOCK(cs_mapLocalHost);
- return vfReachable[net] && !vfLimited[net];
+ return !vfLimited[net];
}
/** check whether a given address is in a network we can probably connect to */
@@ -355,16 +348,25 @@ CCriticalSection CNode::cs_totalBytesSent;
CNode* FindNode(const CNetAddr& ip)
{
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes)
+ for (CNode* pnode : vNodes)
if ((CNetAddr)pnode->addr == ip)
return (pnode);
return NULL;
}
+CNode* FindNode(const CSubNet& subNet)
+{
+ LOCK(cs_vNodes);
+ for (CNode* pnode : vNodes)
+ if (subNet.Match((CNetAddr)pnode->addr))
+ return (pnode);
+ return NULL;
+}
+
CNode* FindNode(const std::string& addrName)
{
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes)
+ for (CNode* pnode : vNodes)
if (pnode->addrName == addrName)
return (pnode);
return NULL;
@@ -373,7 +375,7 @@ CNode* FindNode(const std::string& addrName)
CNode* FindNode(const CService& addr)
{
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes) {
+ for (CNode* pnode : vNodes) {
if (Params().NetworkID() == CBaseChainParams::REGTEST) {
//if using regtest, just check the IP
if ((CNetAddr)pnode->addr == (CNetAddr)addr)
@@ -410,7 +412,7 @@ CNode* ConnectNode(CAddress addrConnect, const char* pszDest, bool obfuScationMa
pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime) / 3600.0);
// Connect
- SOCKET hSocket;
+ SOCKET hSocket = INVALID_SOCKET;
bool proxyConnectionFailed = false;
if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, Params().GetDefaultPort(), nConnectTimeout, &proxyConnectionFailed) :
ConnectSocket(addrConnect, hSocket, nConnectTimeout, &proxyConnectionFailed)) {
@@ -484,16 +486,23 @@ void CNode::PushVersion()
else
LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), id);
PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
- nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector()), nBestHeight, true);
+ nLocalHostNonce, strSubVersion, nBestHeight, true);
}
-std::map CNode::setBanned;
+banmap_t CNode::setBanned;
CCriticalSection CNode::cs_setBanned;
+bool CNode::setBannedIsDirty;
void CNode::ClearBanned()
{
- setBanned.clear();
+ {
+ LOCK(cs_setBanned);
+ setBanned.clear();
+ setBannedIsDirty = true;
+ }
+ DumpBanlist(); // store banlist to Disk
+ uiInterface.BannedListChanged();
}
bool CNode::IsBanned(CNetAddr ip)
@@ -501,27 +510,146 @@ bool CNode::IsBanned(CNetAddr ip)
bool fResult = false;
{
LOCK(cs_setBanned);
- std::map::iterator i = setBanned.find(ip);
+ for (banmap_t::iterator it = setBanned.begin(); it != setBanned.end(); it++)
+ {
+ CSubNet subNet = (*it).first;
+ CBanEntry banEntry = (*it).second;
+
+ if(subNet.Match(ip) && GetTime() < banEntry.nBanUntil)
+ fResult = true;
+ }
+ }
+ return fResult;
+}
+
+bool CNode::IsBanned(CSubNet subnet)
+{
+ bool fResult = false;
+ {
+ LOCK(cs_setBanned);
+ banmap_t::iterator i = setBanned.find(subnet);
if (i != setBanned.end()) {
- int64_t t = (*i).second;
- if (GetTime() < t)
+ CBanEntry banEntry = (*i).second;
+ if (GetTime() < banEntry.nBanUntil)
fResult = true;
}
}
return fResult;
}
-bool CNode::Ban(const CNetAddr& addr)
+void CNode::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch)
+{
+ CSubNet subNet(addr);
+ Ban(subNet, banReason, bantimeoffset, sinceUnixEpoch);
+}
+
+void CNode::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch)
+{
+ CBanEntry banEntry(GetTime());
+ banEntry.banReason = banReason;
+ if (bantimeoffset <= 0)
+ {
+ bantimeoffset = GetArg("-bantime", 60*60*24); // Default 24-hour ban
+ sinceUnixEpoch = false;
+ }
+ banEntry.nBanUntil = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset;
+
+ {
+ LOCK(cs_setBanned);
+ if (setBanned[subNet].nBanUntil < banEntry.nBanUntil) {
+ setBanned[subNet] = banEntry;
+ setBannedIsDirty = true;
+ }
+ else
+ return;
+ }
+ uiInterface.BannedListChanged();
+ {
+ LOCK(cs_vNodes);
+ for (CNode* pnode : vNodes) {
+ if (subNet.Match((CNetAddr)pnode->addr))
+ pnode->fDisconnect = true;
+ }
+ }
+ if(banReason == BanReasonManuallyAdded)
+ DumpBanlist(); //store banlist to disk immediately if user requested ban
+}
+
+bool CNode::Unban(const CNetAddr &addr)
+{
+ CSubNet subNet(addr);
+ return Unban(subNet);
+}
+
+bool CNode::Unban(const CSubNet &subNet)
{
- int64_t banTime = GetTime() + GetArg("-bantime", 60 * 60 * 24); // Default 24-hour ban
{
LOCK(cs_setBanned);
- if (setBanned[addr] < banTime)
- setBanned[addr] = banTime;
+ if (!setBanned.erase(subNet))
+ return false;
+ setBannedIsDirty = true;
}
+ uiInterface.BannedListChanged();
+ DumpBanlist(); //store banlist to disk immediately
return true;
}
+void CNode::GetBanned(banmap_t &banMap)
+{
+ LOCK(cs_setBanned);
+ // Sweep the banlist so expired bans are not returned
+ SweepBanned();
+ banMap = setBanned; //create a thread safe copy
+}
+
+void CNode::SetBanned(const banmap_t &banMap)
+{
+ LOCK(cs_setBanned);
+ setBanned = banMap;
+ setBannedIsDirty = true;
+}
+
+void CNode::SweepBanned()
+{
+ int64_t now = GetTime();
+
+ bool notifyUI = false;
+ {
+ LOCK(cs_setBanned);
+ banmap_t::iterator it = setBanned.begin();
+ while(it != setBanned.end())
+ {
+ CSubNet subNet = (*it).first;
+ CBanEntry banEntry = (*it).second;
+ if(now > banEntry.nBanUntil)
+ {
+ setBanned.erase(it++);
+ setBannedIsDirty = true;
+ notifyUI = true;
+ LogPrint("net", "%s: Removed banned node ip/subnet from banlist.dat: %s\n", __func__, subNet.ToString());
+ }
+ else
+ ++it;
+ }
+ }
+ // update UI
+ if(notifyUI) {
+ uiInterface.BannedListChanged();
+ }
+}
+
+bool CNode::BannedSetIsDirty()
+{
+ LOCK(cs_setBanned);
+ return setBannedIsDirty;
+}
+
+void CNode::SetBannedSetDirty(bool dirty)
+{
+ LOCK(cs_setBanned); //reuse setBanned lock for the isDirty flag
+ setBannedIsDirty = dirty;
+}
+
std::vector CNode::vWhitelistedRange;
CCriticalSection CNode::cs_vWhitelistedRange;
@@ -529,7 +657,7 @@ CCriticalSection CNode::cs_vWhitelistedRange;
bool CNode::IsWhitelistedRange(const CNetAddr& addr)
{
LOCK(cs_vWhitelistedRange);
- BOOST_FOREACH (const CSubNet& subnet, vWhitelistedRange) {
+ for (const CSubNet& subnet : vWhitelistedRange) {
if (subnet.Match(addr))
return true;
}
@@ -551,6 +679,7 @@ void CNode::copyStats(CNodeStats& stats)
X(nLastSend);
X(nLastRecv);
X(nTimeConnected);
+ X(nTimeOffset);
X(addrName);
X(nVersion);
X(cleanSubVer);
@@ -658,12 +787,25 @@ int CNetMessage::readData(const char* pch, unsigned int nBytes)
vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
}
+ hasher.Write((const unsigned char*)pch, nCopy);
memcpy(&vRecv[nDataPos], pch, nCopy);
nDataPos += nCopy;
return nCopy;
}
+const uint256& CNetMessage::GetMessageHash() const
+{
+ assert(complete());
+ if (data_hash.IsNull())
+ hasher.Finalize(data_hash.begin());
+ return data_hash;
+}
+
+
+
+
+
// requires LOCK(cs_vSend)
void SocketSendData(CNode* pnode)
@@ -721,7 +863,7 @@ void ThreadSocketHandler()
LOCK(cs_vNodes);
// Disconnect unused nodes
vector vNodesCopy = vNodes;
- BOOST_FOREACH (CNode* pnode, vNodesCopy) {
+ for (CNode* pnode : vNodesCopy) {
if (pnode->fDisconnect ||
(pnode->GetRefCount() <= 0 && pnode->vRecvMsg.empty() && pnode->nSendSize == 0 && pnode->ssSend.empty())) {
// remove from vNodes
@@ -743,7 +885,7 @@ void ThreadSocketHandler()
{
// Delete disconnected nodes
list vNodesDisconnectedCopy = vNodesDisconnected;
- BOOST_FOREACH (CNode* pnode, vNodesDisconnectedCopy) {
+ for (CNode* pnode : vNodesDisconnectedCopy) {
// wait until threads are done using it
if (pnode->GetRefCount() <= 0) {
bool fDelete = false;
@@ -791,7 +933,7 @@ void ThreadSocketHandler()
SOCKET hSocketMax = 0;
bool have_fds = false;
- BOOST_FOREACH (const ListenSocket& hListenSocket, vhListenSocket) {
+ for (const ListenSocket& hListenSocket : vhListenSocket) {
FD_SET(hListenSocket.socket, &fdsetRecv);
hSocketMax = max(hSocketMax, hListenSocket.socket);
have_fds = true;
@@ -799,7 +941,7 @@ void ThreadSocketHandler()
{
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes) {
+ for (CNode* pnode : vNodes) {
if (pnode->hSocket == INVALID_SOCKET)
continue;
FD_SET(pnode->hSocket, &fdsetError);
@@ -856,7 +998,7 @@ void ThreadSocketHandler()
//
// Accept new connections
//
- BOOST_FOREACH (const ListenSocket& hListenSocket, vhListenSocket) {
+ for (const ListenSocket& hListenSocket : vhListenSocket) {
if (hListenSocket.socket != INVALID_SOCKET && FD_ISSET(hListenSocket.socket, &fdsetRecv)) {
struct sockaddr_storage sockaddr;
socklen_t len = sizeof(sockaddr);
@@ -871,7 +1013,7 @@ void ThreadSocketHandler()
bool whitelisted = hListenSocket.whitelisted || CNode::IsWhitelistedRange(addr);
{
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes)
+ for (CNode* pnode : vNodes)
if (pnode->fInbound)
nInbound++;
}
@@ -909,10 +1051,10 @@ void ThreadSocketHandler()
{
LOCK(cs_vNodes);
vNodesCopy = vNodes;
- BOOST_FOREACH (CNode* pnode, vNodesCopy)
+ for (CNode* pnode : vNodesCopy)
pnode->AddRef();
}
- BOOST_FOREACH (CNode* pnode, vNodesCopy) {
+ for (CNode* pnode : vNodesCopy) {
boost::this_thread::interruption_point();
//
@@ -984,7 +1126,7 @@ void ThreadSocketHandler()
}
{
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodesCopy)
+ for (CNode* pnode : vNodesCopy)
pnode->Release();
}
}
@@ -1119,14 +1261,14 @@ void ThreadDNSAddressSeed()
LogPrintf("Loading addresses from DNS seeds (could take a while)\n");
- BOOST_FOREACH (const CDNSSeedData& seed, vSeeds) {
+ for (const CDNSSeedData& seed : vSeeds) {
if (HaveNameProxy()) {
AddOneShot(seed.host);
} else {
vector vIPs;
vector vAdd;
if (LookupHost(seed.host.c_str(), vIPs)) {
- BOOST_FOREACH (CNetAddr& ip, vIPs) {
+ for (CNetAddr& ip : vIPs) {
int nOneDay = 24 * 3600;
CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()));
addr.nTime = GetTime() - 3 * nOneDay - GetRand(4 * nOneDay); // use a random age between 3 and 7 days old
@@ -1153,6 +1295,12 @@ void DumpAddresses()
addrman.size(), GetTimeMillis() - nStart);
}
+void DumpData()
+{
+ DumpAddresses();
+ DumpBanlist();
+}
+
void static ProcessOneShot()
{
string strDest;
@@ -1177,7 +1325,7 @@ void ThreadOpenConnections()
if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0) {
for (int64_t nLoop = 0;; nLoop++) {
ProcessOneShot();
- BOOST_FOREACH (string strAddr, mapMultiArgs["-connect"]) {
+ for (string strAddr : mapMultiArgs["-connect"]) {
CAddress addr;
OpenNetworkConnection(addr, NULL, strAddr.c_str());
for (int i = 0; i < 10 && i < nLoop; i++) {
@@ -1219,7 +1367,7 @@ void ThreadOpenConnections()
set > setConnected;
{
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes) {
+ for (CNode* pnode : vNodes) {
if (!pnode->fInbound) {
setConnected.insert(pnode->addr.GetGroup());
nOutbound++;
@@ -1279,10 +1427,10 @@ void ThreadOpenAddedConnections()
list lAddresses(0);
{
LOCK(cs_vAddedNodes);
- BOOST_FOREACH (string& strAddNode, vAddedNodes)
+ for (string& strAddNode : vAddedNodes)
lAddresses.push_back(strAddNode);
}
- BOOST_FOREACH (string& strAddNode, lAddresses) {
+ for (string& strAddNode : lAddresses) {
CAddress addr;
CSemaphoreGrant grant(*semOutbound);
OpenNetworkConnection(addr, &grant, strAddNode.c_str());
@@ -1296,18 +1444,18 @@ void ThreadOpenAddedConnections()
list lAddresses(0);
{
LOCK(cs_vAddedNodes);
- BOOST_FOREACH (string& strAddNode, vAddedNodes)
+ for (string& strAddNode : vAddedNodes)
lAddresses.push_back(strAddNode);
}
list > lservAddressesToAdd(0);
- BOOST_FOREACH (string& strAddNode, lAddresses) {
+ for (string& strAddNode : lAddresses) {
vector vservNode(0);
if (Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0)) {
lservAddressesToAdd.push_back(vservNode);
{
LOCK(cs_setservAddNodeAddresses);
- BOOST_FOREACH (CService& serv, vservNode)
+ for (CService& serv : vservNode)
setservAddNodeAddresses.insert(serv);
}
}
@@ -1316,16 +1464,16 @@ void ThreadOpenAddedConnections()
// (keeping in mind that addnode entries can have many IPs if fNameLookup)
{
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes)
+ for (CNode* pnode : vNodes)
for (list >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
- BOOST_FOREACH (CService& addrNode, *(it))
+ for (CService& addrNode : *(it))
if (pnode->addr == addrNode) {
it = lservAddressesToAdd.erase(it);
it--;
break;
}
}
- BOOST_FOREACH (vector& vserv, lservAddressesToAdd) {
+ for (vector& vserv : lservAddressesToAdd) {
CSemaphoreGrant grant(*semOutbound);
OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
MilliSleep(500);
@@ -1415,9 +1563,7 @@ void ThreadMessageHandler()
// Send messages
{
TRY_LOCK(pnode->cs_vSend, lockSend);
-
- if(lockSend) {
-
+ if (lockSend) {
g_signals.SendMessages(pnode, pnode == pnodeTrickle || pnode->fWhitelisted);
if(performRebroadcast) {
@@ -1426,6 +1572,8 @@ void ThreadMessageHandler()
if (nLastRebroadcast)
pnode->setAddrKnown.clear();
+ // Logging from quato
+ LogPrintf("Rebroadcast our address with AdvertiseLocal\n");
// Rebroadcast our address
AdvertiseLocal(pnode);
@@ -1436,6 +1584,7 @@ void ThreadMessageHandler()
boost::this_thread::interruption_point();
}
+
{
LOCK(cs_vNodes);
for (CNode* pnode : vNodesCopy)
@@ -1447,6 +1596,7 @@ void ThreadMessageHandler()
}
}
+#ifdef ENABLE_WALLET
// ppcoin: stake minter thread
void static ThreadStakeMinter()
{
@@ -1463,6 +1613,7 @@ void static ThreadStakeMinter()
}
LogPrintf("ThreadStakeMinter exiting,\n");
}
+#endif // ENABLE_WALLET
bool BindListenPort(const CService& addrBind, string& strError, bool fWhitelisted)
{
@@ -1563,7 +1714,7 @@ void static Discover(boost::thread_group& threadGroup)
if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR) {
vector vaddr;
if (LookupHost(pszHostName, vaddr)) {
- BOOST_FOREACH (const CNetAddr& addr, vaddr) {
+ for (const CNetAddr& addr : vaddr) {
if (AddLocal(addr, LOCAL_IF))
LogPrintf("%s: %s - %s\n", __func__, pszHostName, addr.ToString());
}
@@ -1605,6 +1756,21 @@ void StartNode(boost::thread_group& threadGroup)
if (!adb.Read(addrman))
LogPrintf("Invalid or missing peers.dat; recreating\n");
}
+
+ //try to read stored banlist
+ CBanDB bandb;
+ banmap_t banmap;
+ if (!bandb.Read(banmap))
+ LogPrintf("Invalid or missing banlist.dat; recreating\n");
+
+ CNode::SetBanned(banmap); //thread save setter
+ CNode::SetBannedSetDirty(false); //no need to write down just read or nonexistent data
+ CNode::SweepBanned(); //sweap out unused entries
+
+ // Initialize random numbers. Even when rand() is only usable for trivial use-cases most nodes should have a different
+ // seed after all the file-IO done at this point. Should be good enough even when nodes are started via scripts.
+ srand(time(NULL));
+
LogPrintf("Loaded %i addresses from peers.dat %dms\n",
addrman.size(), GetTimeMillis() - nStart);
fAddressesInitialized = true;
@@ -1647,9 +1813,11 @@ void StartNode(boost::thread_group& threadGroup)
// Dump network addresses
threadGroup.create_thread(boost::bind(&LoopForever, "dumpaddr", &DumpAddresses, DUMP_ADDRESSES_INTERVAL * 1000));
+#ifdef ENABLE_WALLET
// ppcoin:mint proof-of-stake blocks in the background
- if (GetBoolArg("-staking", true))
+ if (GetBoolArg("-staking", true) && pwalletMain)
threadGroup.create_thread(boost::bind(&TraceThread, "stakemint", &ThreadStakeMinter));
+#endif // ENABLE_WALLET
}
bool StopNode()
@@ -1661,7 +1829,7 @@ bool StopNode()
semOutbound->post();
if (fAddressesInitialized) {
- DumpAddresses();
+ DumpData();
fAddressesInitialized = false;
}
@@ -1676,18 +1844,18 @@ class CNetCleanup
~CNetCleanup()
{
// Close sockets
- BOOST_FOREACH (CNode* pnode, vNodes)
+ for (CNode* pnode : vNodes)
if (pnode->hSocket != INVALID_SOCKET)
CloseSocket(pnode->hSocket);
- BOOST_FOREACH (ListenSocket& hListenSocket, vhListenSocket)
+ for (ListenSocket& hListenSocket : vhListenSocket)
if (hListenSocket.socket != INVALID_SOCKET)
if (!CloseSocket(hListenSocket.socket))
LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()));
// clean up some globals (to help leak detection)
- BOOST_FOREACH (CNode* pnode, vNodes)
+ for (CNode* pnode : vNodes)
delete pnode;
- BOOST_FOREACH (CNode* pnode, vNodesDisconnected)
+ for (CNode* pnode : vNodesDisconnected)
delete pnode;
vNodes.clear();
vNodesDisconnected.clear();
@@ -1736,7 +1904,7 @@ void RelayTransaction(const CTransaction& tx, const CDataStream& ss)
vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
}
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes) {
+ for (CNode* pnode : vNodes) {
if (!pnode->fRelayTxes)
continue;
LOCK(pnode->cs_filter);
@@ -1754,7 +1922,7 @@ void RelayTransactionLockReq(const CTransaction& tx, bool relayToAll)
//broadcast the new lock
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes) {
+ for (CNode* pnode : vNodes) {
if (!relayToAll && !pnode->fRelayTxes)
continue;
@@ -1765,8 +1933,7 @@ void RelayTransactionLockReq(const CTransaction& tx, bool relayToAll)
void RelayInv(CInv& inv)
{
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes){
- if((pnode->nServices==NODE_BLOOM_WITHOUT_MN) && inv.IsMasterNodeType())continue;
+ for (CNode* pnode : vNodes){
if (pnode->nVersion >= ActiveProtocol())
pnode->PushInventory(inv);
}
@@ -1796,40 +1963,6 @@ uint64_t CNode::GetTotalBytesSent()
return nTotalBytesSent;
}
-void CNode::Fuzz(int nChance)
-{
- if (!fSuccessfullyConnected) return; // Don't fuzz initial handshake
- if (GetRand(nChance) != 0) return; // Fuzz 1 of every nChance messages
-
- switch (GetRand(3)) {
- case 0:
- // xor a random byte with a random value:
- if (!ssSend.empty()) {
- CDataStream::size_type pos = GetRand(ssSend.size());
- ssSend[pos] ^= (unsigned char)(GetRand(256));
- }
- break;
- case 1:
- // delete a random byte:
- if (!ssSend.empty()) {
- CDataStream::size_type pos = GetRand(ssSend.size());
- ssSend.erase(ssSend.begin() + pos);
- }
- break;
- case 2:
- // insert a random byte at a random position
- {
- CDataStream::size_type pos = GetRand(ssSend.size());
- char ch = (char)GetRand(256);
- ssSend.insert(ssSend.begin() + pos, ch);
- }
- break;
- }
- // Chance of more than one change half the time:
- // (more changes exponentially less likely):
- Fuzz(2);
-}
-
//
// CAddrDB
//
@@ -1881,11 +2014,11 @@ bool CAddrDB::Read(CAddrMan& addr)
return error("%s : Failed to open file %s", __func__, pathAddr.string());
// use file size to size memory buffer
- int fileSize = boost::filesystem::file_size(pathAddr);
- int dataSize = fileSize - sizeof(uint256);
+ uint64_t fileSize = boost::filesystem::file_size(pathAddr);
+ uint64_t dataSize = fileSize - sizeof(uint256);
// Don't try to resize to a negative number if file is small
- if (dataSize < 0)
- dataSize = 0;
+ if (fileSize >= sizeof(uint256))
+ dataSize = fileSize - sizeof(uint256);
vector vchData;
vchData.resize(dataSize);
uint256 hashIn;
@@ -1937,6 +2070,7 @@ CNode::CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn, bool fIn
nSendBytes = 0;
nRecvBytes = 0;
nTimeConnected = GetTime();
+ nTimeOffset = 0;
addr = addrIn;
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
nVersion = 0;
@@ -2047,11 +2181,11 @@ void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend)
AbortMessage();
return;
}
- if (mapArgs.count("-fuzzmessagestest"))
- Fuzz(GetArg("-fuzzmessagestest", 10));
- if (ssSend.size() == 0)
+ if (ssSend.size() == 0) {
+ LEAVE_CRITICAL_SECTION(cs_vSend);
return;
+ }
// Set the size
unsigned int nSize = ssSend.size() - CMessageHeader::HEADER_SIZE;
@@ -2076,3 +2210,124 @@ void CNode::EndMessage() UNLOCK_FUNCTION(cs_vSend)
LEAVE_CRITICAL_SECTION(cs_vSend);
}
+
+//
+// CBanDB
+//
+
+CBanDB::CBanDB()
+{
+ pathBanlist = GetDataDir() / "banlist.dat";
+}
+
+bool CBanDB::Write(const banmap_t& banSet)
+{
+ // Generate random temporary filename
+ unsigned short randv = 0;
+ GetRandBytes((unsigned char*)&randv, sizeof(randv));
+ std::string tmpfn = strprintf("banlist.dat.%04x", randv);
+
+ // serialize banlist, checksum data up to that point, then append csum
+ CDataStream ssBanlist(SER_DISK, CLIENT_VERSION);
+ ssBanlist << FLATDATA(Params().MessageStart());
+ ssBanlist << banSet;
+ uint256 hash = Hash(ssBanlist.begin(), ssBanlist.end());
+ ssBanlist << hash;
+
+ // open temp output file, and associate with CAutoFile
+ boost::filesystem::path pathTmp = GetDataDir() / tmpfn;
+ FILE *file = fopen(pathTmp.string().c_str(), "wb");
+ CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
+ if (fileout.IsNull())
+ return error("%s: Failed to open file %s", __func__, pathTmp.string());
+
+ // Write and commit header, data
+ try {
+ fileout << ssBanlist;
+ }
+ catch (const std::exception& e) {
+ return error("%s: Serialize or I/O error - %s", __func__, e.what());
+ }
+ FileCommit(fileout.Get());
+ fileout.fclose();
+
+ // replace existing banlist.dat, if any, with new banlist.dat.XXXX
+ if (!RenameOver(pathTmp, pathBanlist))
+ return error("%s: Rename-into-place failed", __func__);
+
+ return true;
+}
+
+bool CBanDB::Read(banmap_t& banSet)
+{
+ // open input file, and associate with CAutoFile
+ FILE *file = fopen(pathBanlist.string().c_str(), "rb");
+ CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
+ if (filein.IsNull())
+ return error("%s: Failed to open file %s", __func__, pathBanlist.string());
+
+ // use file size to size memory buffer
+ uint64_t fileSize = boost::filesystem::file_size(pathBanlist);
+ uint64_t dataSize = 0;
+ // Don't try to resize to a negative number if file is small
+ if (fileSize >= sizeof(uint256))
+ dataSize = fileSize - sizeof(uint256);
+ vector vchData;
+ vchData.resize(dataSize);
+ uint256 hashIn;
+
+ // read data and checksum from file
+ try {
+ filein.read((char *)&vchData[0], dataSize);
+ filein >> hashIn;
+ }
+ catch (const std::exception& e) {
+ return error("%s: Deserialize or I/O error - %s", __func__, e.what());
+ }
+ filein.fclose();
+
+ CDataStream ssBanlist(vchData, SER_DISK, CLIENT_VERSION);
+
+ // verify stored checksum matches input data
+ uint256 hashTmp = Hash(ssBanlist.begin(), ssBanlist.end());
+ if (hashIn != hashTmp)
+ return error("%s: Checksum mismatch, data corrupted", __func__);
+
+ unsigned char pchMsgTmp[4];
+ try {
+ // de-serialize file header (network specific magic number) and ..
+ ssBanlist >> FLATDATA(pchMsgTmp);
+
+ // ... verify the network matches ours
+ if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
+ return error("%s: Invalid network magic number", __func__);
+
+ // de-serialize address data into one CAddrMan object
+ ssBanlist >> banSet;
+ }
+ catch (const std::exception& e) {
+ return error("%s: Deserialize or I/O error - %s", __func__, e.what());
+ }
+
+ return true;
+}
+
+void DumpBanlist()
+{
+ CNode::SweepBanned(); // clean unused entries (if bantime has expired)
+
+ if (!CNode::BannedSetIsDirty())
+ return;
+
+ int64_t nStart = GetTimeMillis();
+
+ CBanDB bandb;
+ banmap_t banmap;
+ CNode::GetBanned(banmap);
+ if (bandb.Write(banmap)) {
+ CNode::SetBannedSetDirty(false);
+ }
+
+ LogPrint("net", "Flushed %d banned node ips/subnets to banlist.dat %dms\n",
+ banmap.size(), GetTimeMillis() - nStart);
+}
diff --git a/src/net.h b/src/net.h
index 159e05a..2fe1489 100644
--- a/src/net.h
+++ b/src/net.h
@@ -1,7 +1,7 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -51,6 +51,8 @@ static const unsigned int MAX_INV_SZ = 50000;
static const unsigned int MAX_ADDR_TO_SEND = 1000;
/** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 2 * 1024 * 1024;
+/** Maximum length of strSubVer in `version` message */
+static const unsigned int MAX_SUBVERSION_LENGTH = 256;
/** -listen default */
static const bool DEFAULT_LISTEN = true;
/** -upnp default */
@@ -69,6 +71,7 @@ void AddOneShot(std::string strDest);
bool RecvLine(SOCKET hSocket, std::string& strLine);
void AddressCurrentlyConnected(const CService& addr);
CNode* FindNode(const CNetAddr& ip);
+CNode* FindNode(const CSubNet& subNet);
CNode* FindNode(const std::string& addrName);
CNode* FindNode(const CService& ip);
CNode* ConnectNode(CAddress addrConnect, const char* pszDest = NULL, bool obfuScationMaster = false);
@@ -118,7 +121,6 @@ bool IsLocal(const CService& addr);
bool GetLocal(CService& addr, const CNetAddr* paddrPeer = NULL);
bool IsReachable(enum Network net);
bool IsReachable(const CNetAddr& addr);
-void SetReachable(enum Network net, bool fFlag = true);
CAddress GetLocalAddress(const CNetAddr* paddrPeer = NULL);
@@ -142,6 +144,9 @@ extern CCriticalSection cs_vAddedNodes;
extern NodeId nLastNodeId;
extern CCriticalSection cs_nLastNodeId;
+/** Subversion as sent to the P2P network in `version` messages */
+extern std::string strSubVersion;
+
struct LocalServiceInfo {
int nScore;
int nPort;
@@ -158,6 +163,7 @@ class CNodeStats
int64_t nLastSend;
int64_t nLastRecv;
int64_t nTimeConnected;
+ int64_t nTimeOffset;
std::string addrName;
int nVersion;
std::string cleanSubVer;
@@ -174,6 +180,10 @@ class CNodeStats
class CNetMessage
{
+private:
+ mutable CHash256 hasher;
+ mutable uint256 data_hash;
+
public:
bool in_data; // parsing header (false) or data (true)
@@ -202,6 +212,8 @@ class CNetMessage
return (hdr.nMessageSize == nDataPos);
}
+ const uint256& GetMessageHash() const;
+
void SetVersion(int nVersionIn)
{
hdrbuf.SetVersion(nVersionIn);
@@ -212,6 +224,66 @@ class CNetMessage
int readData(const char* pch, unsigned int nBytes);
};
+typedef enum BanReason
+{
+ BanReasonUnknown = 0,
+ BanReasonNodeMisbehaving = 1,
+ BanReasonManuallyAdded = 2
+} BanReason;
+
+class CBanEntry
+{
+public:
+ static const int CURRENT_VERSION=1;
+ int nVersion;
+ int64_t nCreateTime;
+ int64_t nBanUntil;
+ uint8_t banReason;
+
+ CBanEntry()
+ {
+ SetNull();
+ }
+
+ CBanEntry(int64_t nCreateTimeIn)
+ {
+ SetNull();
+ nCreateTime = nCreateTimeIn;
+ }
+
+ ADD_SERIALIZE_METHODS;
+
+ template
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ READWRITE(this->nVersion);
+ nVersion = this->nVersion;
+ READWRITE(nCreateTime);
+ READWRITE(nBanUntil);
+ READWRITE(banReason);
+ }
+
+ void SetNull()
+ {
+ nVersion = CBanEntry::CURRENT_VERSION;
+ nCreateTime = 0;
+ nBanUntil = 0;
+ banReason = BanReasonUnknown;
+ }
+
+ std::string banReasonToString()
+ {
+ switch (banReason) {
+ case BanReasonNodeMisbehaving:
+ return "node misbehaving";
+ case BanReasonManuallyAdded:
+ return "manually added";
+ default:
+ return "unknown";
+ }
+ }
+};
+
+typedef std::map banmap_t;
/** Information about a peer */
class CNode
@@ -236,6 +308,7 @@ class CNode
int64_t nLastSend;
int64_t nLastRecv;
int64_t nTimeConnected;
+ int64_t nTimeOffset;
CAddress addr;
std::string addrName;
CService addrLocal;
@@ -272,8 +345,9 @@ class CNode
protected:
// Denial-of-service detection/prevention
// Key is IP address, value is banned-until-time
- static std::map setBanned;
+ static banmap_t setBanned;
static CCriticalSection cs_setBanned;
+ static bool setBannedIsDirty;
std::vector vecRequestsFulfilled; //keep track of what client has asked for
@@ -341,7 +415,7 @@ class CNode
unsigned int GetTotalRecvSize()
{
unsigned int total = 0;
- BOOST_FOREACH (const CNetMessage& msg, vRecvMsg)
+ for (const CNetMessage& msg : vRecvMsg)
total += msg.vRecv.size() + 24;
return total;
}
@@ -353,7 +427,7 @@ class CNode
void SetRecvVersion(int nVersionIn)
{
nRecvVersion = nVersionIn;
- BOOST_FOREACH (CNetMessage& msg, vRecvMsg)
+ for (CNetMessage& msg : vRecvMsg)
msg.SetVersion(nVersionIn);
}
@@ -589,7 +663,7 @@ class CNode
bool HasFulfilledRequest(std::string strRequest)
{
- BOOST_FOREACH (std::string& type, vecRequestsFulfilled) {
+ for (std::string& type : vecRequestsFulfilled) {
if (type == strRequest) return true;
}
return false;
@@ -635,7 +709,21 @@ class CNode
// new code.
static void ClearBanned(); // needed for unit testing
static bool IsBanned(CNetAddr ip);
- static bool Ban(const CNetAddr& ip);
+ static bool IsBanned(CSubNet subnet);
+ static void Ban(const CNetAddr &ip, const BanReason &banReason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
+ static void Ban(const CSubNet &subNet, const BanReason &banReason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
+ static bool Unban(const CNetAddr &ip);
+ static bool Unban(const CSubNet &ip);
+ static void GetBanned(banmap_t &banmap);
+ static void SetBanned(const banmap_t &banmap);
+
+ //!check is the banlist has unwritten changes
+ static bool BannedSetIsDirty();
+ //!set the "dirty" flag for the banlist
+ static void SetBannedSetDirty(bool dirty=true);
+ //!clean unused entires (if bantime has expired)
+ static void SweepBanned();
+
void copyStats(CNodeStats& stats);
static bool IsWhitelistedRange(const CNetAddr& ip);
@@ -673,4 +761,17 @@ class CAddrDB
bool Read(CAddrMan& addr);
};
+/** Access to the banlist database (banlist.dat) */
+class CBanDB
+{
+private:
+ boost::filesystem::path pathBanlist;
+public:
+ CBanDB();
+ bool Write(const banmap_t& banSet);
+ bool Read(banmap_t& banSet);
+};
+
+void DumpBanlist();
+
#endif // BITCOIN_NET_H
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 115e269..ba4daa3 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -1,7 +1,7 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2015-2017 The PIVX Core developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -1306,6 +1306,13 @@ CSubNet::CSubNet(const std::string& strSubnet, bool fAllowLookup)
network.ip[x] &= netmask[x];
}
+CSubNet::CSubNet(const CNetAddr &addr):
+ valid(addr.IsValid())
+{
+ memset(netmask, 255, sizeof(netmask));
+ network = addr;
+}
+
bool CSubNet::Match(const CNetAddr& addr) const
{
if (!valid || !addr.IsValid())
@@ -1316,17 +1323,57 @@ bool CSubNet::Match(const CNetAddr& addr) const
return true;
}
+static inline int NetmaskBits(uint8_t x)
+{
+ switch(x) {
+ case 0x00: return 0; break;
+ case 0x80: return 1; break;
+ case 0xc0: return 2; break;
+ case 0xe0: return 3; break;
+ case 0xf0: return 4; break;
+ case 0xf8: return 5; break;
+ case 0xfc: return 6; break;
+ case 0xfe: return 7; break;
+ case 0xff: return 8; break;
+ default: return -1; break;
+ }
+}
+
std::string CSubNet::ToString() const
{
+ /* Parse binary 1{n}0{N-n} to see if mask can be represented as /n */
+ int cidr = 0;
+ bool valid_cidr = true;
+ int n = network.IsIPv4() ? 12 : 0;
+ for (; n < 16 && netmask[n] == 0xff; ++n)
+ cidr += 8;
+ if (n < 16) {
+ int bits = NetmaskBits(netmask[n]);
+ if (bits < 0)
+ valid_cidr = false;
+ else
+ cidr += bits;
+ ++n;
+ }
+ for (; n < 16 && valid_cidr; ++n)
+ if (netmask[n] != 0x00)
+ valid_cidr = false;
+
+ /* Format output */
std::string strNetmask;
- if (network.IsIPv4())
- strNetmask = strprintf("%u.%u.%u.%u", netmask[12], netmask[13], netmask[14], netmask[15]);
- else
- strNetmask = strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
- netmask[0] << 8 | netmask[1], netmask[2] << 8 | netmask[3],
- netmask[4] << 8 | netmask[5], netmask[6] << 8 | netmask[7],
- netmask[8] << 8 | netmask[9], netmask[10] << 8 | netmask[11],
- netmask[12] << 8 | netmask[13], netmask[14] << 8 | netmask[15]);
+ if (valid_cidr) {
+ strNetmask = strprintf("%u", cidr);
+ } else {
+ if (network.IsIPv4())
+ strNetmask = strprintf("%u.%u.%u.%u", netmask[12], netmask[13], netmask[14], netmask[15]);
+ else
+ strNetmask = strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
+ netmask[0] << 8 | netmask[1], netmask[2] << 8 | netmask[3],
+ netmask[4] << 8 | netmask[5], netmask[6] << 8 | netmask[7],
+ netmask[8] << 8 | netmask[9], netmask[10] << 8 | netmask[11],
+ netmask[12] << 8 | netmask[13], netmask[14] << 8 | netmask[15]);
+ }
+
return network.ToString() + "/" + strNetmask;
}
@@ -1345,6 +1392,11 @@ bool operator!=(const CSubNet& a, const CSubNet& b)
return !(a == b);
}
+bool operator<(const CSubNet& a, const CSubNet& b)
+{
+ return (a.network < b.network || (a.network == b.network && memcmp(a.netmask, b.netmask, 16) < 0));
+}
+
#ifdef WIN32
std::string NetworkErrorString(int err)
{
diff --git a/src/netbase.h b/src/netbase.h
index deced7af..74cfb76 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -1,7 +1,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2015-2017 The PIVX Core developers
// Copyright (c) 2017-2018 The Bulwark developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -123,6 +123,9 @@ class CSubNet
CSubNet();
explicit CSubNet(const std::string& strSubnet, bool fAllowLookup = false);
+ //constructor for single ip subnet (/32 or /128)
+ explicit CSubNet(const CNetAddr &addr);
+
bool Match(const CNetAddr& addr) const;
std::string ToString() const;
@@ -130,6 +133,16 @@ class CSubNet
friend bool operator==(const CSubNet& a, const CSubNet& b);
friend bool operator!=(const CSubNet& a, const CSubNet& b);
+ friend bool operator<(const CSubNet& a, const CSubNet& b);
+
+ ADD_SERIALIZE_METHODS;
+
+ template
+ inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+ READWRITE(network);
+ READWRITE(FLATDATA(netmask));
+ READWRITE(FLATDATA(valid));
+ }
};
/** A combination of a network address (CNetAddr) and a (TCP) port */
diff --git a/src/noui.cpp b/src/noui.cpp
index 18bb919..173d1e3 100644
--- a/src/noui.cpp
+++ b/src/noui.cpp
@@ -2,7 +2,7 @@
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/obfuscation.cpp b/src/obfuscation.cpp
index f862ad3..49fd378 100644
--- a/src/obfuscation.cpp
+++ b/src/obfuscation.cpp
@@ -1,6 +1,6 @@
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -133,7 +133,7 @@ void CObfuscationPool::ProcessMessageObfuscation(CNode* pfrom, std::string& strC
PrepareObfuscationDenominate();
}
} else {
- BOOST_FOREACH (CObfuscationQueue q, vecObfuscationQueue) {
+ for (CObfuscationQueue q : vecObfuscationQueue) {
if (q.vin == dsq.vin) return;
}
@@ -204,7 +204,7 @@ void CObfuscationPool::ProcessMessageObfuscation(CNode* pfrom, std::string& strC
CValidationState state;
CMutableTransaction tx;
- BOOST_FOREACH (const CTxOut o, out) {
+ for (const CTxOut o : out) {
nValueOut += o.nValue;
tx.vout.push_back(o);
@@ -222,7 +222,7 @@ void CObfuscationPool::ProcessMessageObfuscation(CNode* pfrom, std::string& strC
}
}
- BOOST_FOREACH (const CTxIn i, in) {
+ for (const CTxIn i : in) {
tx.vin.push_back(i);
LogPrint("obfuscation", "dsi -- tx in %s\n", i.ToString());
@@ -318,7 +318,7 @@ void CObfuscationPool::ProcessMessageObfuscation(CNode* pfrom, std::string& strC
bool success = false;
int count = 0;
- BOOST_FOREACH (const CTxIn item, sigs) {
+ for (const CTxIn item : sigs) {
if (AddScriptSig(item)) success = true;
LogPrint("obfuscation", " -- sigs count %d %d\n", (int)sigs.size(), count);
count++;
@@ -438,7 +438,7 @@ void CObfuscationPool::UnlockCoins()
MilliSleep(50);
continue;
}
- BOOST_FOREACH (CTxIn v, lockedCoins)
+ for (CTxIn v : lockedCoins)
pwalletMain->UnlockCoin(v.prevout);
break;
}
@@ -540,10 +540,10 @@ void CObfuscationPool::Check()
// make our new transaction
for (unsigned int i = 0; i < entries.size(); i++) {
- BOOST_FOREACH (const CTxOut& v, entries[i].vout)
+ for (const CTxOut& v : entries[i].vout)
txNew.vout.push_back(v);
- BOOST_FOREACH (const CTxDSIn& s, entries[i].sev)
+ for (const CTxDSIn& s : entries[i].sev)
txNew.vin.push_back(s);
}
@@ -672,9 +672,9 @@ void CObfuscationPool::ChargeFees()
if (r > 33) return;
if (state == POOL_STATUS_ACCEPTING_ENTRIES) {
- BOOST_FOREACH (const CTransaction& txCollateral, vecSessionCollateral) {
+ for (const CTransaction& txCollateral : vecSessionCollateral) {
bool found = false;
- BOOST_FOREACH (const CObfuScationEntry& v, entries) {
+ for (const CObfuScationEntry& v : entries) {
if (v.collateral == txCollateral) {
found = true;
}
@@ -690,8 +690,8 @@ void CObfuscationPool::ChargeFees()
if (state == POOL_STATUS_SIGNING) {
// who didn't sign?
- BOOST_FOREACH (const CObfuScationEntry v, entries) {
- BOOST_FOREACH (const CTxDSIn s, v.sev) {
+ for (const CObfuScationEntry v : entries) {
+ for (const CTxDSIn s : v.sev) {
if (!s.fHasSig) {
LogPrintf("CObfuscationPool::ChargeFees -- found uncooperative node (didn't sign). Found offence\n");
offences++;
@@ -716,9 +716,9 @@ void CObfuscationPool::ChargeFees()
r = rand() % 100;
if (state == POOL_STATUS_ACCEPTING_ENTRIES) {
- BOOST_FOREACH (const CTransaction& txCollateral, vecSessionCollateral) {
+ for (const CTransaction& txCollateral : vecSessionCollateral) {
bool found = false;
- BOOST_FOREACH (const CObfuScationEntry& v, entries) {
+ for (const CObfuScationEntry& v : entries) {
if (v.collateral == txCollateral) {
found = true;
}
@@ -743,8 +743,8 @@ void CObfuscationPool::ChargeFees()
if (state == POOL_STATUS_SIGNING) {
// who didn't sign?
- BOOST_FOREACH (const CObfuScationEntry v, entries) {
- BOOST_FOREACH (const CTxDSIn s, v.sev) {
+ for (const CObfuScationEntry v : entries) {
+ for (const CTxDSIn s : v.sev) {
if (!s.fHasSig && r > target) {
LogPrintf("CObfuscationPool::ChargeFees -- found uncooperative node (didn't sign). charging fees.\n");
@@ -770,7 +770,7 @@ void CObfuscationPool::ChargeRandomFees()
if (fMasterNode) {
int i = 0;
- BOOST_FOREACH (const CTransaction& txCollateral, vecSessionCollateral) {
+ for (const CTransaction& txCollateral : vecSessionCollateral) {
int r = rand() % 100;
/*
@@ -919,11 +919,11 @@ bool CObfuscationPool::SignatureValid(const CScript& newSig, const CTxIn& newVin
CScript sigPubKey = CScript();
unsigned int i = 0;
- BOOST_FOREACH (CObfuScationEntry& e, entries) {
- BOOST_FOREACH (const CTxOut& out, e.vout)
+ for (CObfuScationEntry& e : entries) {
+ for (const CTxOut& out : e.vout)
txNew.vout.push_back(out);
- BOOST_FOREACH (const CTxDSIn& s, e.sev) {
+ for (const CTxDSIn& s : e.sev) {
txNew.vin.push_back(s);
if (s == newVin) {
@@ -958,7 +958,7 @@ bool CObfuscationPool::IsCollateralValid(const CTransaction& txCollateral)
int64_t nValueOut = 0;
bool missingTx = false;
- BOOST_FOREACH (const CTxOut o, txCollateral.vout) {
+ for (const CTxOut o : txCollateral.vout) {
nValueOut += o.nValue;
if (!o.scriptPubKey.IsNormalPaymentScript()) {
@@ -967,7 +967,7 @@ bool CObfuscationPool::IsCollateralValid(const CTransaction& txCollateral)
}
}
- BOOST_FOREACH (const CTxIn i, txCollateral.vin) {
+ for (const CTxIn i : txCollateral.vin) {
CTransaction tx2;
uint256 hash;
if (GetTransaction(i.prevout.hash, tx2, hash, true)) {
@@ -1012,7 +1012,7 @@ bool CObfuscationPool::AddEntry(const std::vector& newInput, const CAmoun
{
if (!fMasterNode) return false;
- BOOST_FOREACH (CTxIn in, newInput) {
+ for (CTxIn in : newInput) {
if (in.prevout.IsNull() || nAmount < 0) {
LogPrint("obfuscation", "CObfuscationPool::AddEntry - input not valid!\n");
errorID = ERR_INVALID_INPUT;
@@ -1035,10 +1035,10 @@ bool CObfuscationPool::AddEntry(const std::vector& newInput, const CAmoun
return false;
}
- BOOST_FOREACH (CTxIn in, newInput) {
+ for (CTxIn in : newInput) {
LogPrint("obfuscation", "looking for vin -- %s\n", in.ToString());
- BOOST_FOREACH (const CObfuScationEntry& v, entries) {
- BOOST_FOREACH (const CTxDSIn& s, v.sev) {
+ for (const CObfuScationEntry& v : entries) {
+ for (const CTxDSIn& s : v.sev) {
if ((CTxIn)s == in) {
LogPrint("obfuscation", "CObfuscationPool::AddEntry - found in vin\n");
errorID = ERR_ALREADY_HAVE;
@@ -1064,8 +1064,8 @@ bool CObfuscationPool::AddScriptSig(const CTxIn& newVin)
LogPrint("obfuscation", "CObfuscationPool::AddScriptSig -- new sig %s\n", newVin.scriptSig.ToString().substr(0, 24));
- BOOST_FOREACH (const CObfuScationEntry& v, entries) {
- BOOST_FOREACH (const CTxDSIn& s, v.sev) {
+ for (const CObfuScationEntry& v : entries) {
+ for (const CTxDSIn& s : v.sev) {
if (s.scriptSig == newVin.scriptSig) {
LogPrint("obfuscation", "CObfuscationPool::AddScriptSig - already exists\n");
return false;
@@ -1080,7 +1080,7 @@ bool CObfuscationPool::AddScriptSig(const CTxIn& newVin)
LogPrint("obfuscation", "CObfuscationPool::AddScriptSig -- sig %s\n", newVin.ToString());
- BOOST_FOREACH (CTxIn& vin, finalTransaction.vin) {
+ for (CTxIn& vin : finalTransaction.vin) {
if (newVin.prevout == vin.prevout && vin.nSequence == newVin.nSequence) {
vin.scriptSig = newVin.scriptSig;
vin.prevPubKey = newVin.prevPubKey;
@@ -1101,8 +1101,8 @@ bool CObfuscationPool::AddScriptSig(const CTxIn& newVin)
// Check to make sure everything is signed
bool CObfuscationPool::SignaturesComplete()
{
- BOOST_FOREACH (const CObfuScationEntry& v, entries) {
- BOOST_FOREACH (const CTxDSIn& s, v.sev) {
+ for (const CObfuScationEntry& v : entries) {
+ for (const CTxDSIn& s : v.sev) {
if (!s.fHasSig) return false;
}
}
@@ -1126,13 +1126,13 @@ void CObfuscationPool::SendObfuscationDenominate(std::vector& vin, std::v
}
// lock the funds we're going to use
- BOOST_FOREACH (CTxIn in, txCollateral.vin)
+ for (CTxIn in : txCollateral.vin)
lockedCoins.push_back(in);
- BOOST_FOREACH (CTxIn in, vin)
+ for (CTxIn in : vin)
lockedCoins.push_back(in);
- //BOOST_FOREACH(CTxOut o, vout)
+ //for(CTxOut o : vout)
// LogPrintf(" vout - %s\n", o.ToString());
@@ -1165,12 +1165,12 @@ void CObfuscationPool::SendObfuscationDenominate(std::vector& vin, std::v
CValidationState state;
CMutableTransaction tx;
- BOOST_FOREACH (const CTxOut& o, vout) {
+ for (const CTxOut& o : vout) {
nValueOut += o.nValue;
tx.vout.push_back(o);
}
- BOOST_FOREACH (const CTxIn& i, vin) {
+ for (const CTxIn& i : vin) {
tx.vin.push_back(i);
LogPrint("obfuscation", "dsi -- tx in %s\n", i.ToString());
@@ -1266,8 +1266,8 @@ bool CObfuscationPool::SignFinalTransaction(CTransaction& finalTransactionNew, C
vector sigs;
//make sure my inputs/outputs are present, otherwise refuse to sign
- BOOST_FOREACH (const CObfuScationEntry e, entries) {
- BOOST_FOREACH (const CTxDSIn s, e.sev) {
+ for (const CObfuScationEntry e : entries) {
+ for (const CTxDSIn s : e.sev) {
/* Sign my transaction and all outputs */
int mine = -1;
CScript prevPubKey = CScript();
@@ -1287,7 +1287,7 @@ bool CObfuscationPool::SignFinalTransaction(CTransaction& finalTransactionNew, C
CAmount nValue2 = 0;
for (unsigned int i = 0; i < finalTransaction.vout.size(); i++) {
- BOOST_FOREACH (const CTxOut& o, e.vout) {
+ for (const CTxOut& o : e.vout) {
if (finalTransaction.vout[i] == o) {
foundOutputs++;
nValue1 += finalTransaction.vout[i].nValue;
@@ -1295,7 +1295,7 @@ bool CObfuscationPool::SignFinalTransaction(CTransaction& finalTransactionNew, C
}
}
- BOOST_FOREACH (const CTxOut o, e.vout)
+ for (const CTxOut o : e.vout)
nValue2 += o.nValue;
int targetOuputs = e.vout.size();
@@ -1840,7 +1840,7 @@ bool CObfuscationPool::IsCompatibleWithEntries(std::vector& vout)
{
if (GetDenominations(vout) == 0) return false;
- BOOST_FOREACH (const CObfuScationEntry v, entries) {
+ for (const CObfuScationEntry v : entries) {
LogPrintf(" IsCompatibleWithEntries %d %d\n", GetDenominations(vout), GetDenominations(v.vout));
/*
BOOST_FOREACH(CTxOut o1, vout)
@@ -1950,7 +1950,7 @@ int CObfuscationPool::GetDenominations(const std::vector& vout)
{
std::vector vout2;
- BOOST_FOREACH (CTxDSOut out, vout)
+ for (CTxDSOut out : vout)
vout2.push_back(out);
return GetDenominations(vout2);
@@ -1962,13 +1962,13 @@ int CObfuscationPool::GetDenominations(const std::vector& vout, bool fSi
std::vector > denomUsed;
// make a list of denominations, with zero uses
- BOOST_FOREACH (int64_t d, obfuScationDenominations)
+ for (int64_t d : obfuScationDenominations)
denomUsed.push_back(make_pair(d, 0));
// look for denominations and update uses to 1
- BOOST_FOREACH (CTxOut out, vout) {
+ for (CTxOut out : vout) {
bool found = false;
- BOOST_FOREACH (PAIRTYPE(int64_t, int) & s, denomUsed) {
+ for (PAIRTYPE(int64_t, int) & s : denomUsed) {
if (out.nValue == s.first) {
s.second = 1;
found = true;
@@ -1981,7 +1981,7 @@ int CObfuscationPool::GetDenominations(const std::vector& vout, bool fSi
int c = 0;
// if the denomination is used, shift the bit on.
// then move to the next
- BOOST_FOREACH (PAIRTYPE(int64_t, int) & s, denomUsed) {
+ for (PAIRTYPE(int64_t, int) & s : denomUsed) {
int bit = (fSingleRandomDenom ? rand() % 2 : 1) * s.second;
denom |= bit << c++;
if (fSingleRandomDenom && bit) break; // use just one random denomination
@@ -2214,7 +2214,7 @@ bool CObfuscationQueue::Sign()
bool CObfuscationQueue::Relay()
{
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes) {
+ for (CNode* pnode : vNodes) {
// always relay to everyone
pnode->PushMessage("dsq", (*this));
}
@@ -2244,7 +2244,7 @@ bool CObfuscationQueue::CheckSignature()
void CObfuscationPool::RelayFinalTransaction(const int sessionID, const CTransaction& txNew)
{
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes) {
+ for (CNode* pnode : vNodes) {
pnode->PushMessage("dsf", sessionID, txNew);
}
}
@@ -2256,10 +2256,10 @@ void CObfuscationPool::RelayIn(const std::vector& vin, const int64_t& n
std::vector vin2;
std::vector vout2;
- BOOST_FOREACH (CTxDSIn in, vin)
+ for (CTxDSIn in : vin)
vin2.push_back(in);
- BOOST_FOREACH (CTxDSOut out, vout)
+ for (CTxDSOut out : vout)
vout2.push_back(out);
CNode* pnode = FindNode(pSubmittedToMasternode->addr);
@@ -2272,14 +2272,14 @@ void CObfuscationPool::RelayIn(const std::vector& vin, const int64_t& n
void CObfuscationPool::RelayStatus(const int sessionID, const int newState, const int newEntriesCount, const int newAccepted, const int errorID)
{
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes)
+ for (CNode* pnode : vNodes)
pnode->PushMessage("dssu", sessionID, newState, newEntriesCount, newAccepted, errorID);
}
void CObfuscationPool::RelayCompletedTransaction(const int sessionID, const bool error, const int errorID)
{
LOCK(cs_vNodes);
- BOOST_FOREACH (CNode* pnode, vNodes)
+ for (CNode* pnode : vNodes)
pnode->PushMessage("dsc", sessionID, error, errorID);
}
diff --git a/src/obfuscation.h b/src/obfuscation.h
index 92b184d..711befb 100644
--- a/src/obfuscation.h
+++ b/src/obfuscation.h
@@ -411,15 +411,15 @@ class CObfuscationPool
void UpdateState(unsigned int newState)
{
if (fMasterNode && (newState == POOL_STATUS_ERROR || newState == POOL_STATUS_SUCCESS)) {
- LogPrint("obfuscation", "CObfuscationPool::UpdateState() - Can't set state to ERROR or SUCCESS as a Masternode. \n");
+ // LogPrint("obfuscation", "CObfuscationPool::UpdateState() - Can't set state to ERROR or SUCCESS as a Masternode. \n");
return;
}
- LogPrintf("CObfuscationPool::UpdateState() == %d | %d \n", state, newState);
+ // LogPrintf("CObfuscationPool::UpdateState() == %d | %d \n", state, newState);
if (state != newState) {
lastTimeChanged = GetTimeMillis();
if (fMasterNode) {
- RelayStatus(obfuScationPool.sessionID, newState, obfuScationPool.GetEntriesCount(), MASTERNODE_RESET);
+ RelayStatus(obfuScationPool.sessionID, obfuScationPool.GetState(), obfuScationPool.GetEntriesCount(), MASTERNODE_RESET);
}
}
state = newState;
diff --git a/src/pow.cpp b/src/pow.cpp
index 5749e9f..41effb6 100644
--- a/src/pow.cpp
+++ b/src/pow.cpp
@@ -1,7 +1,7 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -30,7 +30,9 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, uint32_t nTime)
uint256 PastDifficultyAverage;
uint256 PastDifficultyAveragePrev;
- if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < PastBlocksMin) {
+ if (BlockLastSolved == NULL ||
+ BlockLastSolved->nHeight == 0 ||
+ BlockLastSolved->nHeight < PastBlocksMin) {
return Params().StartWork().GetCompact();
}
diff --git a/src/pow.h b/src/pow.h
index d80230a..5a80fc0 100644
--- a/src/pow.h
+++ b/src/pow.h
@@ -8,8 +8,10 @@
#include
+class CBlockHeader;
class CBlockIndex;
class uint256;
+class arith_uint256;
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, uint32_t nTime);
diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp
index 45e98db..021fa60 100644
--- a/src/primitives/block.cpp
+++ b/src/primitives/block.cpp
@@ -86,7 +86,7 @@ uint256 CBlock::BuildMerkleTree(bool* fMutated) const
mutated = true;
}
vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]),
- BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
+ BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
}
j += nSize;
}
@@ -153,7 +153,6 @@ void CBlock::print() const
LogPrintf("%s", ToString());
}
-// ppcoin: sign block
bool CBlock::SignBlock(const CKeyStore& keystore)
{
std::vector vSolutions;
diff --git a/src/primitives/block.h b/src/primitives/block.h
index 16a34dd..42739a6 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -7,7 +7,7 @@
#ifndef BITCOIN_PRIMITIVES_BLOCK_H
#define BITCOIN_PRIMITIVES_BLOCK_H
-#include "transaction.h"
+#include "primitives/transaction.h"
#include "../keystore.h"
#include "../serialize.h"
#include "../uint256.h"
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index 1967270..094b2a6 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -1,7 +1,7 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -14,7 +14,6 @@
#include "tinyformat.h"
#include "utilstrencodings.h"
-#include
extern bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow);
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index faef4b7..ccaa580 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -7,13 +7,13 @@
#ifndef BITCOIN_PRIMITIVES_TRANSACTION_H
#define BITCOIN_PRIMITIVES_TRANSACTION_H
-#include
-
#include "../amount.h"
#include "../script/script.h"
#include "../serialize.h"
#include "../uint256.h"
+#include
+
class CTransaction;
/** An outpoint - a combination of a transaction hash and an index n into its vout */
@@ -276,7 +276,6 @@ class CTransaction
}
std::string ToString() const;
-
bool GetCoinAge(uint64_t& nCoinAge) const; // ppcoin: get transaction coin age
};
diff --git a/src/protocol.cpp b/src/protocol.cpp
index dedfd28..fbed8b0 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -14,7 +14,7 @@
#endif
static const char* ppszTypeName[] =
-{
+ {
"ERROR",
"tx",
"block",
@@ -23,10 +23,15 @@ static const char* ppszTypeName[] =
"tx lock vote",
"spork",
"mn winner",
+ "mn scan error",
+ "mn budget vote",
+ "mn budget proposal",
+ "mn budget finalized",
+ "mn budget finalized vote",
+ "mn quorum",
"mn announce",
"mn ping",
- "dstx"
-};
+ "dstx"};
CMessageHeader::CMessageHeader()
{
diff --git a/src/protocol.h b/src/protocol.h
index d97a8da..d5c462f 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -162,6 +162,12 @@ enum {
MSG_TXLOCK_VOTE,
MSG_SPORK,
MSG_MASTERNODE_WINNER,
+ MSG_MASTERNODE_SCANNING_ERROR,
+ MSG_BUDGET_VOTE,
+ MSG_BUDGET_PROPOSAL,
+ MSG_BUDGET_FINALIZED,
+ MSG_BUDGET_FINALIZED_VOTE,
+ MSG_MASTERNODE_QUORUM,
MSG_MASTERNODE_ANNOUNCE,
MSG_MASTERNODE_PING,
MSG_DSTX
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index 3bcd32a..6ee21c0 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -1,7 +1,7 @@
// Copyright (c) 2011-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp
index 10eeb64..f3a4444 100644
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -1,7 +1,7 @@
// Copyright (c) 2011-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -11,7 +11,7 @@
#include "walletmodel.h"
#include "base58.h"
-#include "wallet.h"
+#include "wallet/wallet.h"
#include
#include
@@ -78,7 +78,7 @@ class AddressTablePriv
cachedAddressTable.clear();
{
LOCK(wallet->cs_wallet);
- BOOST_FOREACH (const PAIRTYPE(CTxDestination, CAddressBookData) & item, wallet->mapAddressBook) {
+ for (const PAIRTYPE(CTxDestination, CAddressBookData) & item : wallet->mapAddressBook) {
const CBitcoinAddress& address = item.first;
bool fMine = IsMine(*wallet, address.Get());
AddressTableEntry::Type addressType = translateTransactionType(
diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h
index 8add193..5cd5e63 100644
--- a/src/qt/addresstablemodel.h
+++ b/src/qt/addresstablemodel.h
@@ -1,7 +1,7 @@
// Copyright (c) 2011-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp
index a013b91..c238672 100644
--- a/src/qt/askpassphrasedialog.cpp
+++ b/src/qt/askpassphrasedialog.cpp
@@ -1,7 +1,7 @@
// Copyright (c) 2011-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/bip38tooldialog.cpp b/src/qt/bip38tooldialog.cpp
index 5d990f5..b2a7ac4 100644
--- a/src/qt/bip38tooldialog.cpp
+++ b/src/qt/bip38tooldialog.cpp
@@ -1,7 +1,7 @@
// Copyright (c) 2011-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -15,7 +15,7 @@
#include "base58.h"
#include "bip38.h"
#include "init.h"
-#include "wallet.h"
+#include "wallet/wallet.h"
#include
#include
diff --git a/src/qt/bitcoinaddressvalidator.cpp b/src/qt/bitcoinaddressvalidator.cpp
index b6d8d19..9dbfac3 100644
--- a/src/qt/bitcoinaddressvalidator.cpp
+++ b/src/qt/bitcoinaddressvalidator.cpp
@@ -1,7 +1,7 @@
// Copyright (c) 2011-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index fb1a46a..71f257f 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -1,7 +1,7 @@
// Copyright (c) 2011-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -203,8 +203,8 @@ QString windowTitle = tr("XDNA Core") + " - ";
frameBlocksLayout->addWidget(labelEncryptionIcon);
}
-
- // frameBlocksLayout->addWidget(labelStakingIcon);
+
+ frameBlocksLayout->addWidget(labelStakingIcon);
frameBlocksLayout->addWidget(labelBlocksIcon);
frameBlocksLayout->addWidget(labelConnectionsIcon);
frameBlocksLayout->setAlignment(Qt::AlignRight);
@@ -280,13 +280,13 @@ QString windowTitle = tr("XDNA Core") + " - ";
subscribeToCoreSignals();
//will be activate when pow ends
- /*
+
labelStakingIcon->hide();
QTimer* timerStakingIcon = new QTimer(labelStakingIcon);
connect(timerStakingIcon, SIGNAL(timeout()), this, SLOT(setStakingStatus()));
timerStakingIcon->start(10000);
setStakingStatus();
- */
+
}
BitcoinGUI::~BitcoinGUI()
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 0758dc9..182b010 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -1,7 +1,7 @@
// Copyright (c) 2011-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp
index 4ec3ced..2be4b4e 100755
--- a/src/qt/bitcoinunits.cpp
+++ b/src/qt/bitcoinunits.cpp
@@ -1,7 +1,7 @@
// Copyright (c) 2011-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/bitcoinunits.h b/src/qt/bitcoinunits.h
index 6f27d13..c9e90bf 100755
--- a/src/qt/bitcoinunits.h
+++ b/src/qt/bitcoinunits.h
@@ -1,7 +1,7 @@
// Copyright (c) 2011-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/blockexplorer.cpp b/src/qt/blockexplorer.cpp
index c0a5229..0865028 100644
--- a/src/qt/blockexplorer.cpp
+++ b/src/qt/blockexplorer.cpp
@@ -401,7 +401,7 @@ std::string AddressToString(const CBitcoinAddress& Address)
{
std::vector Txs;
paddressmap->GetTxs(Txs, AddressScript.GetID());
- BOOST_FOREACH (const CDiskTxPos& pos, Txs)
+ for (const CDiskTxPos& pos : Txs)
{
CTransaction tx;
CBlock block;
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index e077fbb..57cc59e 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -1,7 +1,7 @@
// Copyright (c) 2011-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -62,7 +62,7 @@ int ClientModel::getNumConnections(unsigned int flags) const
return vNodes.size();
int nNum = 0;
- BOOST_FOREACH (CNode* pnode, vNodes)
+ for (CNode* pnode : vNodes)
if (flags & (pnode->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT))
nNum++;
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 7cac01a..60a51f7 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -1,7 +1,7 @@
// Copyright (c) 2011-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 176d37b..3bf5c53 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -1,7 +1,7 @@
// Copyright (c) 2011-2014 The Bitcoin developers
// Copyright (c) 2014-2015 The Dash developers
// Copyright (c) 2015-2017 The PIVX developers
-// Copyright (c) 2017-2018 The XDNA Core developers
+// Copyright (c) 2017-2019 The XDNA Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -18,7 +18,7 @@
#include "coincontrol.h"
#include "main.h"
#include "obfuscation.h"
-#include "wallet.h"
+#include "wallet/wallet.h"
#include "multisigdialog.h"
#include // for 'map_list_of()'
@@ -441,13 +441,6 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column)
else {
coinControl->Select(outpt);
CTxIn vin(outpt);
- int rounds = pwalletMain->GetInputObfuscationRounds(vin);
- if (coinControl->useObfuScation && rounds < nObfuscationRounds) {
- QMessageBox::warning(this, windowTitle(),
- tr("Non-anonymized input selected.