Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: DeFiCh/ain
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 6ecc3ec7030f6f9f3c2b327d497fde712b0c8299
Choose a base ref
..
head repository: DeFiCh/ain
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a7d914f15f762d121ac2c5d07d38d30cf7e09d4d
Choose a head ref
Showing with 2,384 additions and 4,183 deletions.
  1. +118 −0 build-aux/m4/ax_boost_chrono.m4
  2. +150 −0 build-aux/m4/ax_boost_thread.m4
  3. +12 −0 build_msvc/defi_config.h
  4. +1 −1 ci/test/00_setup_env_amd64_asan.sh
  5. +1 −1 ci/test/00_setup_env_amd64_fuzz.sh
  6. +1 −1 ci/test/00_setup_env_amd64_trusty.sh
  7. +1 −1 ci/test/00_setup_env_amd64_tsan.sh
  8. +56 −3 configure.ac
  9. +1 −1 depends/packages/boost.mk
  10. +1 −1 doc/build-unix.md
  11. +1 −2 src/addrman.cpp
  12. +8 −3 src/bench/checkqueue.cpp
  13. +1 −1 src/bench/examples.cpp
  14. +7 −13 src/chainparams.cpp
  15. +0 −1 src/chainparams.h
  16. +29 −59 src/checkqueue.h
  17. +1 −1 src/consensus/params.h
  18. +8 −23 src/consensus/tx_check.cpp
  19. +2 −11 src/consensus/tx_check.h
  20. +15 −15 src/consensus/tx_verify.cpp
  21. +1 −1 src/consensus/tx_verify.h
  22. +1 −1 src/defi-cli.cpp
  23. +1 −1 src/defid.cpp
  24. +5 −19 src/flushablestorage.h
  25. +1 −1 src/httprpc.cpp
  26. +3 −0 src/index/txindex.cpp
  27. +39 −74 src/init.cpp
  28. +11 −14 src/masternodes/accounts.cpp
  29. +2 −6 src/masternodes/accounts.h
  30. +77 −95 src/masternodes/accountshistory.cpp
  31. +42 −16 src/masternodes/accountshistory.h
  32. +1 −1 src/masternodes/anchors.cpp
  33. +3 −3 src/masternodes/anchors.h
  34. +86 −224 src/masternodes/govvariables/attributes.cpp
  35. +14 −55 src/masternodes/govvariables/attributes.h
  36. +1 −23 src/masternodes/gv.cpp
  37. +123 −196 src/masternodes/masternodes.cpp
  38. +28 −80 src/masternodes/masternodes.h
  39. +429 −311 src/masternodes/mn_checks.cpp
  40. +50 −26 src/masternodes/mn_checks.h
  41. +7 −49 src/masternodes/mn_rpc.cpp
  42. +1 −17 src/masternodes/mn_rpc.h
  43. +71 −240 src/masternodes/rpc_accounts.cpp
  44. +18 −16 src/masternodes/rpc_customtx.cpp
  45. +40 −87 src/masternodes/rpc_masternodes.cpp
  46. +4 −35 src/masternodes/rpc_oracles.cpp
  47. +0 −4 src/masternodes/rpc_poolpair.cpp
  48. +3 −3 src/masternodes/rpc_tokens.cpp
  49. +2 −2 src/masternodes/rpc_vault.cpp
  50. +32 −0 src/masternodes/tokens.cpp
  51. +2 −0 src/masternodes/tokens.h
  52. +0 −1 src/masternodes/vaulthistory.h
  53. +14 −18 src/miner.cpp
  54. +5 −2 src/node/coinstats.cpp
  55. +1 −2 src/node/coinstats.h
  56. +5 −13 src/pos.cpp
  57. +0 −16 src/primitives/transaction.h
  58. +1 −1 src/random.cpp
  59. +7 −3 src/rpc/blockchain.cpp
  60. +0 −4 src/rpc/client.cpp
  61. +6 −4 src/rpc/mining.cpp
  62. +4 −0 src/rpc/resultcache.cpp
  63. +4 −0 src/rpc/resultcache.h
  64. +1 −6 src/rpc/server.cpp
  65. +0 −3 src/rpc/server.h
  66. +36 −15 src/scheduler.cpp
  67. +24 −32 src/scheduler.h
  68. +4 −8 src/script/sigcache.cpp
  69. +7 −6 src/spv/bitcoin/BRPeer.cpp
  70. +2 −3 src/spv/bitcoin/BRPeer.h
  71. +5 −4 src/spv/bitcoin/BRPeerManager.cpp
  72. +0 −2 src/spv/bitcoin/BRPeerManager.h
  73. +8 −1 src/spv/bitcoin/BRWallet.cpp
  74. +4 −4 src/spv/spv_wrapper.h
  75. +1 −1 src/test/blockencodings_tests.cpp
  76. +51 −26 src/test/checkqueue_tests.cpp
  77. +5 −11 src/test/cuckoocache_tests.cpp
  78. +16 −3 src/test/oracles_tests.cpp
  79. +16 −31 src/test/pos_tests.cpp
  80. +7 −36 src/test/reverselock_tests.cpp
  81. +35 −32 src/test/scheduler_tests.cpp
  82. +7 −7 src/test/setup_common.cpp
  83. +3 −1 src/test/setup_common.h
  84. +26 −0 src/test/storage_tests.cpp
  85. +5 −2 src/test/transaction_tests.cpp
  86. +2 −2 src/test/util_tests.cpp
  87. +9 −0 src/txdb.cpp
  88. +8 −27 src/txmempool.cpp
  89. +2 −8 src/txmempool.h
  90. +7 −0 src/util/system.h
  91. +19 −4 src/util/time.cpp
  92. +2 −2 src/util/time.h
  93. +103 −327 src/validation.cpp
  94. +8 −23 src/validation.h
  95. +9 −2 src/wallet/db.cpp
  96. +8 −0 src/wallet/walletdb.cpp
  97. +1 −1 test/functional/feature_asymmetric_fee.py
  98. +3 −14 test/functional/feature_burn_address.py
  99. +6 −367 test/functional/feature_futures.py
  100. +2 −2 test/functional/feature_loan_basics.py
  101. 0 test/functional/feature_loan_get_interest.py
  102. +2 −200 test/functional/feature_loan_payback_dfi.py
  103. +13 −17 test/functional/feature_loan_payback_dfi_v2.py
  104. +220 −248 test/functional/feature_poolswap.py
  105. +15 −95 test/functional/feature_poolswap_mainnet.py
  106. +2 −45 test/functional/feature_reject_customtxs.py
  107. 0 test/functional/feature_rpcstats.py
  108. +10 −69 test/functional/feature_setgov.py
  109. +18 −32 test/functional/feature_token_fork.py
  110. +10 −69 test/functional/feature_token_split.py
  111. +4 −0 test/functional/feature_token_split_usd_value.py
  112. +0 −99 test/functional/feature_tx_versioning_and_expiration.py
  113. +22 −0 test/functional/feature_update_mn.py
  114. +1 −1 test/functional/rpc_blockchain.py
  115. +4 −24 test/functional/rpc_getaccounthistory.py
  116. +41 −19 test/functional/rpc_getcustomtx.py
  117. +1 −24 test/functional/rpc_mn_basic.py
  118. +0 −419 test/functional/rpc_updatemasternode.py
  119. +0 −2 test/functional/test_runner.py
  120. +2 −5 test/lint/lint-circular-dependencies.sh
  121. +8 −0 test/lint/lint-includes.sh
118 changes: 118 additions & 0 deletions build-aux/m4/ax_boost_chrono.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_boost_chrono.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_BOOST_CHRONO
#
# DESCRIPTION
#
# Test for Chrono library from the Boost C++ libraries. The macro requires
# a preceding call to AX_BOOST_BASE. Further documentation is available at
# <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_CHRONO_LIB)
#
# And sets:
#
# HAVE_BOOST_CHRONO
#
# LICENSE
#
# Copyright (c) 2012 Xiyue Deng <manphiz@gmail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.

#serial 4

AC_DEFUN([AX_BOOST_CHRONO],
[
AC_ARG_WITH([boost-chrono],
AS_HELP_STRING([--with-boost-chrono@<:@=special-lib@:>@],
[use the Chrono library from boost - it is possible to specify a certain library for the linker
e.g. --with-boost-chrono=boost_chrono-gcc-mt ]),
[
if test "$withval" = "no"; then
want_boost="no"
elif test "$withval" = "yes"; then
want_boost="yes"
ax_boost_user_chrono_lib=""
else
want_boost="yes"
ax_boost_user_chrono_lib="$withval"
fi
],
[want_boost="yes"]
)
if test "x$want_boost" = "xyes"; then
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_BUILD])
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_CACHE_CHECK(whether the Boost::Chrono library is available,
ax_cv_boost_chrono,
[AC_LANG_PUSH([C++])
CXXFLAGS_SAVE=$CXXFLAGS
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/chrono.hpp>]],
[[boost::chrono::system_clock::time_point* time = new boost::chrono::system_clock::time_point; delete time;]])],
ax_cv_boost_chrono=yes, ax_cv_boost_chrono=no)
CXXFLAGS=$CXXFLAGS_SAVE
AC_LANG_POP([C++])
])
if test "x$ax_cv_boost_chrono" = "xyes"; then
AC_SUBST(BOOST_CPPFLAGS)
AC_DEFINE(HAVE_BOOST_CHRONO,,[define if the Boost::Chrono library is available])
BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
LDFLAGS_SAVE=$LDFLAGS
if test "x$ax_boost_user_chrono_lib" = "x"; then
for libextension in `ls $BOOSTLIBDIR/libboost_chrono*.so* $BOOSTLIBDIR/libboost_chrono*.dylib* $BOOSTLIBDIR/libboost_chrono*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_chrono.*\)\.so.*$;\1;' -e 's;^lib\(boost_chrono.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_chrono.*\)\.a.*$;\1;'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_CHRONO_LIB="-l$ax_lib"; AC_SUBST(BOOST_CHRONO_LIB) link_chrono="yes"; break],
[link_chrono="no"])
done
if test "x$link_chrono" != "xyes"; then
for libextension in `ls $BOOSTLIBDIR/boost_chrono*.dll* $BOOSTLIBDIR/boost_chrono*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_chrono.*\)\.dll.*$;\1;' -e 's;^\(boost_chrono.*\)\.a.*$;\1;'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_CHRONO_LIB="-l$ax_lib"; AC_SUBST(BOOST_CHRONO_LIB) link_chrono="yes"; break],
[link_chrono="no"])
done
fi
else
for ax_lib in $ax_boost_user_chrono_lib boost_chrono-$ax_boost_user_chrono_lib; do
AC_CHECK_LIB($ax_lib, exit,
[BOOST_CHRONO_LIB="-l$ax_lib"; AC_SUBST(BOOST_CHRONO_LIB) link_chrono="yes"; break],
[link_chrono="no"])
done
fi
if test "x$ax_lib" = "x"; then
AC_MSG_ERROR(Could not find a version of the library!)
fi
if test "x$link_chrono" = "xno"; then
AC_MSG_ERROR(Could not link against $ax_lib !)
fi
fi
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
fi
])
150 changes: 150 additions & 0 deletions build-aux/m4/ax_boost_thread.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_boost_thread.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_BOOST_THREAD
#
# DESCRIPTION
#
# Test for Thread library from the Boost C++ libraries. The macro requires
# a preceding call to AX_BOOST_BASE. Further documentation is available at
# <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_THREAD_LIB)
#
# And sets:
#
# HAVE_BOOST_THREAD
#
# LICENSE
#
# Copyright (c) 2009 Thomas Porschberg <thomas@randspringer.de>
# Copyright (c) 2009 Michael Tindal
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.

#serial 27

AC_DEFUN([AX_BOOST_THREAD],
[
AC_ARG_WITH([boost-thread],
AS_HELP_STRING([--with-boost-thread@<:@=special-lib@:>@],
[use the Thread library from boost - it is possible to specify a certain library for the linker
e.g. --with-boost-thread=boost_thread-gcc-mt ]),
[
if test "$withval" = "no"; then
want_boost="no"
elif test "$withval" = "yes"; then
want_boost="yes"
ax_boost_user_thread_lib=""
else
want_boost="yes"
ax_boost_user_thread_lib="$withval"
fi
],
[want_boost="yes"]
)
if test "x$want_boost" = "xyes"; then
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_BUILD])
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_CACHE_CHECK(whether the Boost::Thread library is available,
ax_cv_boost_thread,
[AC_LANG_PUSH([C++])
CXXFLAGS_SAVE=$CXXFLAGS
if test "x$host_os" = "xsolaris" ; then
CXXFLAGS="-pthreads $CXXFLAGS"
elif test "x$host_os" = "xmingw32" ; then
CXXFLAGS="-mthreads $CXXFLAGS"
else
CXXFLAGS="-pthread $CXXFLAGS"
fi
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/thread/thread.hpp>]],
[[boost::thread_group thrds;
return 0;]])],
ax_cv_boost_thread=yes, ax_cv_boost_thread=no)
CXXFLAGS=$CXXFLAGS_SAVE
AC_LANG_POP([C++])
])
if test "x$ax_cv_boost_thread" = "xyes"; then
if test "x$host_os" = "xsolaris" ; then
BOOST_CPPFLAGS="-pthreads $BOOST_CPPFLAGS"
elif test "x$host_os" = "xmingw32" ; then
BOOST_CPPFLAGS="-mthreads $BOOST_CPPFLAGS"
else
BOOST_CPPFLAGS="-pthread $BOOST_CPPFLAGS"
fi
AC_SUBST(BOOST_CPPFLAGS)
AC_DEFINE(HAVE_BOOST_THREAD,,[define if the Boost::Thread library is available])
BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
LDFLAGS_SAVE=$LDFLAGS
case "x$host_os" in
*bsd* )
LDFLAGS="-pthread $LDFLAGS"
break;
;;
esac
if test "x$ax_boost_user_thread_lib" = "x"; then
ax_lib=
for libextension in `ls -r $BOOSTLIBDIR/libboost_thread* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'`; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break],
[link_thread="no"])
done
if test "x$link_thread" != "xyes"; then
for libextension in `ls -r $BOOSTLIBDIR/boost_thread* 2>/dev/null | sed 's,.*/,,' | sed 's,\..*,,'`; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break],
[link_thread="no"])
done
fi
else
for ax_lib in $ax_boost_user_thread_lib boost_thread-$ax_boost_user_thread_lib; do
AC_CHECK_LIB($ax_lib, exit,
[BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break],
[link_thread="no"])
done
fi
if test "x$ax_lib" = "x"; then
AC_MSG_ERROR(Could not find a version of the boost_thread library!)
fi
if test "x$link_thread" = "xno"; then
AC_MSG_ERROR(Could not link against $ax_lib !)
else
case "x$host_os" in
*bsd* )
BOOST_LDFLAGS="-pthread $BOOST_LDFLAGS"
break;
;;
esac
fi
fi
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
fi
])
12 changes: 12 additions & 0 deletions build_msvc/defi_config.h
Original file line number Diff line number Diff line change
@@ -43,6 +43,9 @@
/* define if the Boost library is available */
#define HAVE_BOOST /**/

/* define if the Boost::Chrono library is available */
#define HAVE_BOOST_CHRONO /**/

/* define if the Boost::Filesystem library is available */
#define HAVE_BOOST_FILESYSTEM /**/

@@ -52,6 +55,9 @@
/* define if the Boost::System library is available */
#define HAVE_BOOST_SYSTEM /**/

/* define if the Boost::Thread library is available */
#define HAVE_BOOST_THREAD /**/

/* define if the Boost::Unit_Test_Framework library is available */
#define HAVE_BOOST_UNIT_TEST_FRAMEWORK /**/

@@ -324,6 +330,12 @@
/* Define if the visibility attribute is supported. */
#define HAVE_VISIBILITY_ATTRIBUTE 1

/* Define this symbol if boost sleep works */
/* #undef HAVE_WORKING_BOOST_SLEEP */

/* Define this symbol if boost sleep_for works */
#define HAVE_WORKING_BOOST_SLEEP_FOR 1

/* Define to the sub-directory where libtool stores uninstalled libraries. */
#define LT_OBJDIR ".libs/"

2 changes: 1 addition & 1 deletion ci/test/00_setup_env_amd64_asan.sh
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
export LC_ALL=C.UTF-8

export HOST=x86_64-unknown-linux-gnu
export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libssl1.0-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-test-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev"
export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libssl1.0-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev"
export NO_DEPENDS=1
export GOAL="install"
export DEFI_CONFIG="--enable-zmq --with-incompatible-bdb CPPFLAGS=-DDEBUG_LOCKORDER --with-sanitizers=address,integer,undefined CC=clang CXX=clang++"
2 changes: 1 addition & 1 deletion ci/test/00_setup_env_amd64_fuzz.sh
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
export LC_ALL=C.UTF-8

export HOST=x86_64-unknown-linux-gnu
export PACKAGES="clang llvm python3 libssl1.0-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-test-dev"
export PACKAGES="clang llvm python3 libssl1.0-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev"
export NO_DEPENDS=1
export RUN_UNIT_TESTS=false
export RUN_FUNCTIONAL_TESTS=false
2 changes: 1 addition & 1 deletion ci/test/00_setup_env_amd64_trusty.sh
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8

export HOST=x86_64-unknown-linux-gnu
export DOCKER_NAME_TAG=ubuntu:14.04
export PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libicu-dev libpng-dev libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-test-dev libdb5.1++-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev"
export PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libicu-dev libpng-dev libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.1++-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev"
export NO_DEPENDS=1
export RUN_FUNCTIONAL_TESTS=false
export GOAL="install"
2 changes: 1 addition & 1 deletion ci/test/00_setup_env_amd64_tsan.sh
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ export LC_ALL=C.UTF-8

export HOST=x86_64-unknown-linux-gnu
export DOCKER_NAME_TAG=ubuntu:16.04
export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-test-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev"
export PACKAGES="clang llvm python3-zmq qtbase5-dev qttools5-dev-tools libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev"
export NO_DEPENDS=1
export GOAL="install"
export DEFI_CONFIG="--enable-zmq --disable-wallet CPPFLAGS=-DDEBUG_LOCKORDER --with-sanitizers=thread --disable-hardening --disable-asm CC=clang CXX=clang++"
59 changes: 56 additions & 3 deletions configure.ac
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
AC_PREREQ([2.60])
define(_CLIENT_VERSION_MAJOR, 2)
define(_CLIENT_VERSION_MINOR, 9)
define(_CLIENT_VERSION_MINOR, 8)
define(_CLIENT_VERSION_REVISION, 1)
define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_RC, 0)
@@ -519,7 +519,7 @@ case $host in
AC_MSG_ERROR("windres not found")
fi

CPPFLAGS="$CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -D_WIN32_WINNT=0x0601"
CPPFLAGS="$CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -D_WIN32_WINNT=0x0601"
LEVELDB_TARGET_FLAGS="-DOS_WINDOWS"
if test "x$CXXFLAGS_overridden" = "xno"; then
CXXFLAGS="$CXXFLAGS -w"
@@ -1083,6 +1083,8 @@ if test x$want_boost = xno; then
fi
AX_BOOST_SYSTEM
AX_BOOST_FILESYSTEM
AX_BOOST_THREAD
AX_BOOST_CHRONO

dnl Boost 1.56 through 1.62 allow using std::atomic instead of its own atomic
dnl counter implementations. In 1.63 and later the std::atomic approach is default.
@@ -1149,7 +1151,7 @@ fi

if test x$use_boost = xyes; then

BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB"
BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_THREAD_LIB $BOOST_CHRONO_LIB"


dnl If boost (prior to 1.57) was built without c++11, it emulated scoped enums
@@ -1187,6 +1189,57 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
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
dnl a working version is available, else fall back to sleep. sleep was removed
dnl after 1.56.
dnl If neither is available, abort.
TEMP_LIBS="$LIBS"
LIBS="$BOOST_LIBS $LIBS"
TEMP_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <boost/thread/thread.hpp>
#include <boost/version.hpp>
]],[[
#if BOOST_VERSION >= 105000 && (!defined(BOOST_HAS_NANOSLEEP) || BOOST_VERSION >= 105200)
boost::this_thread::sleep_for(boost::chrono::milliseconds(0));
#else
choke me
#endif
]])],
[boost_sleep=yes;
AC_DEFINE(HAVE_WORKING_BOOST_SLEEP_FOR, 1, [Define this symbol if boost sleep_for works])],
[boost_sleep=no])
LIBS="$TEMP_LIBS"
CPPFLAGS="$TEMP_CPPFLAGS"

if test x$boost_sleep != xyes; then
TEMP_LIBS="$LIBS"
LIBS="$BOOST_LIBS $LIBS"
TEMP_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <boost/version.hpp>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
]],[[
#if BOOST_VERSION <= 105600
boost::this_thread::sleep(boost::posix_time::milliseconds(0));
#else
choke me
#endif
]])],
[boost_sleep=yes; AC_DEFINE(HAVE_WORKING_BOOST_SLEEP, 1, [Define this symbol if boost sleep works])],
[boost_sleep=no])
LIBS="$TEMP_LIBS"
CPPFLAGS="$TEMP_CPPFLAGS"
fi

if test x$boost_sleep != xyes; then
AC_MSG_ERROR(No working boost sleep implementation found.)
fi

fi

if test x$use_pkgconfig = xyes; then
2 changes: 1 addition & 1 deletion depends/packages/boost.mk
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ $(package)_toolset_$(host_os)=gcc
$(package)_archiver_$(host_os)=$($(package)_ar)
$(package)_toolset_darwin=darwin
$(package)_archiver_darwin=$($(package)_libtool)
$(package)_config_libraries=filesystem,system,test
$(package)_config_libraries=chrono,filesystem,system,thread,test
$(package)_cxxflags=-std=c++17 -fvisibility=hidden
$(package)_cxxflags_linux=-fPIC
endef
2 changes: 1 addition & 1 deletion doc/build-unix.md
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@ Build requirements:

Now, you can either build from self-compiled [depends](/depends/README.md) or install the required dependencies:

sudo apt-get install libssl-dev libevent-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev
sudo apt-get install libssl-dev libevent-dev libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev

BerkeleyDB is required for the wallet.

3 changes: 1 addition & 2 deletions src/addrman.cpp
Original file line number Diff line number Diff line change
@@ -5,7 +5,6 @@

#include <addrman.h>

#include <cmath>
#include <hash.h>
#include <serialize.h>

@@ -60,7 +59,7 @@ double CAddrInfo::GetChance(int64_t nNow) const
fChance *= 0.01;

// deprioritize 66% after each failed attempt, but at most 1/28th to avoid the search taking forever or overly penalizing outages.
fChance *= std::pow(0.66, std::min(nAttempts, 8));
fChance *= pow(0.66, std::min(nAttempts, 8));

return fChance;
}
11 changes: 8 additions & 3 deletions src/bench/checkqueue.cpp
Original file line number Diff line number Diff line change
@@ -6,9 +6,10 @@
#include <util/system.h>
#include <checkqueue.h>
#include <prevector.h>
#include <vector>
#include <boost/thread/thread.hpp>
#include <random.h>

#include <vector>

static const int MIN_CORES = 2;
static const size_t BATCHES = 101;
@@ -35,7 +36,10 @@ static void CCheckQueueSpeedPrevectorJob(benchmark::State& state)
void swap(PrevectorJob& x){p.swap(x.p);};
};
CCheckQueue<PrevectorJob> queue {QUEUE_BATCH_SIZE};
queue.StartWorkerThreads(GetNumCores() - 1);
boost::thread_group tg;
for (auto x = 0; x < std::max(MIN_CORES, GetNumCores()); ++x) {
tg.create_thread([&]{queue.Thread();});
}
while (state.KeepRunning()) {
// Make insecure_rand here so that each iteration is identical.
FastRandomContext insecure_rand(true);
@@ -51,6 +55,7 @@ static void CCheckQueueSpeedPrevectorJob(benchmark::State& state)
// it is done explicitly here for clarity
control.Wait();
}
queue.StopWorkerThreads();
tg.interrupt_all();
tg.join_all();
}
BENCHMARK(CCheckQueueSpeedPrevectorJob, 1400);
2 changes: 1 addition & 1 deletion src/bench/examples.cpp
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
static void Sleep100ms(benchmark::State& state)
{
while (state.KeepRunning()) {
UninterruptibleSleep(std::chrono::milliseconds{100});
MilliSleep(100);
}
}

20 changes: 7 additions & 13 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
@@ -15,11 +15,11 @@
#include <util/strencodings.h>
#include <versionbitsinfo.h>

#include <algorithm>
#include <cassert>

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/case_conv.hpp>

bool fMockNetwork = false;

@@ -135,7 +135,7 @@ class CMainParams : public CChainParams {
consensus.FortCanningHillHeight = 1604999; // Feb 7, 2022.
consensus.FortCanningRoadHeight = 1786000; // April 11, 2022.
consensus.FortCanningCrunchHeight = 1936000; // June 2, 2022.
consensus.FortCanningSpringHeight = 2033000; // July 6, 2022.
consensus.FortCanningGardensHeight = std::numeric_limits<int>::max();
consensus.GreatWorldHeight = std::numeric_limits<int>::max();

consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
@@ -253,7 +253,6 @@ class CMainParams : public CChainParams {
consensus.smartContracts.clear();
consensus.smartContracts[SMART_CONTRACT_DFIP_2201] = GetScriptForDestination(CTxDestination(WitnessV0KeyHash(std::vector<unsigned char>{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})));
consensus.smartContracts[SMART_CONTRACT_DFIP_2203] = GetScriptForDestination(CTxDestination(WitnessV0KeyHash(std::vector<unsigned char>{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1})));
consensus.smartContracts[SMART_CONTRACT_DFIP2206F] = GetScriptForDestination(CTxDestination(WitnessV0KeyHash(std::vector<unsigned char>{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2})));

// owner base58, operator base58
vMasternodes.push_back({"8PuErAcazqccCVzRcc8vJ3wFaZGm4vFbLe", "8J846CKFF83Jcj5m4EReJmxiaJ6Jy1Y6Ea"});
@@ -317,9 +316,7 @@ class CMainParams : public CChainParams {
{597925, uint256S("0ff2aa3749300e3d0b5bc8d48f9d699bc42e222fe718dc011b33913127087c6d")},
{600000, uint256S("79ddf4537e40cb59335a0551e5edc7bd396e6949aa2864c3200ca66f9c455405")},
{650000, uint256S("f18d64dd75c53590e833d3068132a65644963d5c5aebb4c73d42cbde8dc28d68")},
{700000, uint256S("0d0f779d7f43cc3fd9f01e71e136f7e9319d73791f8839720ab495327075e272")},
{757420, uint256S("8d4918be2b2df30175f9e611d9ceb494215b93f2267075ace3f031e784cbccbe")},
{800000, uint256S("8d9ade23a54f16a0a5a6ce5d14788f93bfd7e703be8a3a07a85c935b47511f95")},
{850000, uint256S("2d7d58ae18a74f73b9836a8fffd3f65ce409536e654a6c644ce735215238a004")},
{875000, uint256S("44d3b3ba8e920cef86b7ec096ab0a2e608d9fedc14a59611a76a5e40aa53145e")},
{895741, uint256S("61bc1d73c720990dde43a3fec1f703a222ec5c265e6d491efd60eeec1bdb6dc3")},
@@ -373,7 +370,7 @@ class CTestNetParams : public CChainParams {
consensus.FortCanningHillHeight = 828900;
consensus.FortCanningRoadHeight = 893700;
consensus.FortCanningCrunchHeight = 1011600;
consensus.FortCanningSpringHeight = 1086000;
consensus.FortCanningGardensHeight = std::numeric_limits<int>::max();
consensus.GreatWorldHeight = std::numeric_limits<int>::max();

consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
@@ -481,7 +478,6 @@ class CTestNetParams : public CChainParams {
consensus.smartContracts.clear();
consensus.smartContracts[SMART_CONTRACT_DFIP_2201] = GetScriptForDestination(CTxDestination(WitnessV0KeyHash(std::vector<unsigned char>{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})));
consensus.smartContracts[SMART_CONTRACT_DFIP_2203] = GetScriptForDestination(CTxDestination(WitnessV0KeyHash(std::vector<unsigned char>{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1})));
consensus.smartContracts[SMART_CONTRACT_DFIP2206F] = GetScriptForDestination(CTxDestination(WitnessV0KeyHash(std::vector<unsigned char>{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2})));

// owner base58, operator base58
vMasternodes.push_back({"7LMorkhKTDjbES6DfRxX2RiNMbeemUkxmp", "7KEu9JMKCx6aJ9wyg138W3p42rjg19DR5D"});
@@ -566,7 +562,7 @@ class CDevNetParams : public CChainParams {
consensus.FortCanningHillHeight = std::numeric_limits<int>::max();
consensus.FortCanningRoadHeight = std::numeric_limits<int>::max();
consensus.FortCanningCrunchHeight = std::numeric_limits<int>::max();
consensus.FortCanningSpringHeight = std::numeric_limits<int>::max();
consensus.FortCanningGardensHeight = std::numeric_limits<int>::max();
consensus.GreatWorldHeight = std::numeric_limits<int>::max();

consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
@@ -668,7 +664,6 @@ class CDevNetParams : public CChainParams {
consensus.smartContracts.clear();
consensus.smartContracts[SMART_CONTRACT_DFIP_2201] = GetScriptForDestination(CTxDestination(WitnessV0KeyHash(std::vector<unsigned char>{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})));
consensus.smartContracts[SMART_CONTRACT_DFIP_2203] = GetScriptForDestination(CTxDestination(WitnessV0KeyHash(std::vector<unsigned char>{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1})));
consensus.smartContracts[SMART_CONTRACT_DFIP2206F] = GetScriptForDestination(CTxDestination(WitnessV0KeyHash(std::vector<unsigned char>{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2})));

// owner base58, operator base58
vMasternodes.push_back({"7M3g9CSERjLdXisE5pv2qryDbURUj9Vpi1", "7Grgx69MZJ4wDKRx1bBxLqTnU9T3quKW7n"});
@@ -751,7 +746,7 @@ class CRegTestParams : public CChainParams {
consensus.FortCanningHillHeight = 10000000;
consensus.FortCanningRoadHeight = 10000000;
consensus.FortCanningCrunchHeight = 10000000;
consensus.FortCanningSpringHeight = 10000000;
consensus.FortCanningGardensHeight = 10000000;
consensus.GreatWorldHeight = 10000000;

consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
@@ -861,7 +856,6 @@ class CRegTestParams : public CChainParams {
consensus.smartContracts.clear();
consensus.smartContracts[SMART_CONTRACT_DFIP_2201] = GetScriptForDestination(CTxDestination(WitnessV0KeyHash(std::vector<unsigned char>{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})));
consensus.smartContracts[SMART_CONTRACT_DFIP_2203] = GetScriptForDestination(CTxDestination(WitnessV0KeyHash(std::vector<unsigned char>{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1})));
consensus.smartContracts[SMART_CONTRACT_DFIP2206F] = GetScriptForDestination(CTxDestination(WitnessV0KeyHash(std::vector<unsigned char>{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2})));

// owner base58, operator base58
vMasternodes.push_back({"mwsZw8nF7pKxWH8eoKL9tPxTpaFkz7QeLU", "mswsMVsyGMj1FzDMbbxw2QW3KvQAv2FKiy"});
@@ -941,7 +935,7 @@ std::optional<int> UpdateHeightValidation(const std::string& argName, const std:
if (gArgs.IsArgSet(argFlag)) {
int64_t height = gArgs.GetArg(argFlag, argTarget);
if (height < -1 || height >= std::numeric_limits<int>::max()) {
std::string lowerArgName = ToLower(argFlag);
auto lowerArgName = boost::to_lower_copy(argName);
throw std::runtime_error(strprintf(
"Activation height %ld for %s is out of valid range. Use -1 to disable %s.",
height, argName, lowerArgName));
@@ -974,7 +968,7 @@ void SetupCommonArgActivationParams(Consensus::Params &consensus) {
UpdateHeightValidation("Fort Canning Hill", "-fortcanninghillheight", consensus.FortCanningHillHeight);
UpdateHeightValidation("Fort Canning Road", "-fortcanningroadheight", consensus.FortCanningRoadHeight);
UpdateHeightValidation("Fort Canning Crunch", "-fortcanningcrunchheight", consensus.FortCanningCrunchHeight);
UpdateHeightValidation("Fort Canning Spring", "-fortcanningspringheight", consensus.FortCanningSpringHeight);
UpdateHeightValidation("Fort Canning Gardens", "-fortcanninggardensheight", consensus.FortCanningGardensHeight);
UpdateHeightValidation("Great World", "-greatworldheight", consensus.GreatWorldHeight);

if (gArgs.GetBoolArg("-simulatemainnet", false)) {
1 change: 0 additions & 1 deletion src/chainparams.h
Original file line number Diff line number Diff line change
@@ -128,7 +128,6 @@ class CChainParams

const auto SMART_CONTRACT_DFIP_2201 = "DFIP2201";
const auto SMART_CONTRACT_DFIP_2203 = "DFIP2203";
const auto SMART_CONTRACT_DFIP2206F = "DFIP2206F";

/**
* Creates and returns a std::unique_ptr<CChainParams> of the chosen chain.
88 changes: 29 additions & 59 deletions src/checkqueue.h
Original file line number Diff line number Diff line change
@@ -6,12 +6,13 @@
#define DEFI_CHECKQUEUE_H

#include <sync.h>
#include <tinyformat.h>
#include <util/threadnames.h>

#include <algorithm>
#include <vector>

#include <boost/thread/condition_variable.hpp>
#include <boost/thread/mutex.hpp>

template <typename T>
class CCheckQueueControl;

@@ -30,80 +31,74 @@ class CCheckQueue
{
private:
//! Mutex to protect the inner state
Mutex m_mutex;
boost::mutex mutex;

//! Worker threads block on this when out of work
std::condition_variable m_worker_cv;
boost::condition_variable condWorker;

//! Master thread blocks on this when out of work
std::condition_variable m_master_cv;
boost::condition_variable condMaster;

//! The queue of elements to be processed.
//! As the order of booleans doesn't matter, it is used as a LIFO (stack)
std::vector<T> queue GUARDED_BY(m_mutex);
std::vector<T> queue;

//! The number of workers (including the master) that are idle.
int nIdle GUARDED_BY(m_mutex){0};
int nIdle;

//! The total number of workers (including the master).
int nTotal GUARDED_BY(m_mutex){0};
int nTotal;

//! The temporary evaluation result.
bool fAllOk GUARDED_BY(m_mutex){true};
bool fAllOk;

/**
* Number of verifications that haven't completed yet.
* This includes elements that are no longer queued, but still in the
* worker's own batches.
*/
unsigned int nTodo GUARDED_BY(m_mutex){0};
unsigned int nTodo;

//! The maximum number of elements to be processed in one batch
const unsigned int nBatchSize;

std::vector<std::thread> m_worker_threads;
bool m_request_stop GUARDED_BY(m_mutex){false};
unsigned int nBatchSize;

/** Internal function that does bulk of the verification work. */
bool Loop(bool fMaster)
bool Loop(bool fMaster = false)
{
std::condition_variable& cond = fMaster ? m_master_cv : m_worker_cv;
boost::condition_variable& cond = fMaster ? condMaster : condWorker;
std::vector<T> vChecks;
vChecks.reserve(nBatchSize);
unsigned int nNow = 0;
bool fOk = true;
do {
{
WAIT_LOCK(m_mutex, lock);
boost::unique_lock<boost::mutex> lock(mutex);
// first do the clean-up of the previous loop run (allowing us to do it in the same critsect)
if (nNow) {
fAllOk &= fOk;
nTodo -= nNow;
if (nTodo == 0 && !fMaster)
// We processed the last element; inform the master it can exit and return the result
m_master_cv.notify_one();
condMaster.notify_one();
} else {
// first iteration
nTotal++;
}
// logically, the do loop starts here
while (queue.empty() && !m_request_stop) {
while (queue.empty()) {
if (fMaster && nTodo == 0) {
nTotal--;
bool fRet = fAllOk;
// reset the status for new work later
fAllOk = true;
if (fMaster)
fAllOk = true;
// return the current status
return fRet;
}
nIdle++;
cond.wait(lock); // wait
nIdle--;
}
if (m_request_stop) {
return false;
}

// Decide how many work units to process now.
// * Do not try to do everything at once, but aim for increasingly smaller batches so
// all workers finish approximately simultaneously.
@@ -130,27 +125,15 @@ class CCheckQueue

public:
//! Mutex to ensure only one concurrent CCheckQueueControl
Mutex m_control_mutex;
boost::mutex ControlMutex;

//! Create a new check queue
explicit CCheckQueue(unsigned int nBatchSizeIn) : nBatchSize(nBatchSizeIn) {}
explicit CCheckQueue(unsigned int nBatchSizeIn) : nIdle(0), nTotal(0), fAllOk(true), nTodo(0), nBatchSize(nBatchSizeIn) {}

//! Create a pool of new worker threads.
void StartWorkerThreads(const int threads_num)
//! Worker thread
void Thread()
{
{
LOCK(m_mutex);
nIdle = 0;
nTotal = 0;
fAllOk = true;
}
assert(m_worker_threads.empty());
for (int n = 0; n < threads_num; ++n) {
m_worker_threads.emplace_back([this, n]() {
util::ThreadRename(strprintf("scriptch.%i", n));
Loop(false /* worker thread */);
});
}
Loop();
}

//! Wait until execution finishes, and return whether all evaluations were successful.
@@ -162,33 +145,20 @@ class CCheckQueue
//! Add a batch of checks to the queue
void Add(std::vector<T>& vChecks)
{
LOCK(m_mutex);
boost::unique_lock<boost::mutex> lock(mutex);
for (T& check : vChecks) {
queue.push_back(T());
check.swap(queue.back());
}
nTodo += vChecks.size();
if (vChecks.size() == 1)
m_worker_cv.notify_one();
condWorker.notify_one();
else if (vChecks.size() > 1)
m_worker_cv.notify_all();
}

//! Stop all of the worker threads.
void StopWorkerThreads()
{
WITH_LOCK(m_mutex, m_request_stop = true);
m_worker_cv.notify_all();
for (std::thread& t : m_worker_threads) {
t.join();
}
m_worker_threads.clear();
WITH_LOCK(m_mutex, m_request_stop = false);
condWorker.notify_all();
}

~CCheckQueue()
{
assert(m_worker_threads.empty());
}

};
@@ -212,7 +182,7 @@ class CCheckQueueControl
{
// passed queue is supposed to be unused, or nullptr
if (pqueue != nullptr) {
ENTER_CRITICAL_SECTION(pqueue->m_control_mutex);
ENTER_CRITICAL_SECTION(pqueue->ControlMutex);
}
}

@@ -236,7 +206,7 @@ class CCheckQueueControl
if (!fDone)
Wait();
if (pqueue != nullptr) {
LEAVE_CRITICAL_SECTION(pqueue->m_control_mutex);
LEAVE_CRITICAL_SECTION(pqueue->ControlMutex);
}
}
};
2 changes: 1 addition & 1 deletion src/consensus/params.h
Original file line number Diff line number Diff line change
@@ -96,7 +96,7 @@ struct Params {
int FortCanningHillHeight;
int FortCanningRoadHeight;
int FortCanningCrunchHeight;
int FortCanningSpringHeight;
int FortCanningGardensHeight;
int GreatWorldHeight;

/** Foundation share after AMK, normalized to COIN = 100% */
31 changes: 8 additions & 23 deletions src/consensus/tx_check.cpp
Original file line number Diff line number Diff line change
@@ -4,7 +4,6 @@

#include <consensus/tx_check.h>

#include <clientversion.h>
#include <primitives/transaction.h>
#include <consensus/validation.h>

@@ -69,8 +68,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fChe
bool ParseScriptByMarker(CScript const & script,
const std::vector<unsigned char> & marker,
std::vector<unsigned char> & metadata,
uint8_t& hasAdditionalOpcodes,
CExpirationAndVersion* customTxParams)
bool& hasAdditionalOpcodes)
{
opcodetype opcode;
auto pc = script.begin();
@@ -85,20 +83,8 @@ bool ParseScriptByMarker(CScript const & script,
}

// Check that no more opcodes are found in the script
std::vector<unsigned char> expirationAndVersion;
if (script.GetOp(pc, opcode, expirationAndVersion)) {
hasAdditionalOpcodes |= HasForks::FortCanning;
if (expirationAndVersion.size() == sizeof(uint32_t) + sizeof(uint8_t)) {
if (customTxParams) {
VectorReader stream(SER_DISK, CLIENT_VERSION, expirationAndVersion, 0);
stream >> *customTxParams;
}
} else {
hasAdditionalOpcodes |= HasForks::GreatWorld;
}
if (pc != script.end()) {
hasAdditionalOpcodes |= HasForks::GreatWorld;
}
if (script.GetOp(pc, opcode)) {
hasAdditionalOpcodes = true;
}

metadata.erase(metadata.begin(), metadata.begin() + marker.size());
@@ -110,23 +96,22 @@ bool IsAnchorRewardTx(CTransaction const & tx, std::vector<unsigned char> & meta
if (!tx.IsCoinBase() || tx.vout.size() != 2 || tx.vout[0].nValue != 0) {
return false;
}
uint8_t hasAdditionalOpcodes{HasForks::None};
bool hasAdditionalOpcodes{false};
const auto result = ParseScriptByMarker(tx.vout[0].scriptPubKey, DfAnchorFinalizeTxMarker, metadata, hasAdditionalOpcodes);
if (fortCanning && hasAdditionalOpcodes) {
return false;
}
return result;
}

bool IsAnchorRewardTxPlus(CTransaction const & tx, std::vector<unsigned char> & metadata, uint8_t hasForks)
bool IsAnchorRewardTxPlus(CTransaction const & tx, std::vector<unsigned char> & metadata, bool fortCanning)
{
if (!tx.IsCoinBase() || tx.vout.size() != 2 || tx.vout[0].nValue != 0) {
return false;
}
uint8_t hasAdditionalOpcodes{HasForks::None};
bool hasAdditionalOpcodes{false};
const auto result = ParseScriptByMarker(tx.vout[0].scriptPubKey, DfAnchorFinalizeTxMarkerPlus, metadata, hasAdditionalOpcodes);
if ((hasForks & HasForks::FortCanning && !(hasForks & HasForks::GreatWorld) && hasAdditionalOpcodes & HasForks::FortCanning) ||
(hasForks & HasForks::GreatWorld && hasAdditionalOpcodes & HasForks::GreatWorld)) {
if (fortCanning && hasAdditionalOpcodes) {
return false;
}
return result;
@@ -140,7 +125,7 @@ bool IsTokenSplitTx(CTransaction const & tx, std::vector<unsigned char> & metada
if (!tx.IsCoinBase() || tx.vout.size() != 1 || tx.vout[0].nValue != 0) {
return false;
}
uint8_t hasAdditionalOpcodes{HasForks::None};
bool hasAdditionalOpcodes{false};
const auto result = ParseScriptByMarker(tx.vout[0].scriptPubKey, DfTokenSplitMarker, metadata, hasAdditionalOpcodes);
if (hasAdditionalOpcodes) {
return false;
13 changes: 2 additions & 11 deletions src/consensus/tx_check.h
Original file line number Diff line number Diff line change
@@ -12,34 +12,25 @@
* belongs in tx_verify.h/cpp instead.
*/

#include <cstdint>
#include <vector>

extern const std::vector<unsigned char> DfTxMarker;
extern const std::vector<unsigned char> DfAnchorFinalizeTxMarker;
extern const std::vector<unsigned char> DfAnchorFinalizeTxMarkerPlus;
extern const std::vector<unsigned char> DfTokenSplitMarker;

struct CExpirationAndVersion;
class CScript;
class CTransaction;
class CValidationState;

enum HasForks : uint8_t {
None = 0,
FortCanning = 1 << 0,
GreatWorld = 1 << 1,
};

bool CheckTransaction(const CTransaction& tx, CValidationState& state, bool fCheckDuplicateInputs=true);

bool ParseScriptByMarker(CScript const & script,
const std::vector<unsigned char> & marker,
std::vector<unsigned char> & metadata,
uint8_t& hasAdditionalOpcodes,
CExpirationAndVersion* customTxParams = nullptr);
bool& hasAdditionalOpcodes);
bool IsAnchorRewardTx(CTransaction const & tx, std::vector<unsigned char> & metadata, bool fortCanning = false);
bool IsAnchorRewardTxPlus(CTransaction const & tx, std::vector<unsigned char> & metadata, uint8_t hasForks = HasForks::None);
bool IsAnchorRewardTxPlus(CTransaction const & tx, std::vector<unsigned char> & metadata, bool fortCanning = false);
bool IsTokenSplitTx(CTransaction const & tx, std::vector<unsigned char> & metadata, bool fortCanningCrunch = true);

#endif // DEFI_CONSENSUS_TX_CHECK_H
30 changes: 15 additions & 15 deletions src/consensus/tx_verify.cpp
Original file line number Diff line number Diff line change
@@ -161,27 +161,14 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i
return nSigOps;
}

bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, CCustomCSView& mnview, int nSpendHeight, CAmount& txfee, const CChainParams& chainparams)
bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, const CCustomCSView * mnview, int nSpendHeight, CAmount& txfee, const CChainParams& chainparams)
{
// are the actual inputs available?
if (!inputs.HaveInputs(tx)) {
return state.Invalid(ValidationInvalidReason::TX_MISSING_INPUTS, false, REJECT_INVALID, "bad-txns-inputs-missingorspent",
strprintf("%s: inputs missing/spent", __func__));
}

// check for tokens values
uint256 canSpend;
std::vector<unsigned char> dummy;
const auto txType = GuessCustomTxType(tx, dummy);

if (NotAllowedToFail(txType, nSpendHeight) || (nSpendHeight >= chainparams.GetConsensus().GreatWorldHeight && txType == CustomTxType::UpdateMasternode)) {
CCustomCSView discardCache(mnview);
auto res = ApplyCustomTx(discardCache, inputs, tx, chainparams.GetConsensus(), nSpendHeight, 0, &canSpend);
if (!res.ok && (res.code & CustomTxErrCodes::Fatal)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-customtx", res.msg);
}
}

TAmounts nValuesIn;
for (unsigned int i = 0; i < tx.vin.size(); ++i) {
const COutPoint &prevout = tx.vin[i].prevout;
@@ -200,7 +187,8 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange");
}
/// @todo tokens: later match the range with TotalSupply
if (canSpend != prevout.hash && prevout.n == 1 && !mnview.CanSpend(prevout.hash, nSpendHeight)) {

if (prevout.n == 1 && !mnview->CanSpend(prevout.hash, nSpendHeight)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-collateral-locked",
strprintf("tried to spend locked collateral for %s", prevout.hash.ToString())); /// @todo may be somehow place the height of unlocking?
}
@@ -227,6 +215,18 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-tokens-in-old-version-tx");
}

// check for tokens values
std::vector<unsigned char> dummy;
const auto txType = GuessCustomTxType(tx, dummy);

if (NotAllowedToFail(txType, nSpendHeight)) {
CCustomCSView discardCache(const_cast<CCustomCSView&>(*mnview));
auto res = ApplyCustomTx(discardCache, inputs, tx, chainparams.GetConsensus(), nSpendHeight);
if (!res.ok && (res.code & CustomTxErrCodes::Fatal)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, REJECT_INVALID, "bad-txns-customtx", res.msg);
}
}

for (auto const & kv : non_minted_values_out) {
DCT_ID const & tokenId = kv.first;

2 changes: 1 addition & 1 deletion src/consensus/tx_verify.h
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ namespace Consensus {
* @param[out] txfee Set to the transaction fee if successful.
* Preconditions: tx.IsCoinBase() is false.
*/
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, CCustomCSView& mnview, int nSpendHeight, CAmount& txfee, const CChainParams& chainparams);
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, const CCustomCSView * mnview, int nSpendHeight, CAmount& txfee, const CChainParams& chainparams);
} // namespace Consensus

/** Auxiliary functions for transaction validation (ideally should not be exposed) */
2 changes: 1 addition & 1 deletion src/defi-cli.cpp
Original file line number Diff line number Diff line change
@@ -483,7 +483,7 @@ static int CommandLineRPC(int argc, char *argv[])
}
catch (const CConnectionFailed&) {
if (fWait)
UninterruptibleSleep(std::chrono::milliseconds{1000});
MilliSleep(1000);
else
throw;
}
2 changes: 1 addition & 1 deletion src/defid.cpp
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@ static void WaitForShutdown()
{
while (!ShutdownRequested())
{
UninterruptibleSleep(std::chrono::milliseconds{200});
MilliSleep(200);
}
Interrupt();
}
24 changes: 5 additions & 19 deletions src/flushablestorage.h
Original file line number Diff line number Diff line change
@@ -5,15 +5,15 @@
#ifndef DEFI_FLUSHABLESTORAGE_H
#define DEFI_FLUSHABLESTORAGE_H

#include <shutdown.h>

#include <dbwrapper.h>
#include <functional>
#include <map>
#include <memusage.h>

#include <optional>

#include <boost/thread.hpp>

using TBytes = std::vector<unsigned char>;
using MapKV = std::map<TBytes, std::optional<TBytes>>;

@@ -498,13 +498,15 @@ class CStorageView {
template<typename By, typename KeyType, typename ValueType>
void ForEach(std::function<bool(KeyType const &, CLazySerialize<ValueType>)> callback, KeyType const & start = {}) {
for(auto it = LowerBound<By>(start); it.Valid(); it.Next()) {
boost::this_thread::interruption_point();

if (!callback(it.Key(), it.Value())) {
break;
}
}
}

virtual bool Flush() { return DB().Flush(); }
bool Flush() { return DB().Flush(); }
void Discard() { DB().Discard(); }
size_t SizeEstimate() const { return DB().SizeEstimate(); }

@@ -515,20 +517,4 @@ class CStorageView {
std::unique_ptr<CStorageKV> storage;
};

template<typename KeyPrefix, typename KeyType, typename ValueType>
size_t IterateKV(std::function<bool(KeyType, ValueType)> fn, KeyType start, std::unique_ptr<CStorageKVIterator> iter) {
if (!iter) return 0;
auto it = CStorageIteratorWrapper<KeyPrefix, KeyType>{std::move(iter)};
it.Seek(start);
auto i=0;
while (it.Valid()) {
i++;
auto key = it.Key();
ValueType val = it.Value();
if (!fn(key, val)) break;
it.Next();
}
return i;
}

#endif // DEFI_FLUSHABLESTORAGE_H
2 changes: 1 addition & 1 deletion src/httprpc.cpp
Original file line number Diff line number Diff line change
@@ -197,7 +197,7 @@ static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &)
/* Deter brute-forcing
If this results in a DoS the user really
shouldn't have their RPC port exposed. */
UninterruptibleSleep(std::chrono::milliseconds{250});
MilliSleep(250);

req->WriteHeader("WWW-Authenticate", WWW_AUTH_HEADER_DATA);
req->WriteReply(HTTP_UNAUTHORIZED);
3 changes: 3 additions & 0 deletions src/index/txindex.cpp
Original file line number Diff line number Diff line change
@@ -9,6 +9,8 @@
#include <util/translation.h>
#include <validation.h>

#include <boost/thread.hpp>

constexpr char DB_BEST_BLOCK = 'B';
constexpr char DB_TXINDEX = 't';
constexpr char DB_TXINDEX_BLOCK = 'T';
@@ -150,6 +152,7 @@ bool TxIndex::DB::MigrateData(CBlockTreeDB& block_tree_db, const CBlockLocator&
bool interrupted = false;
std::unique_ptr<CDBIterator> cursor(block_tree_db.NewIterator());
for (cursor->Seek(begin_key); cursor->Valid(); cursor->Next()) {
boost::this_thread::interruption_point();
if (ShutdownRequested()) {
interrupted = true;
break;
113 changes: 39 additions & 74 deletions src/init.cpp
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@

#include <init.h>

#include <addrman.h>
#include <amount.h>
#include <banman.h>
#include <blockfilter.h>
@@ -21,11 +22,11 @@
#include <httpserver.h>
#include <index/blockfilterindex.h>
#include <index/txindex.h>
#include <interfaces/chain.h>
#include <key.h>
#include <key_io.h>
#include <masternodes/accountshistory.h>
#include <masternodes/anchors.h>
#include <masternodes/govvariables/attributes.h>
#include <masternodes/masternodes.h>
#include <masternodes/vaulthistory.h>
#include <miner.h>
@@ -73,7 +74,10 @@
#include <sys/stat.h>
#endif

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/thread.hpp>

#if ENABLE_ZMQ
#include <zmq/zmqabstractnotifier.h>
@@ -156,7 +160,7 @@ NODISCARD static bool CreatePidFile()

static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle;

std::vector<std::thread> threadGroup;
static boost::thread_group threadGroup;
static CScheduler scheduler;

#if HAVE_SYSTEM
@@ -231,12 +235,9 @@ void Shutdown(InitInterfaces& interfaces)
StopTorControl();

// After everything has been shut down, but before things get flushed, stop the
// CScheduler/checkqueue threaGroup
scheduler.stop();
for (auto& thread : threadGroup) {
if (thread.joinable()) thread.join();
}
StopScriptCheckWorkerThreads();
// CScheduler/checkqueue threadGroup
threadGroup.interrupt_all();
threadGroup.join_all();

// After the threads that potentially access these pointers have been stopped,
// destruct and reset all to nullptr.
@@ -416,7 +417,6 @@ void SetupServerArgs()
gArgs.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", nDefaultDbBatchSize), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
gArgs.AddArg("-dbcache=<n>", strprintf("Maximum database cache size <n> MiB (%d to %d, default: %d). In addition, unused mempool memory is shared for this cache (see -maxmempool).", nMinDbCache, nMaxDbCache, nDefaultDbCache), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-debuglogfile=<file>", strprintf("Specify location of debug log file. Relative paths will be prefixed by a net-specific datadir location. (-nodebuglogfile to disable; default: %s)", DEFAULT_DEBUGLOGFILE), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-customtxexpiration=<n>", strprintf("Number of blocks ahead of tip locally created transaction will expire (default: %u)", DEFAULT_CUSTOM_TX_EXPIRATION), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-feefilter", strprintf("Tell other nodes to filter invs to us by our mempool min fee (default: %u)", DEFAULT_FEEFILTER), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
gArgs.AddArg("-includeconf=<file>", "Specify additional configuration file, relative to the -datadir path (only useable from configuration file, not command line)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-loadblock=<file>", "Imports blocks from external blk000??.dat file on startup", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
@@ -501,11 +501,10 @@ void SetupServerArgs()
gArgs.AddArg("-fortcanninghillheight", "Fort Canning Hill fork activation height (regtest only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-fortcanningroadheight", "Fort Canning Road fork activation height (regtest only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-fortcanningcrunchheight", "Fort Canning Crunch fork activation height (regtest only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-fortcanningspringheight", "Fort Canning Spring fork activation height (regtest only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-fortcanninggardensheight", "Fort Canning Gardens fork activation height (regtest only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-greatworldheight", "Great World fork activation height (regtest only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-jellyfish_regtest", "Configure the regtest network for jellyfish testing", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
gArgs.AddArg("-simulatemainnet", "Configure the regtest network to mainnet target timespan and spacing ", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
gArgs.AddArg("-dexstats", strprintf("Enable storing live dex data in DB (default: %u)", DEFAULT_DEXSTATS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#ifdef USE_UPNP
#if USE_UPNP
gArgs.AddArg("-upnp", "Use UPnP to map the listening port (default: 1 when listening and no -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
@@ -759,10 +758,6 @@ static void ThreadImport(std::vector<fs::path> vImportFiles)
break; // This error is logged in OpenBlockFile
LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile);
LoadExternalBlockFile(chainparams, file, &pos);
if (ShutdownRequested()) {
LogPrintf("Shutdown requested. Exit %s\n", __func__);
return;
}
nFile++;
}
pblocktree->WriteReindexing(false);
@@ -780,10 +775,6 @@ static void ThreadImport(std::vector<fs::path> vImportFiles)
fs::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old";
LogPrintf("Importing bootstrap.dat...\n");
LoadExternalBlockFile(chainparams, file);
if (ShutdownRequested()) {
LogPrintf("Shutdown requested. Exit %s\n", __func__);
return;
}
RenameOver(pathBootstrap, pathBootstrapOld);
} else {
LogPrintf("Warning: Could not open bootstrap file %s\n", pathBootstrap.string());
@@ -1182,6 +1173,15 @@ bool AppInitParameterInteraction()
incrementalRelayFee = CFeeRate(n);
}

// -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency
nScriptCheckThreads = gArgs.GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS);
if (nScriptCheckThreads <= 0)
nScriptCheckThreads += GetNumCores();
if (nScriptCheckThreads <= 1)
nScriptCheckThreads = 0;
else if (nScriptCheckThreads > MAX_SCRIPTCHECK_THREADS)
nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS;

// block pruning; get the amount of disk space (in MiB) to allot for block & undo files
int64_t nPruneArg = gArgs.GetArg("-prune", 0);
if (nPruneArg < 0) {
@@ -1319,10 +1319,10 @@ bool AppInitLockDataDirectory()
return true;
}

void SetupAnchorSPVDatabases(bool resync, int64_t customCache) {
void SetupAnchorSPVDatabases(bool resync) {
// Close and open database
panchors.reset();
panchors = std::make_unique<CAnchorIndex>(customCache, false, gArgs.GetBoolArg("-spv", true) && resync);
panchors = std::make_unique<CAnchorIndex>(nDefaultDbCache << 20, false, gArgs.GetBoolArg("-spv", true) && resync);

// load anchors after spv due to spv (and spv height) not set before (no last height yet)
if (gArgs.GetBoolArg("-spv", true)) {
@@ -1333,9 +1333,9 @@ void SetupAnchorSPVDatabases(bool resync, int64_t customCache) {
if (Params().NetworkIDString() == "regtest") {
spv::pspv = std::make_unique<spv::CFakeSpvWrapper>();
} else if (Params().NetworkIDString() == "test" || Params().NetworkIDString() == "devnet") {
spv::pspv = std::make_unique<spv::CSpvWrapper>(false, customCache, false, resync);
spv::pspv = std::make_unique<spv::CSpvWrapper>(false, nMinDbCache << 20, false, resync);
} else {
spv::pspv = std::make_unique<spv::CSpvWrapper>(true, customCache, false, resync);
spv::pspv = std::make_unique<spv::CSpvWrapper>(true, nMinDbCache << 20, false, resync);
}
}
}
@@ -1419,27 +1419,15 @@ bool AppInitMain(InitInterfaces& interfaces)
InitSignatureCache();
InitScriptExecutionCache();

int script_threads = gArgs.GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS);
if (script_threads <= 0) {
// -par=0 means autodetect (number of cores - 1 script threads)
// -par=-n means "leave n cores free" (number of cores - n - 1 script threads)
script_threads += GetNumCores();
}

// Subtract 1 because the main thread counts towards the par threads
script_threads = std::max(script_threads - 1, 0);

// Number of script-checking threads <= MAX_SCRIPTCHECK_THREADS
script_threads = std::min(script_threads, MAX_SCRIPTCHECK_THREADS);

LogPrintf("Script verification uses %d additional threads\n", script_threads);
if (script_threads >= 1) {
g_parallel_script_checks = true;
StartScriptCheckWorkerThreads(script_threads);
LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads);
if (nScriptCheckThreads) {
for (int i=0; i<nScriptCheckThreads-1; i++)
threadGroup.create_thread([i]() { return ThreadScriptCheck(i); });
}

// Start the lightweight task scheduler thread
scheduler.m_service_thread = std::thread([&] { TraceThread("scheduler", [&] { scheduler.serviceQueue(); }); });
CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler);
threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));

GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
GetMainSignals().RegisterWithMempoolSignals(mempool);
@@ -1718,7 +1706,6 @@ bool AppInitMain(InitInterfaces& interfaces)
pcustomcsDB = std::make_unique<CStorageLevelDB>(GetDataDir() / "enhancedcs", nCustomCacheSize, false, fReset || fReindexChainState);
pcustomcsview.reset();
pcustomcsview = std::make_unique<CCustomCSView>(*pcustomcsDB.get());

if (!fReset && !fReindexChainState) {
if (!pcustomcsDB->IsEmpty() && pcustomcsview->GetDbVersion() != CCustomCSView::DbVersion) {
strLoadError = _("Account database is unsuitable").translated;
@@ -1729,19 +1716,14 @@ bool AppInitMain(InitInterfaces& interfaces)
// Ensure we are on latest DB version
pcustomcsview->SetDbVersion(CCustomCSView::DbVersion);

// Set custom Tx expiration
pcustomcsview->SetGlobalCustomTxExpiration(gArgs.GetArg("-customtxexpiration", DEFAULT_CUSTOM_TX_EXPIRATION));

// make account history db
paccountHistoryDB.reset();
if (gArgs.GetBoolArg("-acindex", DEFAULT_ACINDEX)) {
paccountHistoryDB = std::make_unique<CAccountHistoryStorage>(GetDataDir() / "history", nCustomCacheSize, false, fReset || fReindexChainState);
paccountHistoryDB->CreateMultiIndexIfNeeded();
}

pburnHistoryDB.reset();
pburnHistoryDB = std::make_unique<CBurnHistoryStorage>(GetDataDir() / "burn", nCustomCacheSize, false, fReset || fReindexChainState);
pburnHistoryDB->CreateMultiIndexIfNeeded();

// Create vault history DB
pvaultHistoryDB.reset();
@@ -1776,24 +1758,6 @@ bool AppInitMain(InitInterfaces& interfaces)
}
assert(::ChainActive().Tip() != nullptr);
}

auto dexStats = gArgs.GetBoolArg("-dexstats", DEFAULT_DEXSTATS);
pcustomcsview->SetDexStatsEnabled(dexStats);

if (!fReset && !fReindexChainState && !pcustomcsDB->IsEmpty() && dexStats) {
// force reindex if there is no dex data at the tip
PoolHeightKey anyPoolSwap{DCT_ID{}, ~0u};
auto it = pcustomcsview->LowerBound<CPoolPairView::ByPoolSwap>(anyPoolSwap);
auto shouldReindex = it.Valid();
auto lastHeight = pcustomcsview->GetDexStatsLastHeight();
if (lastHeight.has_value())
shouldReindex &= !(*lastHeight == ::ChainActive().Tip()->nHeight);

if (shouldReindex) {
strLoadError = _("Live dex needs reindex").translated;
break;
}
}
} catch (const std::exception& e) {
LogPrintf("%s\n", e.what());
strLoadError = _("Error opening block database").translated;
@@ -1907,11 +1871,11 @@ bool AppInitMain(InitInterfaces& interfaces)
panchorauths = std::make_unique<CAnchorAuthIndex>();
panchorAwaitingConfirms.reset();
panchorAwaitingConfirms = std::make_unique<CAnchorAwaitingConfirms>();
SetupAnchorSPVDatabases(gArgs.GetBoolArg("-spv_resync", fReindex || fReindexChainState), nCustomCacheSize);
SetupAnchorSPVDatabases(gArgs.GetBoolArg("-spv_resync", fReindex || fReindexChainState));

// Check if DB version changed
if (spv::pspv && SPV_DB_VERSION != spv::pspv->GetDBVersion()) {
SetupAnchorSPVDatabases(true, nCustomCacheSize);
SetupAnchorSPVDatabases(true);
assert(spv::pspv->SetDBVersion() == SPV_DB_VERSION);
LogPrintf("Cleared anchor and SPV dasebase. SPV DB version set to %d\n", SPV_DB_VERSION);
}
@@ -1981,7 +1945,6 @@ bool AppInitMain(InitInterfaces& interfaces)
});
ConsolidateRewards(*pcustomcsview, ::ChainActive().Height(), balancesToMigrate, true);
}
pcustomcsview->Flush();
}

// ********************************************************* Step 11: import blocks
@@ -2014,7 +1977,7 @@ bool AppInitMain(InitInterfaces& interfaces)
vImportFiles.push_back(strFile);
}

threadGroup.emplace_back(ThreadImport, vImportFiles);
threadGroup.create_thread(std::bind(&ThreadImport, vImportFiles));

// Wait for genesis block to be processed
{
@@ -2221,11 +2184,13 @@ bool AppInitMain(InitInterfaces& interfaces)
}

// Mint proof-of-stake blocks in background
threadGroup.emplace_back(TraceThread<std::function<void()>>, "CoinStaker", [=]() {
// Run ThreadStaker
pos::ThreadStaker threadStaker;
threadStaker(stakersParams, chainparams);
});
threadGroup.create_thread(
std::bind(TraceThread<std::function<void()>>, "CoinStaker", [=]() {
// Run ThreadStaker
pos::ThreadStaker threadStaker;
threadStaker(std::move(stakersParams), std::move(chainparams));
}
));
}

return true;
25 changes: 11 additions & 14 deletions src/masternodes/accounts.cpp
Original file line number Diff line number Diff line change
@@ -122,25 +122,22 @@ Res CAccountsView::EraseFuturesUserValues(const CFuturesUserKey& key)
return Res::Ok();
}

Res CAccountsView::StoreFuturesDUSD(const CFuturesUserKey& key, const CAmount& amount)
std::optional<uint32_t> CAccountsView::GetMostRecentFuturesHeight()
{
if (!WriteBy<ByFuturesDUSDKey>(key, amount)) {
return Res::Err("Failed to store futures");
const CFuturesUserKey key{std::numeric_limits<uint32_t>::max(), {}, std::numeric_limits<uint32_t>::max()};
auto it = LowerBound<ByFuturesSwapKey>(key);
if (it.Valid()) {
return it.Key().height;
}

return Res::Ok();
}

void CAccountsView::ForEachFuturesDUSD(std::function<bool(const CFuturesUserKey&, const CAmount&)> callback, const CFuturesUserKey& start)
{
ForEach<ByFuturesDUSDKey, CFuturesUserKey, CAmount>(callback, start);
return {};
}

Res CAccountsView::EraseFuturesDUSD(const CFuturesUserKey& key)
{
if (!EraseBy<ByFuturesDUSDKey>(key)) {
return Res::Err("Failed to erase futures");
ResVal<CFuturesUserValue> CAccountsView::GetFuturesUserValues(const CFuturesUserKey& key) {
CFuturesUserValue source;
if (!ReadBy<ByFuturesSwapKey>(key, source)) {
return Res::Err("Failed to read futures source");
}

return Res::Ok();
return {source, Res::Ok()};
}
8 changes: 2 additions & 6 deletions src/masternodes/accounts.h
Original file line number Diff line number Diff line change
@@ -70,20 +70,16 @@ class CAccountsView : public virtual CStorageView
Res UpdateBalancesHeight(CScript const & owner, uint32_t height);

Res StoreFuturesUserValues(const CFuturesUserKey& key, const CFuturesUserValue& futures);
ResVal<CFuturesUserValue> GetFuturesUserValues(const CFuturesUserKey& key);
Res EraseFuturesUserValues(const CFuturesUserKey& key);
std::optional<uint32_t> GetMostRecentFuturesHeight();
void ForEachFuturesUserValues(std::function<bool(const CFuturesUserKey&, const CFuturesUserValue&)> callback, const CFuturesUserKey& start =
{std::numeric_limits<uint32_t>::max(), {}, std::numeric_limits<uint32_t>::max()});

Res StoreFuturesDUSD(const CFuturesUserKey& key, const CAmount& amount);
Res EraseFuturesDUSD(const CFuturesUserKey& key);
void ForEachFuturesDUSD(std::function<bool(const CFuturesUserKey&, const CAmount&)> callback, const CFuturesUserKey& start =
{std::numeric_limits<uint32_t>::max(), {}, std::numeric_limits<uint32_t>::max()});

// tags
struct ByBalanceKey { static constexpr uint8_t prefix() { return 'a'; } };
struct ByHeightKey { static constexpr uint8_t prefix() { return 'b'; } };
struct ByFuturesSwapKey { static constexpr uint8_t prefix() { return 'J'; } };
struct ByFuturesDUSDKey { static constexpr uint8_t prefix() { return 'm'; } };

private:
Res SetBalance(CScript const & owner, CTokenAmount amount);
172 changes: 77 additions & 95 deletions src/masternodes/accountshistory.cpp
Original file line number Diff line number Diff line change
@@ -8,112 +8,25 @@
#include <masternodes/vaulthistory.h>
#include <key_io.h>

struct AccountHistoryKeyNew {
uint32_t blockHeight;
CScript owner;
uint32_t txn; // for order in block

ADD_SERIALIZE_METHODS;

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
if (ser_action.ForRead()) {
READWRITE(WrapBigEndian(blockHeight));
blockHeight = ~blockHeight;
} else {
uint32_t blockHeight_ = ~blockHeight;
READWRITE(WrapBigEndian(blockHeight_));
}

READWRITE(owner);

if (ser_action.ForRead()) {
READWRITE(WrapBigEndian(txn));
txn = ~txn;
} else {
uint32_t txn_ = ~txn;
READWRITE(WrapBigEndian(txn_));
}
}
};

static AccountHistoryKeyNew Convert(AccountHistoryKey const & key) {
return {key.blockHeight, key.owner, key.txn};
}

static AccountHistoryKey Convert(AccountHistoryKeyNew const & key) {
return {key.owner, key.blockHeight, key.txn};
}

void CAccountsHistoryView::CreateMultiIndexIfNeeded()
void CAccountsHistoryView::ForEachAccountHistory(std::function<bool(AccountHistoryKey const &, CLazySerialize<AccountHistoryValue>)> callback, AccountHistoryKey const & start)
{
AccountHistoryKeyNew anyNewKey{~0u, {}, ~0u};
if (auto it = LowerBound<ByAccountHistoryKeyNew>(anyNewKey); it.Valid()) {
return;
}

LogPrintf("Adding multi index in progress...\n");

auto startTime = GetTimeMillis();

AccountHistoryKey startKey{{}, ~0u, ~0u};
auto it = LowerBound<ByAccountHistoryKey>(startKey);
for (; it.Valid(); it.Next()) {
WriteBy<ByAccountHistoryKeyNew>(Convert(it.Key()), '\0');
}

Flush();

LogPrint(BCLog::BENCH, " - Multi index took: %dms\n", GetTimeMillis() - startTime);
ForEach<ByAccountHistoryKey, AccountHistoryKey, AccountHistoryValue>(callback, start);
}

void CAccountsHistoryView::ForEachAccountHistory(std::function<bool(AccountHistoryKey const &, AccountHistoryValue)> callback,
const CScript & owner, uint32_t height, uint32_t txn)
Res CAccountsHistoryView::WriteAccountHistory(const AccountHistoryKey& key, const AccountHistoryValue& value)
{
if (!owner.empty()) {
ForEach<ByAccountHistoryKey, AccountHistoryKey, AccountHistoryValue>(callback, {owner, height, txn});
return;
}

ForEach<ByAccountHistoryKeyNew, AccountHistoryKeyNew, char>([&](AccountHistoryKeyNew const & newKey, char) {
auto key = Convert(newKey);
auto value = ReadAccountHistory(key);
assert(value);
return callback(key, *value);
}, {height, owner, txn});
WriteBy<ByAccountHistoryKey>(key, value);
return Res::Ok();
}

std::optional<AccountHistoryValue> CAccountsHistoryView::ReadAccountHistory(AccountHistoryKey const & key) const
{
return ReadBy<ByAccountHistoryKey, AccountHistoryValue>(key);
}

Res CAccountsHistoryView::WriteAccountHistory(const AccountHistoryKey& key, const AccountHistoryValue& value)
{
WriteBy<ByAccountHistoryKey>(key, value);
WriteBy<ByAccountHistoryKeyNew>(Convert(key), '\0');
return Res::Ok();
}

Res CAccountsHistoryView::EraseAccountHistory(const AccountHistoryKey& key)
{
EraseBy<ByAccountHistoryKey>(key);
EraseBy<ByAccountHistoryKeyNew>(Convert(key));
return Res::Ok();
}

Res CAccountsHistoryView::EraseAccountHistoryHeight(uint32_t height)
{
std::vector<AccountHistoryKey> keysToDelete;

auto it = LowerBound<ByAccountHistoryKeyNew>(AccountHistoryKeyNew{height, {}, ~0u});
for (; it.Valid() && it.Key().blockHeight == height; it.Next()) {
keysToDelete.push_back(Convert(it.Key()));
}

for (const auto& key : keysToDelete) {
EraseAccountHistory(key);
}
return Res::Ok();
}

@@ -162,9 +75,78 @@ bool CAccountsHistoryWriter::Flush()
return CCustomCSView::Flush();
}

CAccountHistoryStorage* CAccountsHistoryWriter::GetAccountHistoryStore() {
return writers ? writers->GetAccountHistoryStore() : nullptr;
};
CAccountsHistoryEraser::CAccountsHistoryEraser(CCustomCSView & storage, uint32_t height, uint32_t txn, CHistoryErasers& erasers)
: CStorageView(new CFlushableStorageKV(static_cast<CStorageKV&>(storage.GetStorage()))), height(height), txn(txn), erasers(erasers)
{
}

Res CAccountsHistoryEraser::AddBalance(CScript const & owner, CTokenAmount)
{
erasers.AddBalance(owner, vaultID);
return Res::Ok();
}

Res CAccountsHistoryEraser::SubBalance(CScript const & owner, CTokenAmount)
{
erasers.SubBalance(owner, vaultID);
return Res::Ok();
}

bool CAccountsHistoryEraser::Flush()
{
erasers.Flush(height, txn, vaultID);
return Res::Ok(); // makes sure no changes are applyed to underlaying view
}

CHistoryErasers::CHistoryErasers(CAccountHistoryStorage* historyView, CBurnHistoryStorage* burnView, CVaultHistoryStorage* vaultView)
: historyView(historyView), burnView(burnView), vaultView(vaultView) {}

void CHistoryErasers::AddBalance(const CScript& owner, const uint256& vaultID)
{
if (historyView) {
accounts.insert(owner);
}
if (burnView && owner == Params().GetConsensus().burnAddress) {
burnAccounts.insert(owner);
}
if (vaultView && !vaultID.IsNull()) {
vaults.insert(vaultID);
}
}

void CHistoryErasers::SubFeeBurn(const CScript& owner)
{
if (burnView) {
burnAccounts.insert(owner);
}
}

void CHistoryErasers::SubBalance(const CScript& owner, const uint256& vaultID)
{
if (historyView) {
accounts.insert(owner);
}
if (burnView && owner == Params().GetConsensus().burnAddress) {
burnAccounts.insert(owner);
}
if (vaultView && !vaultID.IsNull()) {
vaults.insert(vaultID);
}
}

void CHistoryErasers::Flush(const uint32_t height, const uint32_t txn, const uint256& vaultID)
{
if (historyView) {
for (const auto& account : accounts) {
historyView->EraseAccountHistory({account, height, txn});
}
}
if (burnView) {
for (const auto& account : burnAccounts) {
burnView->EraseAccountHistory({account, height, txn});
}
}
}

CHistoryWriters::CHistoryWriters(CAccountHistoryStorage* historyView, CBurnHistoryStorage* burnView, CVaultHistoryStorage* vaultView)
: historyView(historyView), burnView(burnView), vaultView(vaultView) {}
58 changes: 42 additions & 16 deletions src/masternodes/accountshistory.h
Original file line number Diff line number Diff line change
@@ -59,24 +59,19 @@ struct AccountHistoryValue {
class CAccountsHistoryView : public virtual CStorageView
{
public:
void CreateMultiIndexIfNeeded();
Res EraseAccountHistoryHeight(uint32_t height);
[[nodiscard]] std::optional<AccountHistoryValue> ReadAccountHistory(AccountHistoryKey const & key) const;
Res WriteAccountHistory(AccountHistoryKey const & key, AccountHistoryValue const & value);
std::optional<AccountHistoryValue> ReadAccountHistory(AccountHistoryKey const & key) const;
Res EraseAccountHistory(AccountHistoryKey const & key);
void ForEachAccountHistory(std::function<bool(AccountHistoryKey const &, AccountHistoryValue)> callback,
const CScript& owner = {}, uint32_t height = std::numeric_limits<uint32_t>::max(), uint32_t txn = std::numeric_limits<uint32_t>::max());
void ForEachAccountHistory(std::function<bool(AccountHistoryKey const &, CLazySerialize<AccountHistoryValue>)> callback, AccountHistoryKey const & start = {});

// tags
struct ByAccountHistoryKey { static constexpr uint8_t prefix() { return 'h'; } };
struct ByAccountHistoryKeyNew { static constexpr uint8_t prefix() { return 'H'; } };
struct ByAccountHistoryKey { static constexpr uint8_t prefix() { return 'h'; } };
};

class CAccountHistoryStorage : public CAccountsHistoryView
, public CAuctionHistoryView
{
public:
CAccountHistoryStorage(CAccountHistoryStorage& accountHistory) : CStorageView(new CFlushableStorageKV(accountHistory.DB())) {}
CAccountHistoryStorage(const fs::path& dbName, std::size_t cacheSize, bool fMemory = false, bool fWipe = false);
};

@@ -87,44 +82,75 @@ class CBurnHistoryStorage : public CAccountsHistoryView
};

class CHistoryWriters {
CAccountHistoryStorage* historyView{};
CBurnHistoryStorage* burnView{};
CAccountHistoryStorage* historyView;
CBurnHistoryStorage* burnView;
std::map<CScript, TAmounts> diffs;
std::map<CScript, TAmounts> burnDiffs;
std::map<uint256, std::map<CScript,TAmounts>> vaultDiffs;

public:
CVaultHistoryStorage* vaultView{};
CVaultHistoryStorage* vaultView;
CLoanSchemeCreation globalLoanScheme;
std::string schemeID;

CHistoryWriters(CAccountHistoryStorage* historyView, CBurnHistoryStorage* burnView, CVaultHistoryStorage* vaultView);

CAccountHistoryStorage* GetAccountHistoryStore() { return historyView; };

void AddBalance(const CScript& owner, const CTokenAmount amount, const uint256& vaultID);
void AddFeeBurn(const CScript& owner, const CAmount amount);
void SubBalance(const CScript& owner, const CTokenAmount amount, const uint256& vaultID);
void Flush(const uint32_t height, const uint256& txid, const uint32_t txn, const uint8_t type, const uint256& vaultID);
};

class CHistoryErasers {
CAccountHistoryStorage* historyView;
CBurnHistoryStorage* burnView;
std::set<CScript> accounts;
std::set<CScript> burnAccounts;
std::set<uint256> vaults;

public:
CVaultHistoryStorage* vaultView;
bool removeLoanScheme{false};
uint256 schemeCreationTxid;

CHistoryErasers(CAccountHistoryStorage* historyView, CBurnHistoryStorage* burnView, CVaultHistoryStorage* vaultView);

void AddBalance(const CScript& owner, const uint256& vaultID);
void SubFeeBurn(const CScript& owner);
void SubBalance(const CScript& owner, const uint256& vaultID);
void Flush(const uint32_t height, const uint32_t txn, const uint256& vaultID);
};

class CAccountsHistoryWriter : public CCustomCSView
{
const uint32_t height;
const uint32_t txn;
const uint256 txid;
const uint8_t type;
CHistoryWriters* writers{};
CHistoryWriters* writers;

public:
uint256 vaultID;

CAccountsHistoryWriter(CCustomCSView & storage, uint32_t height, uint32_t txn, const uint256& txid, uint8_t type, CHistoryWriters* writers);
Res AddBalance(CScript const & owner, CTokenAmount amount) override;
Res SubBalance(CScript const & owner, CTokenAmount amount) override;
bool Flush() override;
bool Flush();
};

CAccountHistoryStorage* GetAccountHistoryStore() override;
class CAccountsHistoryEraser : public CCustomCSView
{
const uint32_t height;
const uint32_t txn;
CHistoryErasers& erasers;

public:
uint256 vaultID;

CAccountsHistoryEraser(CCustomCSView & storage, uint32_t height, uint32_t txn, CHistoryErasers& erasers);
Res AddBalance(CScript const & owner, CTokenAmount amount) override;
Res SubBalance(CScript const & owner, CTokenAmount amount) override;
bool Flush();
};

extern std::unique_ptr<CAccountHistoryStorage> paccountHistoryDB;
2 changes: 1 addition & 1 deletion src/masternodes/anchors.cpp
Original file line number Diff line number Diff line change
@@ -1011,7 +1011,7 @@ bool CAnchorAwaitingConfirms::Validate(CAnchorConfirmMessage const &confirmMessa
}

auto it = pcustomcsview->GetMasternodeIdByOperator(signer);
if (!it || !pcustomcsview->GetMasternode(*it)->IsActive(height, *pcustomcsview)) {
if (!it || !pcustomcsview->GetMasternode(*it)->IsActive(height)) {
LogPrint(BCLog::ANCHORING, "%s: Warning! Masternode with operator key %s does not exist or not active!\n", __func__, signer.ToString());
return false;
}
6 changes: 3 additions & 3 deletions src/masternodes/anchors.h
Original file line number Diff line number Diff line change
@@ -9,7 +9,6 @@
#include <script/script.h>
#include <script/standard.h>
#include <serialize.h>
#include <shutdown.h>
#include <uint256.h>

#include <functional>
@@ -23,6 +22,8 @@
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/ordered_index.hpp>

#include <boost/thread.hpp>

#include <dbwrapper.h>

class CBlockIndex;
@@ -276,8 +277,7 @@ class CAnchorIndex

while (pcursor->Valid())
{
// ShutdownRequested replaces interruption_point
if (ShutdownRequested()) break;
boost::this_thread::interruption_point();
std::pair<char, Key> key;
if (pcursor->GetKey(key) && key.first == prefix)
{
310 changes: 86 additions & 224 deletions src/masternodes/govvariables/attributes.cpp

Large diffs are not rendered by default.

69 changes: 14 additions & 55 deletions src/masternodes/govvariables/attributes.h
Original file line number Diff line number Diff line change
@@ -28,35 +28,26 @@ enum ParamIDs : uint8_t {
DFIP2203 = 'b',
TokenID = 'c',
Economy = 'e',
DFIP2206A = 'f',
DFIP2206F = 'g',
};

enum OracleIDs : uint8_t {
Splits = 'a',
};

enum EconomyKeys : uint8_t {
PaybackDFITokens = 'a',
PaybackTokens = 'b',
DFIP2203Current = 'c',
DFIP2203Burned = 'd',
DFIP2203Minted = 'e',
DFIP2206FCurrent = 'f',
DFIP2206FBurned = 'g',
DFIP2206FMinted = 'h',
DexTokens = 'i',
PaybackDFITokens = 'a',
PaybackTokens = 'b',
DFIP2203Current = 'c',
DFIP2203Burned = 'd',
DFIP2203Minted = 'e',
};

enum DFIPKeys : uint8_t {
Active = 'a',
Premium = 'b',
MinSwap = 'c',
RewardPct = 'd',
BlockPeriod = 'e',
DUSDInterestBurn = 'g',
DUSDLoanBurn = 'h',
StartBlock = 'i',
Active = 'a',
Premium = 'b',
MinSwap = 'c',
RewardPct = 'd',
BlockPeriod = 'e',
};

enum TokenKeys : uint8_t {
@@ -149,48 +140,19 @@ struct CFeeDir {
}
};

ResVal<CScript> GetFutureSwapContractAddress(const std::string& contract);

struct CDexTokenInfo {
struct CTokenInfo {
uint64_t swaps;
uint64_t feeburn;
uint64_t commissions;

ADD_SERIALIZE_METHODS;

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(swaps);
READWRITE(feeburn);
READWRITE(commissions);
}
};

CTokenInfo totalTokenA;
CTokenInfo totalTokenB;

ADD_SERIALIZE_METHODS;

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(totalTokenA);
READWRITE(totalTokenB);
}
};
ResVal<CScript> GetFutureSwapContractAddress();

enum FeeDirValues : uint8_t {
Both,
In,
Out
};

using CDexBalances = std::map<DCT_ID, CDexTokenInfo>;
using OracleSplits = std::map<uint32_t, int32_t>;
using DescendantValue = std::pair<uint32_t, int32_t>;
using AscendantValue = std::pair<uint32_t, std::string>;
using CAttributeType = std::variant<CDataStructureV0, CDataStructureV1>;
using CAttributeValue = std::variant<bool, CAmount, CBalances, CTokenPayback, CTokenCurrencyPair, OracleSplits, DescendantValue, AscendantValue, CFeeDir, CDexBalances>;
using CAttributeValue = std::variant<bool, CAmount, CBalances, CTokenPayback, CTokenCurrencyPair, OracleSplits, DescendantValue, AscendantValue, CFeeDir>;

enum GovVarsFilter {
All,
@@ -213,7 +175,7 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator<GovVariable, ATTRI
Res Import(UniValue const &val) override;
UniValue Export() const override;
UniValue ExportFiltered(GovVarsFilter filter, const std::string &prefix) const;

Res Validate(CCustomCSView const& mnview) const override;
Res Apply(CCustomCSView &mnview, const uint32_t height) override;

@@ -290,7 +252,6 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator<GovVariable, ATTRI
READWRITE(attributes);
}


uint32_t time{0};

// For formatting in export
@@ -304,8 +265,7 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator<GovVariable, ATTRI

private:
friend class CGovView;
bool futureUpdated{};
bool futureDUSDUpdated{};
bool futureBlockUpdated{};
std::set<uint32_t> tokenSplits{};
std::set<CAttributeType> changed;
std::map<CAttributeType, CAttributeValue> attributes;
@@ -322,7 +282,6 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator<GovVariable, ATTRI

Res ProcessVariable(const std::string& key, const std::string& value,
std::function<Res(const CAttributeType&, const CAttributeValue&)> applyVariable);
Res RefundFuturesDUSD(CCustomCSView &mnview, const uint32_t height);
};

#endif // DEFI_MASTERNODES_GOVVARIABLES_ATTRIBUTES_H
24 changes: 1 addition & 23 deletions src/masternodes/gv.cpp
Original file line number Diff line number Diff line change
@@ -15,29 +15,7 @@

Res CGovView::SetVariable(GovVariable const & var)
{
auto WriteVar = [this](GovVariable const & var) {
return WriteBy<ByName>(var.GetName(), var) ? Res::Ok() : Res::Err("can't write to DB");
};
if (var.GetName() != "ATTRIBUTES") {
return WriteVar(var);
}
auto attributes = GetAttributes();
if (!attributes) {
return WriteVar(var);
}
auto& current = dynamic_cast<const ATTRIBUTES&>(var);
if (current.changed.empty()) {
return Res::Ok();
}
for (auto& key : current.changed) {
auto it = current.attributes.find(key);
if (it == current.attributes.end()) {
attributes->attributes.erase(key);
} else {
attributes->attributes[key] = it->second;
}
}
return WriteVar(*attributes);
return WriteBy<ByName>(var.GetName(), var) ? Res::Ok() : Res::Err("can't write to DB");
}

std::shared_ptr<GovVariable> CGovView::GetVariable(std::string const & name) const
319 changes: 123 additions & 196 deletions src/masternodes/masternodes.cpp

Large diffs are not rendered by default.

108 changes: 28 additions & 80 deletions src/masternodes/masternodes.h
Original file line number Diff line number Diff line change
@@ -29,11 +29,8 @@
#include <set>
#include <stdint.h>

class CAccountHistoryStorage;
class CBlockIndex;
class CMasternodesView;
class CTransaction;
class CVaultHistoryStorage;

// Works instead of constants cause 'regtest' differs (don't want to overcharge chainparams)
int GetMnActivationDelay(int height);
@@ -43,17 +40,7 @@ CAmount GetMnCreationFee(int height);
CAmount GetTokenCreationFee(int height);
CAmount GetMnCollateralAmount(int height);

enum class UpdateMasternodeType : uint8_t
{
None = 0x00,
OwnerAddress = 0x01,
OperatorAddress = 0x02,
SetRewardAddress = 0x03,
RemRewardAddress = 0x04
};

constexpr uint8_t SUBNODE_COUNT{4};
constexpr uint32_t DEFAULT_CUSTOM_TX_EXPIRATION{120};

class CMasternode
{
@@ -63,7 +50,6 @@ class CMasternode
ENABLED,
PRE_RESIGNED,
RESIGNED,
TRANSFERRING,
UNKNOWN // unreachable
};

@@ -102,13 +88,13 @@ class CMasternode

//! This fields are for transaction rollback (by disconnecting block)
uint256 resignTx;
uint256 collateralTx;
uint256 banTx;

//! empty constructor
CMasternode();

State GetState(int height, const CMasternodesView& mnview) const;
bool IsActive(int height, const CMasternodesView& mnview) const;
State GetState(int height) const;
bool IsActive(int height) const;

static std::string GetHumanReadableState(State state);
static std::string GetTimelockToString(TimeLock timelock);
@@ -129,7 +115,7 @@ class CMasternode
READWRITE(version);

READWRITE(resignTx);
READWRITE(collateralTx);
READWRITE(banTx);

// Only available after FortCanning
if (version > PRE_FORT_CANNING) {
@@ -188,25 +174,12 @@ struct SubNodeBlockTimeKey
}
};

struct MNNewOwnerHeightValue
{
uint32_t blockHeight;
uint256 masternodeID;

ADD_SERIALIZE_METHODS;

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(blockHeight);
READWRITE(masternodeID);
}
};

class CMasternodesView : public virtual CStorageView
{
std::map<CKeyID, std::pair<uint32_t, int64_t>> minterTimeCache;

public:
// CMasternodesView() = default;

std::optional<CMasternode> GetMasternode(uint256 const & id) const;
std::optional<uint256> GetMasternodeIdByOperator(CKeyID const & id) const;
@@ -223,16 +196,12 @@ class CMasternodesView : public virtual CStorageView
std::set<std::pair<CKeyID, uint256>> GetOperatorsMulti() const;

Res CreateMasternode(uint256 const & nodeId, CMasternode const & node, uint16_t timelock);
Res ResignMasternode(CMasternode& node, uint256 const & nodeId, uint256 const & txid, int height);

// Masternode updates
void SetForcedRewardAddress(uint256 const & nodeId, CMasternode& node, const char rewardAddressType, CKeyID const & rewardAddress, int height);
void RemForcedRewardAddress(uint256 const & nodeId, CMasternode& node, int height);
void UpdateMasternodeOperator(uint256 const & nodeId, CMasternode& node, const char operatorType, const CKeyID& operatorAuthAddress, int height);
void UpdateMasternodeOwner(uint256 const & nodeId, CMasternode& node, const char ownerType, const CKeyID& ownerAuthAddress);
void UpdateMasternodeCollateral(uint256 const & nodeId, CMasternode& node, const uint256& newCollateralTx, const int height);
[[nodiscard]] std::optional<MNNewOwnerHeightValue> GetNewCollateral(const uint256& txid) const;
void ForEachNewCollateral(std::function<bool(const uint256&, CLazySerialize<MNNewOwnerHeightValue>)> callback);
Res ResignMasternode(uint256 const & nodeId, uint256 const & txid, int height);
Res UnCreateMasternode(uint256 const & nodeId);
Res UnResignMasternode(uint256 const & nodeId, uint256 const & resignTx);
Res SetForcedRewardAddress(uint256 const & nodeId, const char rewardAddressType, CKeyID const & rewardAddress, int height);
Res RemForcedRewardAddress(uint256 const & nodeId, int height);
Res UpdateMasternode(uint256 const & nodeId, char operatorType, const CKeyID& operatorAuthAddress, int height);

// Get blocktimes for non-subnode and subnode with fork logic
std::vector<int64_t> GetBlockTimes(const CKeyID& keyID, const uint32_t blockHeight, const int32_t creationHeight, const uint16_t timelock);
@@ -255,7 +224,6 @@ class CMasternodesView : public virtual CStorageView
struct ID { static constexpr uint8_t prefix() { return 'M'; } };
struct Operator { static constexpr uint8_t prefix() { return 'o'; } };
struct Owner { static constexpr uint8_t prefix() { return 'w'; } };
struct NewCollateral { static constexpr uint8_t prefix() { return 's'; } };

// For storing last staked block time
struct Staker { static constexpr uint8_t prefix() { return 'X'; } };
@@ -329,21 +297,6 @@ class CAnchorConfirmsView : public virtual CStorageView
struct BtcTx { static constexpr uint8_t prefix() { return 'x'; } };
};

class CSettingsView : public virtual CStorageView
{

public:
const std::string DEX_STATS_LAST_HEIGHT = "DexStatsLastHeight";
const std::string DEX_STATS_ENABLED = "DexStatsEnabled";

void SetDexStatsLastHeight(int32_t height);
std::optional<int32_t> GetDexStatsLastHeight();
void SetDexStatsEnabled(bool enabled);
std::optional<bool> GetDexStatsEnabled();

struct KVSettings { static constexpr uint8_t prefix() { return '0'; } };
};

class CCollateralLoans { // in USD

double calcRatio(uint64_t maxRatio) const;
@@ -398,12 +351,11 @@ class CCustomCSView
, public CICXOrderView
, public CLoanView
, public CVaultView
, public CSettingsView
{
void CheckPrefixes()
{
CheckPrefix<
CMasternodesView :: ID, NewCollateral, Operator, Owner, Staker, SubNode, Timelock,
CMasternodesView :: ID, Operator, Owner, Staker, SubNode, Timelock,
CLastHeightView :: Height,
CTeamView :: AuthTeam, ConfirmTeam, CurrentTeam,
CFoundationsDebtView :: Debt,
@@ -427,30 +379,34 @@ class CCustomCSView
CLoanView :: LoanSetCollateralTokenCreationTx, LoanSetCollateralTokenKey, LoanSetLoanTokenCreationTx,
LoanSetLoanTokenKey, LoanSchemeKey, DefaultLoanSchemeKey, DelayedLoanSchemeKey,
DestroyLoanSchemeKey, LoanInterestByVault, LoanTokenAmount, LoanLiquidationPenalty, LoanInterestV2ByVault,
CVaultView :: VaultKey, OwnerVaultKey, CollateralKey, AuctionBatchKey, AuctionHeightKey, AuctionBidKey,
CSettingsView :: KVSettings
CVaultView :: VaultKey, OwnerVaultKey, CollateralKey, AuctionBatchKey, AuctionHeightKey, AuctionBidKey
>();
}
private:
Res PopulateLoansData(CCollateralLoans& result, CVaultId const& vaultId, uint32_t height, int64_t blockTime, bool useNextPrice, bool requireLivePrice);
Res PopulateCollateralData(CCollateralLoans& result, CVaultId const& vaultId, CBalances const& collaterals, uint32_t height, int64_t blockTime, bool useNextPrice, bool requireLivePrice);

std::unique_ptr<CAccountHistoryStorage> accHistoryStore;
std::unique_ptr<CVaultHistoryStorage> vauHistoryStore;

uint32_t globalCustomTxExpiration{DEFAULT_CUSTOM_TX_EXPIRATION};

public:
// Increase version when underlaying tables are changed
static constexpr const int DbVersion = 1;

CCustomCSView();
explicit CCustomCSView(CStorageKV & st);
CCustomCSView()
{
CheckPrefixes();
}

// cache-upon-a-cache (not a copy!) constructor
CCustomCSView(CCustomCSView & other);
CCustomCSView(CStorageKV & st)
: CStorageView(new CFlushableStorageKV(st))
{
CheckPrefixes();
}

~CCustomCSView();
// cache-upon-a-cache (not a copy!) constructor
CCustomCSView(CCustomCSView & other)
: CStorageView(new CFlushableStorageKV(other.DB()))
{
CheckPrefixes();
}

// cause depends on current mns:
CTeamView::CTeam CalcNextTeam(int height, uint256 const & stakeModifier);
@@ -484,21 +440,13 @@ class CCustomCSView

int GetDbVersion() const;

void SetGlobalCustomTxExpiration(const uint32_t height);
uint32_t GetGlobalCustomTxExpiration() const;

uint256 MerkleRoot();

// we construct it as it
CFlushableStorageKV& GetStorage() {
return static_cast<CFlushableStorageKV&>(DB());
}

virtual CAccountHistoryStorage* GetAccountHistoryStore();
CVaultHistoryStorage* GetVaultHistoryStore();
void SetAccountHistoryStore();
void SetVaultHistoryStore();

struct DbVersion { static constexpr uint8_t prefix() { return 'D'; } };
};

740 changes: 429 additions & 311 deletions src/masternodes/mn_checks.cpp

Large diffs are not rendered by default.

76 changes: 50 additions & 26 deletions src/masternodes/mn_checks.h
Original file line number Diff line number Diff line change
@@ -41,6 +41,8 @@ enum class CustomTxType : uint8_t
CreateMasternode = 'C',
ResignMasternode = 'R',
UpdateMasternode = 'm',
SetForcedRewardAddress = 'F',
RemForcedRewardAddress = 'f',
// custom tokens:
CreateToken = 'T',
MintToken = 'M',
@@ -63,7 +65,7 @@ enum class CustomTxType : uint8_t
AccountToAccount = 'B',
AnyAccountsToAccounts = 'a',
SmartContract = 'K',
FutureSwap = 'Q',
DFIP2203 = 'Q',
//set governance variable
SetGovVariable = 'G',
SetGovVariableHeight = 'j',
@@ -101,20 +103,15 @@ enum class CustomTxType : uint8_t
// Marker TXs
FutureSwapExecution = 'q',
FutureSwapRefund = 'w',
TokenSplit = 'P',
};

enum class MetadataVersion : uint8_t {
None = 0,
One = 1,
Two = 2,
};

inline CustomTxType CustomTxCodeToType(uint8_t ch) {
auto type = static_cast<CustomTxType>(ch);
switch(type) {
case CustomTxType::CreateMasternode:
case CustomTxType::ResignMasternode:
case CustomTxType::SetForcedRewardAddress:
case CustomTxType::RemForcedRewardAddress:
case CustomTxType::UpdateMasternode:
case CustomTxType::CreateToken:
case CustomTxType::MintToken:
@@ -131,7 +128,7 @@ inline CustomTxType CustomTxCodeToType(uint8_t ch) {
case CustomTxType::AccountToAccount:
case CustomTxType::AnyAccountsToAccounts:
case CustomTxType::SmartContract:
case CustomTxType::FutureSwap:
case CustomTxType::DFIP2203:
case CustomTxType::SetGovVariable:
case CustomTxType::SetGovVariableHeight:
case CustomTxType::AutoAuthPrep:
@@ -163,7 +160,6 @@ inline CustomTxType CustomTxCodeToType(uint8_t ch) {
case CustomTxType::AuctionBid:
case CustomTxType::FutureSwapExecution:
case CustomTxType::FutureSwapRefund:
case CustomTxType::TokenSplit:
case CustomTxType::Reject:
case CustomTxType::None:
return type;
@@ -221,15 +217,45 @@ struct CResignMasterNodeMessage : public uint256 {
}
};

struct CSetForcedRewardAddressMessage {
uint256 nodeId;
char rewardAddressType;
CKeyID rewardAddress;

ADD_SERIALIZE_METHODS;

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(nodeId);
READWRITE(rewardAddressType);
READWRITE(rewardAddress);
}
};

struct CRemForcedRewardAddressMessage {
uint256 nodeId;

ADD_SERIALIZE_METHODS;

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(nodeId);
}
};

struct CUpdateMasterNodeMessage {
uint256 mnId;
std::vector<std::pair<uint8_t, std::pair<char, std::vector<unsigned char>>>> updates;
char operatorType;
CKeyID operatorAuthAddress;

ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(mnId);
READWRITE(updates);
READWRITE(operatorType);
READWRITE(operatorAuthAddress);
}
};

@@ -306,6 +332,8 @@ using CCustomTxMessage = std::variant<
CCustomTxMessageNone,
CCreateMasterNodeMessage,
CResignMasterNodeMessage,
CSetForcedRewardAddressMessage,
CRemForcedRewardAddressMessage,
CUpdateMasterNodeMessage,
CCreateTokenMessage,
CUpdateTokenPreAMKMessage,
@@ -353,17 +381,18 @@ using CCustomTxMessage = std::variant<
CAuctionBidMessage
>;

CCustomTxMessage customTypeToMessage(CustomTxType txType, uint8_t version);
CCustomTxMessage customTypeToMessage(CustomTxType txType);
bool IsMempooledCustomTxCreate(const CTxMemPool& pool, const uint256& txid);
Res RpcInfo(const CTransaction& tx, uint32_t height, CustomTxType& type, UniValue& results);
Res CustomMetadataParse(uint32_t height, const Consensus::Params& consensus, const std::vector<unsigned char>& metadata, CCustomTxMessage& txMessage);
Res ApplyCustomTx(CCustomCSView& mnview, const CCoinsViewCache& coins, const CTransaction& tx, const Consensus::Params& consensus, uint32_t height, uint64_t time = 0, uint256* canSpend = nullptr, uint32_t* customTxExpiration = nullptr, uint32_t txn = 0, CHistoryWriters* writers = nullptr);
Res ApplyCustomTx(CCustomCSView& mnview, const CCoinsViewCache& coins, const CTransaction& tx, const Consensus::Params& consensus, uint32_t height, uint64_t time = 0, uint32_t txn = 0, CHistoryWriters* writers = nullptr);
Res RevertCustomTx(CCustomCSView& mnview, const CCoinsViewCache& coins, const CTransaction& tx, const Consensus::Params& consensus, uint32_t height, uint32_t txn, CHistoryErasers& erasers);
Res CustomTxVisit(CCustomCSView& mnview, const CCoinsViewCache& coins, const CTransaction& tx, uint32_t height, const Consensus::Params& consensus, const CCustomTxMessage& txMessage, uint64_t time, uint32_t txn = 0);
ResVal<uint256> ApplyAnchorRewardTx(CCustomCSView& mnview, const CTransaction& tx, int height, const uint256& prevStakeModifier, const std::vector<unsigned char>& metadata, const Consensus::Params& consensusParams);
ResVal<uint256> ApplyAnchorRewardTxPlus(CCustomCSView& mnview, const CTransaction& tx, int height, const std::vector<unsigned char>& metadata, const Consensus::Params& consensusParams);
ResVal<CAmount> GetAggregatePrice(CCustomCSView& view, const std::string& token, const std::string& currency, uint64_t lastBlockTime);
bool IsVaultPriceValid(CCustomCSView& mnview, const CVaultId& vaultId, uint32_t height);
Res SwapToDFIorDUSD(CCustomCSView & mnview, DCT_ID tokenId, CAmount amount, CScript const & from, CScript const & to, uint32_t height, bool forceLoanSwap = false);
Res SwapToDFIOverUSD(CCustomCSView & mnview, DCT_ID tokenId, CAmount amount, CScript const & from, CScript const & to, uint32_t height);
Res storeGovVars(const CGovernanceHeightMessage& obj, CCustomCSView& view);

inline bool OraclePriceFeed(CCustomCSView& view, const CTokenCurrencyPair& priceFeed) {
@@ -381,8 +410,7 @@ inline bool OraclePriceFeed(CCustomCSView& view, const CTokenCurrencyPair& price
/*
* Checks if given tx is probably one of 'CustomTx', returns tx type and serialized metadata in 'data'
*/
inline CustomTxType GuessCustomTxType(CTransaction const & tx, std::vector<unsigned char> & metadata, bool metadataValidation = false,
uint32_t height = 0, CExpirationAndVersion* customTxParams = nullptr){
inline CustomTxType GuessCustomTxType(CTransaction const & tx, std::vector<unsigned char> & metadata, bool metadataValidation = false){
if (tx.vout.empty()) {
return CustomTxType::None;
}
@@ -391,25 +419,21 @@ inline CustomTxType GuessCustomTxType(CTransaction const & tx, std::vector<unsig
if (metadataValidation) {
for (size_t i{1}; i < tx.vout.size(); ++i) {
std::vector<unsigned char> dummydata;
uint8_t dummyOpcodes{HasForks::None};
bool dummyOpcodes{false};
if (ParseScriptByMarker(tx.vout[i].scriptPubKey, DfTxMarker, dummydata, dummyOpcodes)) {
return CustomTxType::Reject;
}
}
}

uint8_t hasAdditionalOpcodes{HasForks::None};
if (!ParseScriptByMarker(tx.vout[0].scriptPubKey, DfTxMarker, metadata, hasAdditionalOpcodes, customTxParams)) {
bool hasAdditionalOpcodes{false};
if (!ParseScriptByMarker(tx.vout[0].scriptPubKey, DfTxMarker, metadata, hasAdditionalOpcodes)) {
return CustomTxType::None;
}

// If metadata contains additional opcodes mark as Reject.
if (metadataValidation) {
if (height < static_cast<uint32_t>(Params().GetConsensus().GreatWorldHeight) && hasAdditionalOpcodes & HasForks::FortCanning) {
return CustomTxType::Reject;
} else if (height >= static_cast<uint32_t>(Params().GetConsensus().GreatWorldHeight) && hasAdditionalOpcodes & HasForks::GreatWorld) {
return CustomTxType::Reject;
}
if (metadataValidation && hasAdditionalOpcodes) {
return CustomTxType::Reject;
}

auto txType = CustomTxCodeToType(metadata[0]);
56 changes: 7 additions & 49 deletions src/masternodes/mn_rpc.cpp
Original file line number Diff line number Diff line change
@@ -425,9 +425,8 @@ std::vector<CTxIn> GetAuthInputsSmart(CWalletCoinsUnlocker& pwallet, int32_t txV

void execTestTx(const CTransaction& tx, uint32_t height, CTransactionRef optAuthTx) {
std::vector<unsigned char> metadata;
CExpirationAndVersion customTxParams;
auto txType = GuessCustomTxType(tx, metadata, false, 0, &customTxParams);
auto txMessage = customTypeToMessage(txType, customTxParams.version);
auto txType = GuessCustomTxType(tx, metadata);
auto txMessage = customTypeToMessage(txType);
auto res = CustomMetadataParse(height, Params().GetConsensus(), metadata, txMessage);
if (res) {
LOCK(cs_main);
@@ -453,7 +452,7 @@ CWalletCoinsUnlocker GetWallet(const JSONRPCRequest& request) {
return CWalletCoinsUnlocker{std::move(wallet)};
}

std::optional<FutureSwapHeightInfo> GetFuturesBlock(const uint32_t typeId)
std::optional<CAmount> GetFuturesBlock()
{
LOCK(cs_main);

@@ -462,21 +461,19 @@ std::optional<FutureSwapHeightInfo> GetFuturesBlock(const uint32_t typeId)
return {};
}

CDataStructureV0 activeKey{AttributeTypes::Param, typeId, DFIPKeys::Active};
CDataStructureV0 activeKey{AttributeTypes::Param, ParamIDs::DFIP2203, DFIPKeys::Active};
const auto active = attributes->GetValue(activeKey, false);
if (!active) {
return {};
}

CDataStructureV0 blockKey{AttributeTypes::Param, typeId, DFIPKeys::BlockPeriod};
CDataStructureV0 rewardKey{AttributeTypes::Param, typeId, DFIPKeys::RewardPct};
CDataStructureV0 blockKey{AttributeTypes::Param, ParamIDs::DFIP2203, DFIPKeys::BlockPeriod};
CDataStructureV0 rewardKey{AttributeTypes::Param, ParamIDs::DFIP2203, DFIPKeys::RewardPct};
if (!attributes->CheckKey(blockKey) || !attributes->CheckKey(rewardKey)) {
return {};
}

CDataStructureV0 startKey{AttributeTypes::Param, typeId, DFIPKeys::StartBlock};

return FutureSwapHeightInfo{attributes->GetValue(startKey, CAmount{}), attributes->GetValue(blockKey, CAmount{})};
return attributes->GetValue(blockKey, CAmount{});
}

UniValue setgov(const JSONRPCRequest& request) {
@@ -950,44 +947,6 @@ static UniValue clearmempool(const JSONRPCRequest& request)
return removed;
}

UniValue setcustomtxexpiration(const JSONRPCRequest& request) {
RPCHelpMan{"setcustomtxexpiration",
"\nSet the expiration in blocks of locally created transactions. This expiration is to be\n"
"added to the current block height at the point of transaction creation. Once the chain reaches the\n"
"combined height if the transaction has not been added to a block it will be removed from the mempool\n"
"and can no longer be added to a block\n",
{
{"blockCount", RPCArg::Type::NUM, RPCArg::Optional::NO, ""}
},
RPCResults{},
RPCExamples{
HelpExampleCli("setcustomtxexpiration", "10")
+ HelpExampleRpc("setcustomtxexpiration", "10")
},
}.Check(request);

RPCTypeCheck(request.params, {UniValue::VNUM}, false);

LOCK(cs_main);

pcustomcsview->SetGlobalCustomTxExpiration(request.params[0].get_int());

return {};
}

void AddVersionAndExpiration(CScript& metaData, const uint32_t height, const MetadataVersion version)
{
if (height < static_cast<uint32_t>(Params().GetConsensus().GreatWorldHeight)) {
return;
}

CExpirationAndVersion customTxParams{height + pcustomcsview->GetGlobalCustomTxExpiration(), static_cast<uint8_t>(version)};

CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << customTxParams;

metaData << ToByteVector(stream);
}

static const CRPCCommand commands[] =
{
@@ -1000,7 +959,6 @@ static const CRPCCommand commands[] =
{"blockchain", "isappliedcustomtx", &isappliedcustomtx, {"txid", "blockHeight"}},
{"blockchain", "listsmartcontracts", &listsmartcontracts, {}},
{"blockchain", "clearmempool", &clearmempool, {} },
{"blockchain", "setcustomtxexpiration", &setcustomtxexpiration, {"blockHeight"}},
};

void RegisterMNBlockchainRPCCommands(CRPCTable& tableRPC) {
18 changes: 1 addition & 17 deletions src/masternodes/mn_rpc.h
Original file line number Diff line number Diff line change
@@ -35,16 +35,6 @@ typedef enum {
SelectionPie,
} AccountSelectionMode;

enum class AmountFormat : uint8_t {
Unknown,
// amount@0
Id,
// amount@DFI
Symbol,
// amount@0#DFI
Combined,
};

class CWalletCoinsUnlocker {
std::shared_ptr<CWallet> pwallet;
std::vector<COutPoint> coins;
@@ -59,11 +49,6 @@ class CWalletCoinsUnlocker {
void AddLockedCoin(const COutPoint& coin);
};

struct FutureSwapHeightInfo {
CAmount startBlock;
CAmount blockPeriod;
};

// common functions
bool IsSkippedTx(const uint256& hash);
int chainHeight(interfaces::Chain::Lock& locked_chain);
@@ -77,7 +62,6 @@ CAccounts SelectAccountsByTargetBalances(const CAccounts& accounts, const CBalan
void execTestTx(const CTransaction& tx, uint32_t height, CTransactionRef optAuthTx = {});
CScript CreateScriptForHTLC(const JSONRPCRequest& request, uint32_t &blocks, std::vector<unsigned char>& image);
CPubKey PublickeyFromString(const std::string &pubkey);
std::optional<FutureSwapHeightInfo> GetFuturesBlock(const uint32_t typeId);
void AddVersionAndExpiration(CScript& metadata, const uint32_t height, const MetadataVersion version = MetadataVersion::One);
std::optional<CAmount> GetFuturesBlock();

#endif // DEFI_MASTERNODES_MN_RPC_H
Loading