From 1c1193d508a57f0d3f62668b8c946c224235ff31 Mon Sep 17 00:00:00 2001 From: jamescowens Date: Mon, 5 Oct 2020 23:14:38 -0400 Subject: [PATCH 01/53] Increment version to 5.0.1.3 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e6311471a1..6ebe0fea78 100755 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 5) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 1) -define(_CLIENT_VERSION_BUILD, 2) +define(_CLIENT_VERSION_BUILD, 3) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2020) define(_COPYRIGHT_HOLDERS,[The %s developers]) From 44218c4382554104df87ee161e5e9a76c575d415 Mon Sep 17 00:00:00 2001 From: Pythonix <9782029+Pythonix@users.noreply.github.com> Date: Tue, 6 Oct 2020 15:19:17 +0200 Subject: [PATCH 02/53] doc: Fix link in build-openbsd.md The link to the `build-unix.md` file was broken. --- doc/build-openbsd.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/build-openbsd.md b/doc/build-openbsd.md index 2dd80f4d90..93bfb26b5d 100644 --- a/doc/build-openbsd.md +++ b/doc/build-openbsd.md @@ -70,7 +70,7 @@ config_opts="runtime-link=shared threadapi=pthread threading=multi link=static v BerkeleyDB is only necessary for the wallet functionality. To skip this, pass `--disable-wallet` to `./configure`. -See "Berkeley DB" in [build_unix.md](build_unix.md) for instructions on how to build BerkeleyDB 4.8. +See "Berkeley DB" in [build-unix.md](build-unix.md) for instructions on how to build BerkeleyDB 4.8. You cannot use the BerkeleyDB library from ports, for the same reason as boost above (g++/libstd++ incompatibility). ```bash From 86c9f1492f2df02490a8a62d48d474252f2ac663 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Tue, 6 Oct 2020 10:31:37 -0500 Subject: [PATCH 03/53] Add out-of-sync status to "getinfo" and "getblockchaininfo" RPCs This adds an "up_to_date" field to the output of the "getinfo" and "getblockchaininfo" RPCs to indicate whether a node is in-sync. This is a common feature request from headless users. --- src/rpcblockchain.cpp | 1 + src/wallet/rpcwallet.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 72efc5148b..65bad5a91d 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -1815,6 +1815,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) UniValue res(UniValue::VOBJ), diff(UniValue::VOBJ); res.pushKV("blocks", nBestHeight); + res.pushKV("in_sync", !OutOfSyncByAge()); res.pushKV("moneysupply", ValueFromAmount(pindexBest->nMoneySupply)); diff.pushKV("current", GRC::GetCurrentDifficulty()); diff.pushKV("target", GRC::GetTargetDifficulty()); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index f6971100eb..b3f4d54678 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -109,6 +109,7 @@ UniValue getinfo(const UniValue& params, bool fHelp) obj.pushKV("newmint", ValueFromAmount(pwalletMain->GetNewMint())); obj.pushKV("stake", ValueFromAmount(pwalletMain->GetStake())); obj.pushKV("blocks", nBestHeight); + obj.pushKV("in_sync", !OutOfSyncByAge()); obj.pushKV("timeoffset", GetTimeOffset()); obj.pushKV("moneysupply", ValueFromAmount(pindexBest->nMoneySupply)); obj.pushKV("connections", (int)vNodes.size()); From 9c026ccab0264606a4d1bf3346db82e2315506ff Mon Sep 17 00:00:00 2001 From: raphahus <9782029+Pythonix@users.noreply.github.com> Date: Thu, 8 Oct 2020 12:29:41 +0200 Subject: [PATCH 04/53] add autocomplete feature to debug console --- src/qt/rpcconsole.cpp | 11 +++++++++++ src/qt/rpcconsole.h | 2 ++ src/rpcserver.cpp | 11 +++++++++++ src/rpcserver.h | 7 +++++++ 4 files changed, 31 insertions(+) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 39f4973bdb..e6017c49f6 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -405,6 +405,17 @@ void RPCConsole::setClientModel(ClientModel *model) ui->boostVersion->setText(model->formatBoostVersion()); ui->porDiff->setText(model->getDifficulty()); + //Setup autocomplete and attach it + QStringList wordList; + std::vector commandList = tableRPC.listCommands(); + for (size_t i = 0; i < commandList.size(); ++i) + { + wordList << commandList[i].c_str(); + } + + autoCompleter = new QCompleter(wordList, this); + ui->lineEdit->setCompleter(autoCompleter); + } } diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index c714453fda..9033ca441c 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -8,6 +8,7 @@ #include #include +#include #include namespace Ui { @@ -109,6 +110,7 @@ public slots: QList cachedNodeids; QMenu *peersTableContextMenu = nullptr; QMenu *banTableContextMenu = nullptr; + QCompleter *autoCompleter; static QString FormatBytes(quint64 bytes); void setTrafficGraphRange(int mins); /** show detailed information on ui about selected node */ diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 2a5ef942b1..32a93f0aef 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -896,6 +896,17 @@ UniValue CRPCTable::execute(const std::string& strMethod, const UniValue& params } } +std::vector CRPCTable::listCommands() const +{ + std::vector commandList; + typedef std::map commandMap; + + std::transform( mapCommands.begin(), mapCommands.end(), + std::back_inserter(commandList), + boost::bind(&commandMap::value_type::first,_1) ); + return commandList; +} + #ifdef TEST int main(int argc, char *argv[]) { diff --git a/src/rpcserver.h b/src/rpcserver.h index ce2741a1d2..bf4a860388 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -72,6 +72,13 @@ class CRPCTable * @throws an exception when an error happens. */ UniValue execute(const std::string &method, const UniValue& params) const; + + /** + * Returns a list of registered commands + * @returns List of registered commands. + */ + std::vector listCommands() const; + }; extern const CRPCTable tableRPC; From d88144d6de5bb565a2201347a5116fa9ca325022 Mon Sep 17 00:00:00 2001 From: jamescowens Date: Thu, 8 Oct 2020 13:52:50 -0400 Subject: [PATCH 05/53] Increment version to 5.0.2.1 --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index abf8bf21f9..e7012b1fa3 100755 --- a/configure.ac +++ b/configure.ac @@ -3,8 +3,8 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 5) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 2) -define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_IS_RELEASE, true) +define(_CLIENT_VERSION_BUILD, 1) +define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2020) define(_COPYRIGHT_HOLDERS,[The %s developers]) define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[Gridcoin]]) From c1b0dcbc0a294af2669705333516eb275ad43ca6 Mon Sep 17 00:00:00 2001 From: raphahus <9782029+Pythonix@users.noreply.github.com> Date: Fri, 9 Oct 2020 12:41:36 +0200 Subject: [PATCH 06/53] remove deprecated commands from autocomplete --- src/rpcserver.cpp | 6 ++++++ src/rpcserver.h | 17 ++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 32a93f0aef..5cd8b3093a 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -896,6 +897,7 @@ UniValue CRPCTable::execute(const std::string& strMethod, const UniValue& params } } +constexpr const char* CRPCTable::DEPRECATED_RPCS[]; std::vector CRPCTable::listCommands() const { std::vector commandList; @@ -904,6 +906,10 @@ std::vector CRPCTable::listCommands() const std::transform( mapCommands.begin(), mapCommands.end(), std::back_inserter(commandList), boost::bind(&commandMap::value_type::first,_1) ); + // remove deprecated commands from autocomplete + for(auto &command: DEPRECATED_RPCS) { + std::remove(commandList.begin(), commandList.end(), command); + } return commandList; } diff --git a/src/rpcserver.h b/src/rpcserver.h index bf4a860388..089859b940 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -59,6 +59,22 @@ class CRPCTable { private: std::map mapCommands; + static constexpr const char* DEPRECATED_RPCS[] { + "debug", + "debug10", + "execute" , + "getaccount", + "getaccountaddress", + "getaddressesbyaccount", + "getreceivedbyaccount", + "listaccounts", + "listreceivedbyaccount", + "list", + "move", + "setaccount", + "vote", + }; + public: CRPCTable(); const CRPCCommand* operator[](std::string name) const; @@ -80,7 +96,6 @@ class CRPCTable std::vector listCommands() const; }; - extern const CRPCTable tableRPC; extern int64_t nWalletUnlockTime; From 8e4b57ebab09c846585960d98b545de786ca7635 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Mon, 5 Oct 2020 10:01:08 -0500 Subject: [PATCH 07/53] Add checkpoint post block version 11 transition --- src/chainparams.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 24e92fce05..a3a02f5b07 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -124,9 +124,9 @@ class CMainParams : public CChainParams { {1800000, uint256S("0x61bb76ed90de21016de81855d3dc01bd192d17d90de4bdf62e8203c2dde675d7")}, {1900000, uint256S("0x352ca52f9a22fbf1d241082d3bec716ea5bef6b82811f737ae6486bd7771e1c7")}, {2000000, uint256S("0x2e1252a6ed6d0e7e556d4d0377b10f4b542ae5d6c9822cb08d68490a2a0bb706")}, + {2054000, uint256S("0xfa1342b4076ca65be64abd7f9cea50cbbdb6247a6937f1f02d6e76494aab20bf")}, } }; - } }; From 4a0b25a14182b667ea558fe93e3e3ae69b0796ac Mon Sep 17 00:00:00 2001 From: raphahus <9782029+Pythonix@users.noreply.github.com> Date: Sun, 11 Oct 2020 22:39:00 +0200 Subject: [PATCH 08/53] move DEPRECATED_RPCS to rpcserver.cpp to prevent header bloat --- src/rpcserver.cpp | 18 +++++++++++++++++- src/rpcserver.h | 16 ---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 5cd8b3093a..e5913afb2a 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -443,6 +443,22 @@ static const CRPCCommand vRPCCommands[] = { "votedetails", &votedetails, cat_voting }, }; +static constexpr const char* DEPRECATED_RPCS[] { + "debug", + "debug10", + "execute" , + "getaccount", + "getaccountaddress", + "getaddressesbyaccount", + "getreceivedbyaccount", + "listaccounts", + "listreceivedbyaccount", + "list", + "move", + "setaccount", + "vote", +}; + CRPCTable::CRPCTable() { unsigned int vcidx; @@ -897,7 +913,7 @@ UniValue CRPCTable::execute(const std::string& strMethod, const UniValue& params } } -constexpr const char* CRPCTable::DEPRECATED_RPCS[]; + std::vector CRPCTable::listCommands() const { std::vector commandList; diff --git a/src/rpcserver.h b/src/rpcserver.h index 089859b940..317eb58b8c 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -59,22 +59,6 @@ class CRPCTable { private: std::map mapCommands; - static constexpr const char* DEPRECATED_RPCS[] { - "debug", - "debug10", - "execute" , - "getaccount", - "getaccountaddress", - "getaddressesbyaccount", - "getreceivedbyaccount", - "listaccounts", - "listreceivedbyaccount", - "list", - "move", - "setaccount", - "vote", - }; - public: CRPCTable(); const CRPCCommand* operator[](std::string name) const; From 961180d870c77ab519e3b5cec97d52edb3251d65 Mon Sep 17 00:00:00 2001 From: jamescowens Date: Tue, 13 Oct 2020 08:51:38 -0400 Subject: [PATCH 09/53] Modify depends packages for openSUSE In a cross-compilation for Windows using mingw, openSUSE places some libraries and pkgconfig files in lib64 rather than lib in the depends mini op sys tree. This causes problems with configure downstream. This implements a simple directive for curl, bdb, bdb53, and libzip to place their library files in lib instead of lib64. This should have no deleterious effect on other distributions. My guess is that other rpm based distros, such as Redhat, may have the same issue when using depends. --- depends/packages/bdb.mk | 1 + depends/packages/bdb53.mk | 1 + depends/packages/boost.mk | 0 depends/packages/bzip2.mk | 0 depends/packages/curl.mk | 3 ++- depends/packages/libzip.mk | 4 +++- depends/packages/native_ccache.mk | 0 depends/packages/openssl.mk | 0 depends/packages/packages.mk | 0 depends/packages/qrencode.mk | 2 +- depends/packages/zlib.mk | 0 11 files changed, 8 insertions(+), 3 deletions(-) mode change 100755 => 100644 depends/packages/bdb53.mk mode change 100755 => 100644 depends/packages/boost.mk mode change 100755 => 100644 depends/packages/bzip2.mk mode change 100755 => 100644 depends/packages/curl.mk mode change 100755 => 100644 depends/packages/libzip.mk mode change 100755 => 100644 depends/packages/native_ccache.mk mode change 100755 => 100644 depends/packages/openssl.mk mode change 100755 => 100644 depends/packages/packages.mk mode change 100755 => 100644 depends/packages/zlib.mk diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk index afac697e12..05da9acf6a 100644 --- a/depends/packages/bdb.mk +++ b/depends/packages/bdb.mk @@ -8,6 +8,7 @@ $(package)_build_subdir=build_unix define $(package)_set_vars $(package)_config_opts=--disable-shared --enable-cxx --disable-replication + $(package)_config_opts+=--libdir=$($($(package)_type)_prefix)/lib $(package)_config_opts_mingw32=--enable-mingw $(package)_config_opts_linux=--with-pic $(package)_cxxflags=-std=c++11 diff --git a/depends/packages/bdb53.mk b/depends/packages/bdb53.mk old mode 100755 new mode 100644 index d964ddad8d..b8eb318d08 --- a/depends/packages/bdb53.mk +++ b/depends/packages/bdb53.mk @@ -8,6 +8,7 @@ $(package)_build_subdir=build_unix define $(package)_set_vars $(package)_config_opts=--disable-shared --enable-cxx --disable-replication + $(package)_config_opts+=--libdir=$($($(package)_type)_prefix)/lib $(package)_config_opts_mingw32=--enable-mingw $(package)_config_opts_linux=--with-pic $(package)_cxxflags=-std=c++11 diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk old mode 100755 new mode 100644 diff --git a/depends/packages/bzip2.mk b/depends/packages/bzip2.mk old mode 100755 new mode 100644 diff --git a/depends/packages/curl.mk b/depends/packages/curl.mk old mode 100755 new mode 100644 index d9ed3ea56e..73944b9fcf --- a/depends/packages/curl.mk +++ b/depends/packages/curl.mk @@ -10,11 +10,12 @@ define $(package)_set_vars $(package)_config_opts=--disable-shared $(package)_config_opts+= --enable-static $(package)_config_opts+= --without-brotli + $(package)_config_opts+= --libdir=$($($(package)_type)_prefix)/lib $(package)_config_opts_release+=--disable-debug-mode $(package)_config_opts_linux+=--with-pic # Disable OpenSSL for Windows and use native SSL stack (SSPI/Schannel): $(package)_config_opts_mingw32+= --with-winssl --without-ssl - # This extra flag for macOS is necesarry as curl will append a -mmacosx-version-min=10.8 otherwise + # This extra flag for macOS is necessary as curl will append a -mmacosx-version-min=10.8 otherwise # which will cause the linker to fail as it cannot optimize away a __builtin_available(MacOS 10.11...) call # which requires a link to compiler runtime library. $(package)_cflags_darwin=-mmacosx-version-min=$(OSX_MIN_VERSION) diff --git a/depends/packages/libzip.mk b/depends/packages/libzip.mk old mode 100755 new mode 100644 index f3c59c99f3..a35ace1274 --- a/depends/packages/libzip.mk +++ b/depends/packages/libzip.mk @@ -31,7 +31,9 @@ define $(package)_preprocess_cmds endef define $(package)_config_cmds - $($(package)_build_opts) CFLAGS=$(i686_cflag) ./configure --host=$(host) --prefix=$(host_prefix) --with-zlib=$(host_prefix) --with-bzip2=$(host_prefix) --with-pic --enable-static --enable-shared=no + $($(package)_build_opts) CFLAGS=$(i686_cflag) ./configure --host=$(host) \ + --prefix=$(host_prefix) --with-zlib=$(host_prefix) --with-bzip2=$(host_prefix) \ + --with-pic --enable-static --enable-shared=no --libdir=$($($(package)_type)_prefix)/lib endef define $(package)_build_cmds diff --git a/depends/packages/native_ccache.mk b/depends/packages/native_ccache.mk old mode 100755 new mode 100644 diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk old mode 100755 new mode 100644 diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk old mode 100755 new mode 100644 diff --git a/depends/packages/qrencode.mk b/depends/packages/qrencode.mk index bd97880d69..8a2e420205 100644 --- a/depends/packages/qrencode.mk +++ b/depends/packages/qrencode.mk @@ -6,7 +6,7 @@ $(package)_file_name=$(package)-$($(package)_version).tar.bz2 $(package)_sha256_hash=efe5188b1ddbcbf98763b819b146be6a90481aac30cfc8d858ab78a19cde1fa5 define $(package)_set_vars - $(package)_config_opts=--disable-shared -without-tools --disable-sdltest + $(package)_config_opts=--disable-shared -without-tools --disable-sdltest --libdir="$($($(package)_type)_prefix)/lib" $(package)_config_opts_linux=--with-pic $(package)_cxxflags_aarch64_linux = $(GCCFLAGS) $(package)_cflags_aarch64_linux = $(GCCFLAGS) diff --git a/depends/packages/zlib.mk b/depends/packages/zlib.mk old mode 100755 new mode 100644 From 5b54383d2986120c9e6ce8a16979361cb9de1b2e Mon Sep 17 00:00:00 2001 From: jamescowens Date: Fri, 16 Oct 2020 13:09:48 -0400 Subject: [PATCH 10/53] Fix bdb53 compile for mingw (Windows) --- depends/packages/bdb53.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/depends/packages/bdb53.mk b/depends/packages/bdb53.mk index b8eb318d08..2a9af2010d 100644 --- a/depends/packages/bdb53.mk +++ b/depends/packages/bdb53.mk @@ -21,6 +21,7 @@ endef define $(package)_preprocess_cmds sed -i.old 's/__atomic_compare_exchange/__atomic_compare_exchange_db/' src/dbinc/atomic.h && \ sed -i.old 's/atomic_init/atomic_init_db/' src/dbinc/atomic.h src/mp/mp_region.c src/mp/mp_mvcc.c src/mp/mp_fget.c src/mutex/mut_method.c src/mutex/mut_tas.c && \ + sed -i.old "s/WinIoCtl.h/winioctl.h/g" src/dbinc/win_db.h && \ cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub dist endef From 04867b206094c02a9256af5241354e45d9018be0 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Fri, 16 Oct 2020 21:18:44 -0500 Subject: [PATCH 11/53] Add -forcecpid configuration option Enable a user to override CPIDs detected from BOINC's client_state.xml file. This provides some flexibility for a user that needs to manage a split CPID situation or for people that run a wallet on computers that do not have BOINC installed. --- src/gridcoin/researcher.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/gridcoin/researcher.cpp b/src/gridcoin/researcher.cpp index 4c5d39301e..27090e5222 100644 --- a/src/gridcoin/researcher.cpp +++ b/src/gridcoin/researcher.cpp @@ -1185,8 +1185,26 @@ void Researcher::Reload(MiningProjectMap projects, GRC::BeaconError beacon_error MiningId mining_id = MiningId::ForInvestor(); - for (const auto& project_pair : projects) { - TryProjectCpid(mining_id, project_pair.second); + // Enable a user to override CPIDs detected from BOINC's client_state.xml + // file. This provides some flexibility for a user that needs to manage a + // split CPID situation or for people that run a wallet on computers that + // do not have BOINC installed: + // + if (mapArgs.count("-forcecpid")) { + mining_id = MiningId::Parse(GetArg("-forcecpid", "")); + + if (mining_id.Which() == MiningId::Kind::CPID) { + LogPrintf("Configuration forces CPID: %s", mining_id.ToString()); + } else { + LogPrintf("ERROR: invalid CPID in -forcecpid"); + mining_id = MiningId::ForInvestor(); + } + } + + if (mining_id.Which() != MiningId::Kind::CPID) { + for (const auto& project_pair : projects) { + TryProjectCpid(mining_id, project_pair.second); + } } if (const CpidOption cpid = mining_id.TryCpid()) { From 9d000ed887130c543b7ec313ec583955b9bf0a07 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Fri, 16 Oct 2020 21:20:26 -0500 Subject: [PATCH 12/53] Add research reward system options to CLI help message This adds help information for the configuration options used to control the behavior of research reward features. --- src/init.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index 4828613e02..560809a566 100755 --- a/src/init.cpp +++ b/src/init.cpp @@ -290,6 +290,13 @@ std::string HelpMessage() " -blockmaxsize= " + _("Set maximum block size in bytes (default: 250000)") + "\n" + " -blockprioritysize= " + _("Set maximum size of high-priority/low-fee transactions in bytes (default: 27000)") + "\n" + + "\n" + _("Research reward system options:") + "\n" + + " -email= " + _("Email address to use for CPID detection. Must match your BOINC account email") + "\n" + + " -boincdatadir= " + _("Path to the BOINC data directory for CPID detection when the BOINC client uses a non-default directory") + "\n" + + " -forcecpid= " + _("Override automatic CPID detection with the specified CPID") + "\n" + + " -investor " + _("Disable CPID detection and do not participate in the research reward system") + "\n" + + " -pooloperator " + _("Skip pool CPID checks for staking nodes run by pool administrators") + "\n" + + "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n" + " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n" + " -rpcsslcertificatechainfile= " + _("Server certificate file (default: server.cert)") + "\n" + From 5475bfd043f1035d484e22ca7786ccc5ce27b8e4 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Fri, 16 Oct 2020 21:56:26 -0500 Subject: [PATCH 13/53] Remove now useless superblock voting hash RPCs This removes: - myneuralhash - neuralhash - refhash These RPC functions display the superblock hashes used for legacy quorum voting in block version 10 and below. The output is irrelevant to blocks version 11+ which validate superblocks from scraper convergences. --- src/rpcblockchain.cpp | 55 ------------------------------------------- src/rpcserver.cpp | 3 --- src/rpcserver.h | 3 --- 3 files changed, 61 deletions(-) diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 65bad5a91d..f68cbc80db 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -1094,40 +1094,6 @@ UniValue magnitude(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, "No data for investor."); } -UniValue myneuralhash(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "myneuralhash\n" - "\n" - "Displays information about your node's current superblock hash\n"); - - UniValue res(UniValue::VOBJ); - - LOCK(cs_main); - - res.pushKV("my_hash", GRC::Quorum::CreateSuperblock().GetHash().ToString()); - - return res; -} - -UniValue neuralhash(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "neuralhash\n" - "\n" - "Displays information about the popular superblock hash\n"); - - UniValue res(UniValue::VOBJ); - - LOCK(cs_main); - - res.pushKV("Popular", GRC::Quorum::FindPopularHash(pindexBest).ToString()); - - return res; -} - UniValue resetcpids(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -1660,27 +1626,6 @@ UniValue readdata(const UniValue& params, bool fHelp) return res; } -UniValue refhash(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "refhash \n" - "\n" - " -> GRC address to test against\n" - "\n" - "Tests to see if a GRC Address is a superblock quorum participant along with default wallet address\n"); - - UniValue res(UniValue::VOBJ); - - bool r1 = GRC::Quorum::Participating(params[0].get_str(), GetAdjustedTime()); - bool r2 = GRC::Quorum::Participating(DefaultWalletAddress(), GetAdjustedTime()); - - res.pushKV(" Date: Fri, 16 Oct 2020 21:56:30 -0500 Subject: [PATCH 14/53] Remove transitions to version 2 transactions This removes the plumbing that enabled the network to transition to version 2 transactions for the block version 11 hard fork. --- src/main.cpp | 50 ++----------------------------------------- src/main.h | 1 - src/wallet/wallet.cpp | 19 +--------------- 3 files changed, 3 insertions(+), 67 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d8478a572e..e595d5dec6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -877,23 +877,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CTransaction &tx, bool* pfMissingInput *pfMissingInputs = false; // Mandatory switch to binary contracts (tx version 2): - if (IsV11Enabled(nBestHeight + 1) && tx.nVersion < 2) { - // Disallow tx version 1 after the mandatory block to prohibit the - // use of legacy string contracts: + if (tx.nVersion < 2) { return tx.DoS(100, error("AcceptToMemoryPool : legacy transaction")); } - // Reject version 2 transactions until mandatory threshold. - // - // CTransaction::CURRENT_VERSION is now 2, but we cannot send version 2 - // transactions with binary contracts until clients can handle them. - // - // TODO: remove this check in the next release after mandatory block. - // - if (!IsV11Enabled(nBestHeight + 1) && tx.nVersion > 1) { - return error("AcceptToMemoryPool : v2 transaction too early"); - } - if (!tx.CheckTransaction()) return error("AcceptToMemoryPool : CheckTransaction failed"); @@ -1124,22 +1111,6 @@ void CTxMemPool::queryHashes(std::vector& vtxid) vtxid.push_back((*mi).first); } -void CTxMemPool::DiscardVersion1() -{ - LOCK(cs); - - // Recursively remove all version 1 transactions from the memory pool for - // the switch to transaction version 2 at the block version 11 threshold: - // - for (const auto& tx_pair : mapTx) { - if (tx_pair.second.nVersion == 1) { - remove(tx_pair.second, true); - } - } -} - - - int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const { if (hashBlock.IsNull() || nIndex == -1) @@ -2514,7 +2485,7 @@ bool ReorganizeChain(CTxDB& txdb, unsigned &cnt_dis, unsigned &cnt_con, CBlock & // Blocks version 11+ do not use the legacy tally system triggered by // block height intervals: // - if (!IsV11Enabled(pcommon->nHeight) && pcommon != pindexBest) + if (pcommon->nVersion <= 10 && pcommon != pindexBest) { pcommon = GRC::Tally::FindLegacyTrigger(pcommon); if(!pcommon) @@ -3024,17 +2995,6 @@ bool CBlock::AcceptBlock(bool generated_by_me) return DoS(100, error("%s: legacy transaction", __func__)); } - // Reject version 2 transactions until mandatory threshold. - // - // CTransaction::CURRENT_VERSION is now 2, but we cannot send version 2 - // transactions with binary contracts until clients can handle them. - // - // TODO: remove this check in the next release after mandatory block. - // - if (nVersion <= 10 && tx.nVersion > 1) { - return DoS(100, error("%s: v2 transaction too early", __func__)); - } - // Check that all transactions are finalized if (!IsFinalTx(tx, nHeight, GetBlockTime())) return DoS(10, error("AcceptBlock() : contains a non-final transaction")); @@ -3171,12 +3131,6 @@ bool GridcoinServices() return error("GridcoinServices: Failed to prepare tally for v11."); } - // Remove all version 1 transactions from the memory pool for the - // switch to transaction version 2 to prevent nodes from relaying - // legacy transactions that cannot validate: - // - mempool.DiscardVersion1(); - // Set the timestamp for the block version 11 threshold. This // is temporary. Remove this variable in a release that comes // after the hard fork. diff --git a/src/main.h b/src/main.h index d1837efc0d..0c8d0ac053 100644 --- a/src/main.h +++ b/src/main.h @@ -1836,7 +1836,6 @@ class CTxMemPool bool removeConflicts(const CTransaction &tx); void clear(); void queryHashes(std::vector& vtxid); - void DiscardVersion1(); unsigned long size() const { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 9eb2cbed50..c367293581 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1138,7 +1138,7 @@ void CWalletTx::RelayWalletTransaction(CTxDB& txdb) // requires the consent of the user. Log a message instead so // that the user can take action if needed: // - if (nVersion == 1 && IsV11Enabled(nBestHeight + 1)) + if (nVersion == 1) { if (IsCoinBase() || IsCoinStake()) { @@ -1730,23 +1730,6 @@ bool CWallet::CreateTransaction(const vector >& vecSend, { LOCK2(cs_main, cs_wallet); - // Force version 1 transactions until mandatory threshold. - // - // CTransaction::CURRENT_VERSION is now 2, but we cannot send version 2 - // transactions until clients can handle them. - // - // TODO: remove this check in the next release after mandatory block. - // - if (!IsV11Enabled(nBestHeight + 1)) { - wtxNew.nVersion = 1; - - if (!wtxNew.vContracts.empty() - && wtxNew.vContracts[0].m_type == GRC::ContractType::MESSAGE) - { - wtxNew.hashBoinc = wtxNew.vContracts[0].ToString(); - } - } - // txdb must be opened before the mapWallet lock CTxDB txdb("r"); { From 99a1ce6f50e9bc4cfcced96c2c2175887ad3ea4a Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Fri, 16 Oct 2020 21:56:33 -0500 Subject: [PATCH 15/53] Remove miner support for version 10 blocks --- src/miner.cpp | 106 +++----------------------------------------------- 1 file changed, 6 insertions(+), 100 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index b70ef68e89..7ca8a8e5bc 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -262,10 +262,6 @@ bool CreateRestOfTheBlock(CBlock &block, CBlockIndex* pindexPrev) assert(CoinBase.vin[0].scriptSig.size() <= 100); CoinBase.vout[0].SetEmpty(); - if (block.nVersion <= 10) { - CoinBase.nVersion = 1; // TODO: remove after mandatory - } - // Largest block you're willing to create: unsigned int nBlockMaxSize = GetArg("-blockmaxsize", MAX_BLOCK_SIZE_GEN/2); // Limit to between 1K and MAX_BLOCK_SIZE-1K for sanity: @@ -560,10 +556,6 @@ bool CreateCoinStake( CBlock &blocknew, CKey &key, int64_t StakeWeightMax=0; CTransaction &txnew = blocknew.vtx[1]; // second tx is coinstake - if (blocknew.nVersion <= 10) { - txnew.nVersion = 1; // TODO: remove after mandatory - } - //initialize the transaction txnew.nTime = blocknew.nTime & (~GRC::STAKE_TIMESTAMP_MASK); txnew.vin.clear(); @@ -951,14 +943,6 @@ bool SignStakeBlock(CBlock &block, CKey &key, vector &StakeInp return error("%s: failed to sign claim", __func__); } - // Stringify the claim context for legacy blocks. Version 11+ store claims - // in binary format. - // - if (block.nVersion <= 10) { - block.vtx[0].hashBoinc = block.GetClaim().ToString(block.nVersion); - block.vtx[0].vContracts.clear(); - } - //Sign the whole block block.hashMerkleRoot = block.BuildMerkleTree(); if( !key.Sign(block.GetHash(), block.vchBlockSig) ) @@ -986,67 +970,18 @@ void AddSuperblockContractOrVote(CBlock& blocknew) return; } - if (blocknew.nVersion >= 11) { - GRC::Superblock superblock = GRC::Quorum::CreateSuperblock(); - - if (!superblock.WellFormed()) { - LogPrintf("AddSuperblockContractOrVote: Local contract empty."); - return; - } - - // TODO: fix the const cast: - GRC::Claim& claim = const_cast(blocknew.GetClaim()); - - claim.m_quorum_hash = superblock.GetHash(); - claim.m_superblock.Replace(std::move(superblock)); - - LogPrintf( - "AddSuperblockContractOrVote: Added our Superblock (size %" PRIszu ").", - GetSerializeSize(claim.m_superblock, SER_NETWORK, 1)); - - return; - } - - // TODO: remove the rest below after switch to block version 11: + GRC::Superblock superblock = GRC::Quorum::CreateSuperblock(); - std::string quorum_address = DefaultWalletAddress(); - - if (!GRC::Quorum::Participating(quorum_address, blocknew.nTime)) { - LogPrintf("AddSuperblockContractOrVote: Not participating."); + if (!superblock.WellFormed()) { + LogPrintf("AddSuperblockContractOrVote: Local contract empty."); return; } // TODO: fix the const cast: GRC::Claim& claim = const_cast(blocknew.GetClaim()); - // Add our superblock vote - // - // CreateSuperblock() will return an empty superblock when the node has not - // yet received enough scraper data to resolve a convergence locally, so it - // cannot vote for a superblock. - // - claim.m_quorum_hash = GRC::Quorum::CreateSuperblock().GetHash(); - - if (!claim.m_quorum_hash.Valid()) { - LogPrintf("AddSuperblockContractOrVote: Local contract empty."); - return; - } - - claim.m_quorum_address = std::move(quorum_address); - - LogPrintf( - "AddSuperblockContractOrVote: Added our quorum vote: %s", - claim.m_quorum_hash.ToString()); - - const GRC::QuorumHash consensus_hash = GRC::Quorum::FindPopularHash(pindexBest); - - if (claim.m_quorum_hash != consensus_hash) { - LogPrintf("AddSuperblockContractOrVote: Not in consensus."); - return; - } - - // We have consensus, add our superblock contract: - claim.m_superblock.Replace(GRC::Quorum::CreateSuperblock()); + claim.m_quorum_hash = superblock.GetHash(); + claim.m_superblock.Replace(std::move(superblock)); LogPrintf( "AddSuperblockContractOrVote: Added our Superblock (size %" PRIszu ").", @@ -1068,11 +1003,6 @@ bool CreateGridcoinReward( GRC::Claim claim; claim.m_mining_id = researcher->Id(); - // Ensure that we sign claims with the legacy hash before block version 11: - if (blocknew.nVersion <= 10) { - claim.m_version = 1; - } - // If a researcher's beacon expired, generate the block as an investor. We // cannot sign a research claim without the beacon key, so this avoids the // issue that prevents a researcher from staking blocks if the beacon does @@ -1092,11 +1022,7 @@ bool CreateGridcoinReward( nReward += nFees; if (const GRC::CpidOption cpid = claim.m_mining_id.TryCpid()) { - CBlockIndex index; - index.nVersion = blocknew.nVersion; - index.nHeight = pindexPrev->nHeight + 1; - - claim.m_research_subsidy = GRC::Tally::GetAccrual(*cpid, blocknew.nTime, &index); + claim.m_research_subsidy = GRC::Tally::GetAccrual(*cpid, blocknew.nTime, pindexPrev); // If no pending research subsidy value exists, build an investor claim. // This avoids polluting the block index with non-research reward blocks @@ -1118,10 +1044,6 @@ bool CreateGridcoinReward( claim.m_client_version = FormatFullVersion().substr(0, GRC::Claim::MAX_VERSION_SIZE); claim.m_organization = GetArgument("org", "").substr(0, GRC::Claim::MAX_ORGANIZATION_SIZE); - if (blocknew.nVersion <= 10) { - claim.m_magnitude_unit = GRC::Tally::GetMagnitudeUnit(pindexPrev); - } - // Do a dry run for the claim signature to ensure that we can sign for a // researcher claim. We generate the final signature when signing all of // the block: @@ -1143,14 +1065,6 @@ bool CreateGridcoinReward( FormatMoney(claim.m_research_subsidy), FormatMoney(claim.m_block_subsidy)); - // Nodes that do not yet support block version 11 will parse the claim - // from the coinbase hashBoinc field. Set the previous block hash that - // old nodes check for research reward claims if necessary: - // - if (blocknew.nVersion <= 10 && claim.HasResearchReward()) { - claim.m_last_block_hash = blocknew.hashPrevBlock; - } - blocknew.vtx[0].vContracts.emplace_back(GRC::MakeContract( GRC::ContractAction::ADD, std::move(claim))); @@ -1345,14 +1259,6 @@ void StakeMiner(CWallet *pwallet) //clear miner messages g_miner_status.ClearReasonsNotStaking(); - - //New versions - if (IsV11Enabled(pindexPrev->nHeight + 1)) { - StakeBlock.nVersion = 11; - } else { - StakeBlock.nVersion = 10; - } - g_miner_status.Version = StakeBlock.nVersion; // This is needed due to early initialization of bitcoingui From 151568fb3849dfe6fd7f533125f9362b979e1c91 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Fri, 16 Oct 2020 21:56:36 -0500 Subject: [PATCH 16/53] Remove ability to serialize legacy version 1 claims This removes the Claim::m_last_block_hash field and Claim::ToString() method used to serialize claim objects in the delimited string format for blocks version 10 and below. --- src/gridcoin/claim.cpp | 41 ------------------ src/gridcoin/claim.h | 36 +++++----------- src/test/gridcoin/claim_tests.cpp | 71 ------------------------------- 3 files changed, 11 insertions(+), 137 deletions(-) diff --git a/src/gridcoin/claim.cpp b/src/gridcoin/claim.cpp index ea9c15e15f..f94267d601 100644 --- a/src/gridcoin/claim.cpp +++ b/src/gridcoin/claim.cpp @@ -236,44 +236,3 @@ uint256 Claim::GetHash() const return hasher.GetHash(); } - -std::string Claim::ToString(const int block_version) const -{ - constexpr char delim[] = "<|>"; - - const int subsidy_places = block_version < 8 ? 2 : 8; - - // Note: Commented-out items recorded to document removed fields: - // - return m_mining_id.ToString() - + delim // + mcpid.projectname - + delim // + mcpid.aesskein - + delim // + RoundToString(mcpid.rac, 0) - + delim // + RoundToString(mcpid.pobdifficulty, 5) - + delim // + RoundToString((double)mcpid.diffbytes, 0) - + delim // + mcpid.enccpid - + delim // + mcpid.encaes - + delim // + RoundToString(mcpid.nonce, 0) - + delim // + RoundToString(mcpid.NetworkRAC, 0) - + delim + m_client_version - + delim + RoundToString((double)m_research_subsidy / COIN, subsidy_places) - + delim // + std::to_string(m_last_payment_time) - + delim // + std::to_string(m_rsa_weight) - + delim // + mcpid.cpidv2 - + delim + std::to_string(m_magnitude) - + delim + m_quorum_address - + delim + BlockHashToString(m_last_block_hash) - + delim + RoundToString((double)m_block_subsidy / COIN, subsidy_places) - + delim + m_organization - + delim // + mcpid.OrganizationKey - + delim + m_quorum_hash.ToString() - + delim + (m_superblock->WellFormed() ? m_superblock->PackLegacy() : "") - + delim // + RoundToString(mcpid.ResearchSubsidy2,2) - + delim // + RoundToString(m_research_age, 6) - + delim + RoundToString(m_magnitude_unit, MAG_UNIT_PLACES) - + delim // + RoundToString(m_average_magnitude, 2) - + delim // + BlockHashToString(m_last_por_block_hash) - + delim // + mcpid.CurrentNeuralHash - + delim // + m_public_key.ToString() - + delim + EncodeBase64(m_signature.data(), m_signature.size()); -} diff --git a/src/gridcoin/claim.h b/src/gridcoin/claim.h index 2097153180..33354e3f1f 100644 --- a/src/gridcoin/claim.h +++ b/src/gridcoin/claim.h @@ -73,7 +73,7 @@ class Claim : public IContractPayload //! external CPID of the researcher. For this case, it must match a CPID //! advertised in a verified beacon. //! - MiningId m_mining_id; // MiningCPID::cpid + MiningId m_mining_id; //! //! \brief The version string of the wallet software running on the node @@ -86,7 +86,7 @@ class Claim : public IContractPayload //! Max length: 30 bytes. Blocks that contain a claim structure with a //! version field longer than 30 characters are rejected. //! - std::string m_client_version; // MiningCPID::clientversion + std::string m_client_version; //! //! \brief A user-customizable field that may contain any arbitrary data. @@ -99,7 +99,7 @@ class Claim : public IContractPayload //! Max length: 50 bytes. Blocks that contain a claim structure with an //! organization field longer than 50 characters are rejected. //! - std::string m_organization; // MiningCPID::Organization + std::string m_organization; //! //! \brief The value minted for generating the new block in units of @@ -114,21 +114,7 @@ class Claim : public IContractPayload //! incoming reward claims and can index those calculated values without //! this field. It can be considered informational. //! - int64_t m_block_subsidy; // MiningCPID::InterestSubsidy - - //! - //! \brief Hash of the block below the block containing this claim. - //! - //! Nodes check that this hash matches the hash of block that precedes the - //! block that contains the claim. This hash is signed along with the CPID - //! to prevent replay of the research reward subsidy. - //! - //! The significance of the last block is embedded into the claim signature - //! for researchers so we can consider this field informational. - //! - //! TODO: Remove this field after the switch to block version 11. - //! - uint256 m_last_block_hash; // MiningCPID::lastblockhash + int64_t m_block_subsidy; //! //! \brief The value of the research rewards claimed by the node in units @@ -141,7 +127,7 @@ class Claim : public IContractPayload //! incoming reward claims and can index those calculated values without //! this field. It can be considered informational. //! - int64_t m_research_subsidy; // MiningCPID::ResearchSubsidy + int64_t m_research_subsidy; //! //! \brief The researcher magnitude value from the superblock at the time @@ -154,14 +140,14 @@ class Claim : public IContractPayload //! //! Previous protocol versions used the magnitude in reward calculations. //! - uint16_t m_magnitude; // MiningCPID::Magnitude + uint16_t m_magnitude; //! //! \brief The magnitude ratio of the network at the time of the claim. //! //! Informational. //! - double m_magnitude_unit; // MiningCPID::ResearchMagnitudeUnit + double m_magnitude_unit; //! //! \brief Produced by signing the CPID and last block hash with a beacon @@ -170,7 +156,7 @@ class Claim : public IContractPayload //! Nodes verify this signature with the CPID's stored beacon key to prevent //! unauthorized claim or replay of the research reward subsidy. //! - std::vector m_signature; // MiningCPID::BoincSignature + std::vector m_signature; //! //! \brief Hash of the superblock to vote for. @@ -179,7 +165,7 @@ class Claim : public IContractPayload //! superblock contract by submitting in this field the contract hash of //! the pending superblock that the node caches locally. //! - QuorumHash m_quorum_hash; // MiningCPID::NeuralHash + QuorumHash m_quorum_hash; //! //! \brief The default wallet address of the node submitting the claim. @@ -188,7 +174,7 @@ class Claim : public IContractPayload //! owned by the node. It will determine whether a node may participate in //! the superblock quorum for a particular day. //! - std::string m_quorum_address; // MiningCPID::GRCAddress + std::string m_quorum_address; //! //! \brief The complete superblock data when the node submitting the claim @@ -197,7 +183,7 @@ class Claim : public IContractPayload //! Must be accompanied by a valid superblock hash in the \c m_quorum_hash //! field. //! - SuperblockPtr m_superblock; // MiningCPID::superblock + SuperblockPtr m_superblock; //! //! \brief Initialize an empty, invalid reward claim object. diff --git a/src/test/gridcoin/claim_tests.cpp b/src/test/gridcoin/claim_tests.cpp index 0c9ad39aef..b9892b2fcd 100644 --- a/src/test/gridcoin/claim_tests.cpp +++ b/src/test/gridcoin/claim_tests.cpp @@ -430,77 +430,6 @@ BOOST_AUTO_TEST_CASE(it_generates_a_hash_for_a_research_reward_claim) BOOST_CHECK(claim.GetHash() == hasher.GetHash()); } -BOOST_AUTO_TEST_CASE(it_represents_itself_as_a_legacy_boincblock_string) -{ - const GRC::Cpid cpid = GRC::Cpid::Parse("00010203040506070809101112131415"); - const std::string quorum_address = "mk8PmpcTGLCZky8YqFHEEwXs5px3hGfQBG"; - - const GRC::Superblock superblock = GetTestSuperblock(1); - - // Legacy claims only contain MD5 quorum hashes: - const GRC::QuorumHash quorum_hash(GRC::QuorumHash::Md5Sum { - 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, - 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 - }); - - const std::vector signature { - 0x7b, 0x85, 0xc8, 0x3c, 0x92, 0xd9, 0x74, 0x8e, - 0xa3, 0xd2, 0x26, 0x16, 0x6f, 0x9a, 0x00, 0x6c, - 0x6f, 0x0a, 0x97, 0x97, 0xa9, 0x3a, 0x52, 0xd0, - 0xb9, 0x4f, 0xbb, 0x29, 0x61, 0xbe, 0xd5, 0xcc, - }; - - const std::string sig64 = EncodeBase64(signature.data(), signature.size()); - - GRC::Claim claim; - - claim.m_mining_id = cpid; - claim.m_client_version = "v4.0.4.6-unk"; - claim.m_organization = "Example Org"; - claim.m_block_subsidy = 10.0 * COIN; - claim.m_research_subsidy = 47.24638888 * COIN; - claim.m_magnitude = 123; - claim.m_magnitude_unit = 0.123456; - claim.m_signature = signature; - claim.m_quorum_hash = quorum_hash; - claim.m_quorum_address = quorum_address; - claim.m_superblock.Replace(superblock); - - BOOST_CHECK(claim.ToString(8) == - cpid.ToString() + // Mining ID - "<|>" // Project name (obsolete) - "<|>" // AES Skein (obsolete) - "<|>" // Recent average credit (obsolete) - "<|>" // Proof-of-BOINC difficulty (obsolete) - "<|>" // Difficulty bytes (obsolete) - "<|>" // Encrypted CPID (obsolete) - "<|>" // For encrypted CPIDs? (obsolete) - "<|>" // Nonce (obsolete) - "<|>" // Network RAC (obsolete) - "<|>v4.0.4.6-unk" // Client version - "<|>47.24638888" // Research subsidy - "<|>" // Last payment time (obsolete) - "<|>" // RSA weight (obsolete) - "<|>" // CPID "v2" (obsolete) - "<|>123" // Magnitude - "<|>" + quorum_address + // Quorum address - "<|>0" // Last block hash (obsolete) - "<|>10.00000000" // Block subsidy - "<|>Example Org" // Organization - "<|>" // Organization key (obsolete) - "<|>" + quorum_hash.ToString() + // Neural hash - "<|>" + superblock.PackLegacy() +// Superblock - "<|>" // Research subsidy 2 (obsolete) - "<|>" // Research age (obsolete) - "<|>0.123456" // Magnitude unit - "<|>" // Average magnitude (obsolete) - "<|>" // Last PoR block hash (obsolete) - "<|>" // Current Neural hash (obsolete) - "<|>" // Public key (obsolete) - "<|>" + sig64 // Beacon signature - ); -} - BOOST_AUTO_TEST_CASE(it_serializes_to_a_stream_for_investor) { GRC::Claim claim = GetInvestorClaim(); From 1b82ef1d35fcc8e4c535613c7c4a405c68af4601 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Fri, 16 Oct 2020 21:56:40 -0500 Subject: [PATCH 17/53] Remove support for creating legacy version 1 superblocks This removes the ability to construct legacy superblocks from scraper statistics. We keep the Superblock::PackLegacy() function for tests. --- src/gridcoin/scraper/scraper.cpp | 56 +------------------------- src/gridcoin/superblock.cpp | 48 +--------------------- src/gridcoin/superblock.h | 13 +----- src/miner.cpp | 5 --- src/test/gridcoin/superblock_tests.cpp | 52 ------------------------ 5 files changed, 4 insertions(+), 170 deletions(-) diff --git a/src/gridcoin/scraper/scraper.cpp b/src/gridcoin/scraper/scraper.cpp index 685ca68313..b0cca5da00 100755 --- a/src/gridcoin/scraper/scraper.cpp +++ b/src/gridcoin/scraper/scraper.cpp @@ -5126,11 +5126,7 @@ Superblock ScraperGetSuperblockContract(bool bStoreConvergedStats, bool bContrac ConvergedScraperStatsCache.nTime = GetAdjustedTime(); ConvergedScraperStatsCache.Convergence = StructConvergedManifest; - if (IsV11Enabled(nBestHeight + 1)) { - superblock = Superblock::FromConvergence(ConvergedScraperStatsCache); - } else { - superblock = Superblock::FromConvergence(ConvergedScraperStatsCache, 1); - } + superblock = Superblock::FromConvergence(ConvergedScraperStatsCache); ConvergedScraperStatsCache.NewFormatSuperblock = superblock; @@ -5475,24 +5471,8 @@ UniValue testnewsb(const UniValue& params, bool fHelp) // Contract binary pack/unpack check... _log(logattribute::INFO, "testnewsb", "Checking compatibility with binary SB pack/unpack by packing then unpacking, then comparing to the original"); - std::string legacy_packed_contract; - { - LOCK(cs_ConvergedScraperStatsCache); - - legacy_packed_contract = ConvergedScraperStatsCache.NewFormatSuperblock.PackLegacy(); - uint64_t legacy_packed_size = legacy_packed_contract.size(); - - _log(logattribute::INFO, "testnewsb", "legacy packed size = " + std::to_string(legacy_packed_size)); - res.pushKV("legacy packed size", legacy_packed_size); - } - SuperblockPtr NewFormatSuperblock = SuperblockPtr::Empty(); - Superblock NewFormatSuperblock_out; - CDataStream ss(SER_NETWORK, 1); - uint64_t nNewFormatSuperblockSerSize; - uint64_t nNewFormatSuperblock_outSerSize; QuorumHash nNewFormatSuperblockHash; - QuorumHash nNewFormatSuperblock_outHash; uint32_t nNewFormatSuperblockReducedContentHashFromConvergenceHint; uint32_t nNewFormatSuperblockReducedContentHashFromUnderlyingManifestHint; @@ -5513,7 +5493,6 @@ UniValue testnewsb(const UniValue& params, bool fHelp) _log(logattribute::INFO, "testnewsb", "zero-mag count = " + std::to_string(NewFormatSuperblock->m_cpids.Zeros())); res.pushKV("zero-mag count", (uint64_t) NewFormatSuperblock->m_cpids.Zeros()); - nNewFormatSuperblockSerSize = GetSerializeSize(*NewFormatSuperblock, SER_NETWORK, 1); nNewFormatSuperblockHash = NewFormatSuperblock->GetHash(); _log(logattribute::INFO, "testnewsb", "NewFormatSuperblock.m_version = " + std::to_string(NewFormatSuperblock->m_version)); @@ -5522,44 +5501,11 @@ UniValue testnewsb(const UniValue& params, bool fHelp) nNewFormatSuperblockReducedContentHashFromConvergenceHint = NewFormatSuperblock->m_convergence_hint; nNewFormatSuperblockReducedContentHashFromUnderlyingManifestHint = NewFormatSuperblock->m_manifest_content_hint; - _log(logattribute::INFO, "testnewsb", "nNewFormatSuperblockSerSize = " + std::to_string(nNewFormatSuperblockSerSize)); - res.pushKV("nNewFormatSuperblockSerSize", nNewFormatSuperblockSerSize); - - ss << *NewFormatSuperblock; - ss >> NewFormatSuperblock_out; - - nNewFormatSuperblock_outSerSize = GetSerializeSize(NewFormatSuperblock_out, SER_NETWORK, 1); - nNewFormatSuperblock_outHash = NewFormatSuperblock_out.GetHash(); - - _log(logattribute::INFO, "testnewsb", "nNewFormatSuperblock_outSerSize = " + std::to_string(nNewFormatSuperblock_outSerSize)); - res.pushKV("nNewFormatSuperblock_outSerSize", nNewFormatSuperblock_outSerSize); - - if (NewFormatSuperblock->GetHash() == nNewFormatSuperblock_outHash) - { - _log(logattribute::INFO, "testnewsb", "NewFormatSuperblock serialization passed."); - res.pushKV("NewFormatSuperblock serialization", "passed"); - } - else - { - _log(logattribute::ERR, "testnewsb", "NewFormatSuperblock serialization FAILED."); - res.pushKV("NewFormatSuperblock serialization", "FAILED"); - } - - Superblock NewFormatSuperblockFromLegacy = Superblock::UnpackLegacy(legacy_packed_contract); - QuorumHash new_legacy_hash = QuorumHash::Hash(NewFormatSuperblockFromLegacy); - - res.pushKV("NewFormatSuperblockHash", nNewFormatSuperblockHash.ToString()); - _log(logattribute::INFO, "testnewsb", "NewFormatSuperblockHash = " + nNewFormatSuperblockHash.ToString()); - res.pushKV("new_legacy_hash", new_legacy_hash.ToString()); - _log(logattribute::INFO, "testnewsb", "new_legacy_hash = " + new_legacy_hash.ToString()); res.pushKV("nNewFormatSuperblockReducedContentHashFromConvergenceHint", (uint64_t) nNewFormatSuperblockReducedContentHashFromConvergenceHint); _log(logattribute::INFO, "testnewsb", "nNewFormatSuperblockReducedContentHashFromConvergenceHint = " + std::to_string(nNewFormatSuperblockReducedContentHashFromConvergenceHint)); res.pushKV("nNewFormatSuperblockReducedContentHashFromUnderlyingManifestHint", (uint64_t) nNewFormatSuperblockReducedContentHashFromUnderlyingManifestHint); _log(logattribute::INFO, "testnewsb", "nNewFormatSuperblockReducedContentHashFromUnderlyingManifestHint = " + std::to_string(nNewFormatSuperblockReducedContentHashFromUnderlyingManifestHint)); - _log(logattribute::INFO, "testnewsb", "NewFormatSuperblock legacy unpack number of zero mags = " + std::to_string(NewFormatSuperblock->m_cpids.Zeros())); - res.pushKV("NewFormatSuperblock legacy unpack number of zero mags", std::to_string(NewFormatSuperblock->m_cpids.Zeros())); - // Log the number of bits used to force key collisions. _log(logattribute::INFO, "testnewsb", "nReducedCacheBits = " + std::to_string(nReducedCacheBits)); res.pushKV("nReducedCacheBits", std::to_string(nReducedCacheBits)); diff --git a/src/gridcoin/superblock.cpp b/src/gridcoin/superblock.cpp index 95528f2736..2cf7f2f6b3 100644 --- a/src/gridcoin/superblock.cpp +++ b/src/gridcoin/superblock.cpp @@ -68,9 +68,9 @@ class ScraperStatsSuperblockBuilder continue; case statsobjecttype::byCPID: - m_superblock.m_cpids.RoundAndAdd( + m_superblock.m_cpids.Add( Cpid::Parse(object_id), - entry.second.statsvalue.dMag); + Magnitude::RoundFrom(entry.second.statsvalue.dMag)); break; @@ -226,18 +226,6 @@ class ScraperStatsQuorumHasher } } - //! - //! \brief Round and hash a CPID/magnitude pair as it would exist - //! in the Superblock::CpidIndex container. - //! - //! \param cpid The CPID value to hash. - //! \param magnitude The magnitude value to hash. - //! - void RoundAndAdd(Cpid cpid, double magnitude) - { - Add(cpid, Magnitude::RoundFrom(magnitude)); - } - //! //! \brief Hash a project statistics entry as it would exist in the //! Superblock::ProjectIndex container. @@ -580,15 +568,6 @@ Superblock Superblock::FromStats(const ScraperStatsAndVerifiedBeacons& stats_and Superblock superblock(version); ScraperStatsSuperblockBuilder builder(superblock); - if (version == 1) { - // Force the CPID index into legacy mode to capture zero-magnitude - // CPIDs that result from rounding. - // - // TODO: encapsulate this - // - superblock.m_cpids = Superblock::CpidIndex(0); - } - builder.BuildFromStats(stats_and_verified_beacons); return superblock; @@ -818,29 +797,6 @@ void Superblock::CpidIndex::Add(const Cpid cpid, const Magnitude magnitude) m_total_magnitude += magnitude.Scaled(); } -void Superblock::CpidIndex::RoundAndAdd(const Cpid cpid, const double magnitude) -{ - // The ScraperGetNeuralContract() function that these classes replace - // rounded magnitude values using a half-away-from-zero rounding mode - // to determine whether floating-point magnitudes round-down to zero, - // but it added the magnitude values to the superblock with half-even - // rounding. This caused legacy superblock contracts to contain CPIDs - // with zero magnitude when the rounding results differed. - // - // To create legacy superblocks from scraper statistics with matching - // hashes, we filter magnitudes using the same rounding rules: - // - if (m_legacy) { - if (std::round(magnitude) > 0) { - AddLegacy(cpid, std::nearbyint(magnitude)); - } else { - m_zero_magnitude_count++; - } - } else { - Add(cpid, Magnitude::RoundFrom(magnitude)); - } -} - void Superblock::CpidIndex::AddLegacy(const Cpid cpid, const uint16_t magnitude) { m_legacy_magnitudes.emplace_back(cpid, magnitude); diff --git a/src/gridcoin/superblock.h b/src/gridcoin/superblock.h index 13e9d39632..447e0ea435 100644 --- a/src/gridcoin/superblock.h +++ b/src/gridcoin/superblock.h @@ -827,15 +827,6 @@ class Superblock //! void AddLegacy(const Cpid cpid, const uint16_t magnitude); - //! - //! \brief Add the supplied mining ID to the index if it represents a - //! valid CPID after rounding the magnitude to an integer. - //! - //! \param cpid The CPID to add. - //! \param magnitude Total magnitude to associate with the CPID. - //! - void RoundAndAdd(const Cpid cpid, const double magnitude); - //! //! \brief Get a hash of the magnitude segments. //! @@ -1323,9 +1314,7 @@ class Superblock //! CONSENSUS: Although this method produces a legacy contract compatible //! with older protocols, it does not guarantee that the contract matches //! exactly to legacy input contract versions imported by UnpackLegacy(). - //! Use this method to produce new contracts from a superblock object. Do - //! not reproduce existing superblock contracts with this routine if they - //! will be retransmitted to other nodes. + //! We retain this method for unit tests only. //! //! \return Legacy superblock contract as a string of XML-like text data //! and binary-packed CPID/magnitude data. diff --git a/src/miner.cpp b/src/miner.cpp index 7ca8a8e5bc..c877c416ad 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -965,11 +965,6 @@ void AddSuperblockContractOrVote(CBlock& blocknew) return; } - if (GRC::Quorum::HasPendingSuperblock()) { - LogPrintf("AddSuperblockContractOrVote: Already pending."); - return; - } - GRC::Superblock superblock = GRC::Quorum::CreateSuperblock(); if (!superblock.WellFormed()) { diff --git a/src/test/gridcoin/superblock_tests.cpp b/src/test/gridcoin/superblock_tests.cpp index 513697c5fe..3e4a9e386f 100644 --- a/src/test/gridcoin/superblock_tests.cpp +++ b/src/test/gridcoin/superblock_tests.cpp @@ -1270,58 +1270,6 @@ BOOST_AUTO_TEST_CASE(it_adds_a_cpid_magnitude_to_the_index) BOOST_CHECK(cpids.size() == 1); } -BOOST_AUTO_TEST_CASE(it_adds_a_rounded_cpid_magnitude_to_the_index) -{ - GRC::Superblock::CpidIndex cpids; - - GRC::Cpid cpid1 = GRC::Cpid::Parse("00010203040506070809101112131415"); - GRC::Cpid cpid2 = GRC::Cpid::Parse("15141312111009080706050403020100"); - - cpids.RoundAndAdd(cpid1, 123.5); - cpids.RoundAndAdd(cpid2, 123.4); - - BOOST_CHECK(cpids.MagnitudeOf(cpid1) == 124); - BOOST_CHECK(cpids.MagnitudeOf(cpid2) == 123); -} - -BOOST_AUTO_TEST_CASE(it_adds_a_legacy_rounded_cpid_magnitude_to_the_index) -{ - // Initializing the CPID index with a count of zero-magnitude CPIDs - // switches it to legacy mode: - // - GRC::Superblock::CpidIndex cpids(0); - - GRC::Cpid cpid1 = GRC::Cpid::Parse("11111111111111111111111111111111"); - GRC::Cpid cpid2 = GRC::Cpid::Parse("22222222222222222222222222222222"); - GRC::Cpid cpid3 = GRC::Cpid::Parse("33333333333333333333333333333333"); - GRC::Cpid cpid4 = GRC::Cpid::Parse("44444444444444444444444444444444"); - - // The ScraperGetNeuralContract() function that these classes replace - // rounded magnitude values using a half-away-from-zero rounding mode - // to determine whether floating-point magnitudes round-down to zero, - // but it added the magnitude values to the superblock with half-even - // rounding. This caused legacy superblock contracts to contain CPIDs - // with zero magnitude when the rounding results differed. - // - // To create legacy superblocks from scraper statistics with matching - // hashes, we filter magnitudes using the same rounding rules: - // - // - A magnitude of 0.5 is rounded-down to zero. - // - A magnitude less than 0.5 is omitted from the superblock. - // - cpids.RoundAndAdd(cpid1, 1.1); - cpids.RoundAndAdd(cpid2, 1.5); - cpids.RoundAndAdd(cpid3, 0.5); - cpids.RoundAndAdd(cpid4, 0.4); - - BOOST_CHECK(cpids.size() == 3); // cpid4 is omitted - - BOOST_CHECK(cpids.MagnitudeOf(cpid1) == 1); - BOOST_CHECK(cpids.MagnitudeOf(cpid2) == 2); - BOOST_CHECK(cpids.MagnitudeOf(cpid3) == 0); - BOOST_CHECK(cpids.MagnitudeOf(cpid4) == 0); -} - BOOST_AUTO_TEST_CASE(it_fetches_a_cpid_pair_by_offset) { GRC::Superblock::CpidIndex cpids; From 5af01cd1249c9579a2b46af3d41943f046e0571c Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Fri, 16 Oct 2020 21:56:43 -0500 Subject: [PATCH 18/53] Remove ability to serialize legacy contracts This removes the ability to serialize version 1 contracts in the legacy, XML-like string format. --- src/gridcoin/contract/contract.cpp | 34 ++----------------- src/gridcoin/contract/contract.h | 15 --------- src/gridcoin/contract/message.cpp | 17 ---------- src/rpcblockchain.cpp | 14 -------- src/test/gridcoin/contract_tests.cpp | 49 ++++++++-------------------- 5 files changed, 17 insertions(+), 112 deletions(-) diff --git a/src/gridcoin/contract/contract.cpp b/src/gridcoin/contract/contract.cpp index fd454ad665..105e5f1eff 100644 --- a/src/gridcoin/contract/contract.cpp +++ b/src/gridcoin/contract/contract.cpp @@ -427,11 +427,10 @@ void GRC::ApplyContracts( // TODO: move this into the appropriate contract handler. // if (contract.m_type == ContractType::PROTOCOL) { - const ContractPayload payload = contract.m_body.AssumeLegacy(); - const std::string key = payload->LegacyKeyString(); + const auto payload = contract.SharePayloadAs(); - if (key == "REQUIRE_TEAM_WHITELIST_MEMBERSHIP" - || key == "TEAM_WHITELIST") + if (payload->m_key == "REQUIRE_TEAM_WHITELIST_MEMBERSHIP" + || payload->m_key == "TEAM_WHITELIST") { // Rescan in-memory project CPIDs to resolve a primary CPID // that fits the now active team requirement settings: @@ -749,20 +748,6 @@ uint256 Contract::GetHash() const payload.m_value.end()); } -std::string Contract::ToString() const -{ - if (m_type == ContractType::MESSAGE) { - return "" + m_body.m_payload->LegacyValueString() + ""; - } - - return "" + m_type.ToString() + "" - + "" + m_body.m_payload->LegacyKeyString() + "" - + "" + m_body.m_payload->LegacyValueString() + "" - + "" + m_action.ToString() + "" - + "" + m_public_key.ToString() + "" - + "" + m_signature.ToString() + ""; -} - void Contract::Log(const std::string& prefix) const { // TODO: temporary... needs better logging @@ -979,19 +964,6 @@ const std::vector& Contract::Signature::Raw() const return m_bytes; } -Contract Contract::ToLegacy() const -{ - return Contract( - 1, - m_type, - m_action, - ContractPayload::Make( - m_body.m_payload->LegacyKeyString(), - m_body.m_payload->LegacyValueString()), - m_signature, - m_public_key); -} - std::string Contract::Signature::ToString() const { if (m_bytes.empty()) { diff --git a/src/gridcoin/contract/contract.h b/src/gridcoin/contract/contract.h index 3868a97ffe..9f6b0ebf38 100644 --- a/src/gridcoin/contract/contract.h +++ b/src/gridcoin/contract/contract.h @@ -595,21 +595,6 @@ class Contract //! uint256 GetHash() const; - //! - //! \brief Get the string representation of the contract. - //! - //! \return The contract string in an XML-like format as published in a - //! transaction message. - //! - std::string ToString() const; - - //! - //! \brief Convert a contract to legacy format. - //! - //! \return A copy of the contract with a legacy key/value string payload. - //! - Contract ToLegacy() const; - //! //! \brief Write a message to the debug log with the contract data. //! diff --git a/src/gridcoin/contract/message.cpp b/src/gridcoin/contract/message.cpp index f8ea26ead4..3585528233 100644 --- a/src/gridcoin/contract/message.cpp +++ b/src/gridcoin/contract/message.cpp @@ -181,23 +181,6 @@ std::pair GRC::SendContract(CWalletTx wtx) return std::make_pair(std::move(wtx), "Transaction contains no contract."); } - // TODO: remove this after the v11 mandatory block. We don't need to sign - // version 2 contracts: - if (!IsV11Enabled(nBestHeight + 1)) { - Contract& contract = wtx.vContracts[0]; - contract = contract.ToLegacy(); - - if (contract.RequiresMessageKey() && !contract.SignWithMessageKey()) { - return std::make_pair( - std::move(wtx), - "Failed to sign contract with shared message key."); - } - - // Convert any binary contracts to the legacy string representation. - // - wtx.hashBoinc = contract.ToString(); - } - std::string error = SendContractTx(wtx); return std::make_pair(std::move(wtx), std::move(error)); diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index f68cbc80db..d6b7c42d95 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -1288,20 +1288,6 @@ UniValue addkey(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, "Not an admin contract type."); } - // TODO: remove this after the v11 mandatory block. We don't need to sign - // version 2 contracts (the signature is discarded after the threshold): - if (!IsV11Enabled(nBestHeight + 1)) { - contract = contract.ToLegacy(); - - if (!contract.Sign(key)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Failed to sign."); - } - - if (!contract.VerifySignature()) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Failed to verify signature."); - } - } - std::pair result = GRC::SendContract(contract); std::string error = result.second; diff --git a/src/test/gridcoin/contract_tests.cpp b/src/test/gridcoin/contract_tests.cpp index 88431b65c3..8edc35bd47 100644 --- a/src/test/gridcoin/contract_tests.cpp +++ b/src/test/gridcoin/contract_tests.cpp @@ -263,12 +263,15 @@ struct TestMessage //! static GRC::Contract V1() { - return GRC::MakeLegacyContract( - GRC::ContractType::BEACON, + GRC::Contract contract = GRC::MakeLegacyContract( + GRC::ContractType::PROJECT, GRC::ContractAction::ADD, "test", - "test") - .ToLegacy(); + "test"); + + contract.m_version = 1; + + return contract; } //! @@ -965,7 +968,7 @@ BOOST_AUTO_TEST_CASE(it_casts_known_contract_payloads) BOOST_AUTO_TEST_CASE(it_converts_known_legacy_contract_payloads) { - const GRC::Contract contract = TestMessage::Current().ToLegacy(); + const GRC::Contract contract = TestMessage::V1(); const auto payload = contract.SharePayloadAs(); BOOST_CHECK_EQUAL(payload->m_name, "test"); @@ -1068,7 +1071,7 @@ BOOST_AUTO_TEST_CASE(it_signs_a_legacy_v1_message_with_a_supplied_private_key) BOOST_CHECK(contract.Sign(private_key) == true); // Build the message body to hash to verify the new signature: - std::string body = "beacontesttest"; + std::string body = "projecttesttest"; uint256 hashed = Hash(body.begin(), body.end()); BOOST_CHECK(TestKey::Private().Verify(hashed, contract.m_signature.Raw())); @@ -1143,37 +1146,13 @@ BOOST_AUTO_TEST_CASE(it_generates_a_hash_of_a_contract_body) BOOST_AUTO_TEST_CASE(it_generates_a_hash_of_a_legacy_v1_contract_body) { GRC::Contract contract = TestMessage::V1(); + GRC::ContractPayload payload = contract.m_body.AssumeLegacy(); - BOOST_CHECK(contract.GetHash() == uint256S( - "484e6c63845cd102b86b75d1c0cb36dd15ae41f8ad00690cdddbdade666b41b6")); -} - -BOOST_AUTO_TEST_CASE(it_converts_itself_into_a_new_legacy_contract) -{ - const GRC::Contract contract = TestMessage::Current(); - const GRC::Contract legacy = contract.ToLegacy(); - - const auto payload = contract.SharePayloadAs(); - const GRC::ContractPayload legacy_payload = legacy.SharePayload(); - - BOOST_CHECK_EQUAL(legacy.m_version, 1); - - BOOST_CHECK(legacy.m_type == contract.m_type.Value()); - BOOST_CHECK(legacy.m_action == contract.m_action.Value()); - - BOOST_CHECK(legacy_payload->LegacyKeyString() == payload->m_name); - BOOST_CHECK(legacy_payload->LegacyValueString() == payload->m_url); - - BOOST_CHECK(legacy.m_signature.Raw() == contract.m_signature.Raw()); - BOOST_CHECK(legacy.m_public_key.Key() == contract.m_public_key.Key()); -} - -BOOST_AUTO_TEST_CASE(it_represents_itself_as_a_legacy_string) -{ - GRC::Contract contract = TestMessage::V1(); - contract.m_signature = TestSig::V1Bytes(); + std::string legacy = contract.m_type.ToString(); + legacy += payload->LegacyKeyString(); + legacy += payload->LegacyValueString(); - BOOST_CHECK(contract.ToString() == TestMessage::V1String()); + BOOST_CHECK(contract.GetHash() == Hash(legacy.begin(), legacy.end())); } BOOST_AUTO_TEST_CASE(it_serializes_to_a_stream) From 4ed6339dad49d0d5ad7909601b0f197b1461319b Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Fri, 16 Oct 2020 21:56:46 -0500 Subject: [PATCH 19/53] Remove transitions for version 2 beacons This removes transitional code for the renewal of beacons for the block version 11 hard fork including the grace period provision and UI alert. --- src/gridcoin/beacon.cpp | 26 +------------------ src/gridcoin/researcher.cpp | 21 ++------------- src/main.cpp | 6 ----- src/qt/forms/researcherwizardbeaconpage.ui | 17 ------------ src/qt/researcher/researchermodel.cpp | 16 +++--------- src/qt/researcher/researchermodel.h | 1 - .../researcher/researcherwizardbeaconpage.cpp | 5 ---- src/rpcblockchain.cpp | 24 ----------------- 8 files changed, 6 insertions(+), 110 deletions(-) diff --git a/src/gridcoin/beacon.cpp b/src/gridcoin/beacon.cpp index 2e58687dc3..d8c47a391a 100644 --- a/src/gridcoin/beacon.cpp +++ b/src/gridcoin/beacon.cpp @@ -16,7 +16,6 @@ using namespace GRC; using LogFlags = BCLog::LogFlags; extern int64_t g_v11_timestamp; -extern int64_t g_v11_legacy_beacon_days; namespace { BeaconRegistry g_beacons; @@ -147,7 +146,7 @@ bool Beacon::Expired(const int64_t now) const // hard-fork: // if (m_timestamp <= g_v11_timestamp) { - return now - g_v11_timestamp > g_v11_legacy_beacon_days * 86400; + return now - g_v11_timestamp > 14 * 86400; } return false; @@ -375,30 +374,7 @@ void BeaconRegistry::Delete(const ContractContext& ctx) bool BeaconRegistry::Validate(const Contract& contract, const CTransaction& tx) const { - // For legacy beacons, check that the unused parts contain non-empty values - // for compatibility with the existing protocol to prevent a fork. - // if (contract.m_version <= 1) { - // Only administrative contracts can delete legacy beacons. This is - // verified by master public key when checking the contract. - // - if (contract.m_action == ContractAction::REMOVE) { - return true; - } - - if (!contract.m_body.WellFormed(contract.m_action.Value())) { - return false; - } - - const ContractPayload payload = contract.m_body.AssumeLegacy(); - const std::string value = DecodeBase64(payload->LegacyValueString()); - const std::vector parts = split(value, ";"); - - if (parts.size() < 4) return false; - if (parts[0].empty()) return false; - if (parts[2].empty()) return false; - if (parts[3].empty()) return false; - return true; } diff --git a/src/gridcoin/researcher.cpp b/src/gridcoin/researcher.cpp index 4c5d39301e..57e86d6cd1 100644 --- a/src/gridcoin/researcher.cpp +++ b/src/gridcoin/researcher.cpp @@ -30,7 +30,6 @@ using namespace GRC; extern CCriticalSection cs_main; extern std::string msMiningErrors; -extern int64_t g_v11_timestamp; namespace { //! @@ -1089,16 +1088,6 @@ void Researcher::RunRenewBeaconJob() return; } - // Do not send a new beacon without manual action during the grace period - // for beacon readvertisement after block version 11. This prevents users - // from missing the steps needed to verify the new beacon: - // - if (const auto beacon_option = researcher->TryBeacon()) { - if (beacon_option->m_timestamp < g_v11_timestamp) { - return; - } - } - // Do not perform an automated renewal for participants with existing // beacons before a superblock is due. This avoids overwriting beacon // timestamps in the beacon registry in a way that causes the renewed @@ -1381,7 +1370,7 @@ AdvertiseBeaconResult Researcher::AdvertiseBeacon(const bool force) LOCK2(cs_main, pwalletMain->cs_wallet); const BeaconRegistry& beacons = GetBeaconRegistry(); - const BeaconOption current_beacon = beacons.Try(*cpid); + const BeaconOption current_beacon = beacons.TryActive(*cpid, GetAdjustedTime()); AdvertiseBeaconResult result(GRC::BeaconError::NONE); @@ -1393,13 +1382,7 @@ AdvertiseBeaconResult Researcher::AdvertiseBeacon(const bool force) } else if (!current_beacon) { result = SendNewBeacon(*cpid); } else { - // Temporary transition to version 2 beacons after the block version 11 - // threshold. Legacy beacons are not renewable: - if (current_beacon->m_timestamp <= g_v11_timestamp) { - result = SendNewBeacon(*cpid); - } else { - result = RenewBeacon(*cpid, *current_beacon); - } + result = RenewBeacon(*cpid, *current_beacon); } if (result.Error() == GRC::BeaconError::NONE) { diff --git a/src/main.cpp b/src/main.cpp index e595d5dec6..e4f8f72acc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -134,7 +134,6 @@ bool fUseFastIndex = false; // Temporary block version 11 transition helpers: int64_t g_v11_timestamp = 0; -int64_t g_v11_legacy_beacon_days = 14; // End of Gridcoin Global vars @@ -3406,11 +3405,6 @@ bool LoadBlockIndex(bool fAllowNew) nNewIndex2 = 36500; //1-24-2016 MAX_OUTBOUND_CONNECTIONS = (int)GetArg("-maxoutboundconnections", 8); - - // Temporary transition to version 2 beacons after the block version 11 - // hard-fork: - // - g_v11_legacy_beacon_days = 7; } LogPrintf("Mode=%s", fTestNet ? "TestNet" : "Prod"); diff --git a/src/qt/forms/researcherwizardbeaconpage.ui b/src/qt/forms/researcherwizardbeaconpage.ui index 60809c34eb..09c6d22cce 100644 --- a/src/qt/forms/researcherwizardbeaconpage.ui +++ b/src/qt/forms/researcherwizardbeaconpage.ui @@ -161,23 +161,6 @@ - - - - - 10 - 75 - true - - - - font-weight: bold; - - - All active beacon holders must send a new beacon for the protocol update. - - - diff --git a/src/qt/researcher/researchermodel.cpp b/src/qt/researcher/researchermodel.cpp index 7187f6adb2..4ba9785567 100644 --- a/src/qt/researcher/researchermodel.cpp +++ b/src/qt/researcher/researchermodel.cpp @@ -24,8 +24,6 @@ using namespace GRC; using LogFlags = BCLog::LogFlags; -extern int64_t g_v11_timestamp; - namespace { constexpr double SECONDS_IN_DAY = 24.0 * 60.0 * 60.0; constexpr int64_t BEACON_RENEWAL_WARNING_THRESHOLD = 15 * SECONDS_IN_DAY; @@ -180,7 +178,7 @@ void ResearcherModel::showWizard(WalletModel* wallet_model) wizard->setStartId(ResearcherWizard::PageInvestor); } else if (detectedPoolMode()) { wizard->setStartId(ResearcherWizard::PagePoolSummary); - } else if (hasRenewableBeacon() || needsV2BeaconUpgrade()) { + } else if (hasRenewableBeacon()) { wizard->setStartId(ResearcherWizard::PageBeacon); } else if (!actionNeeded()) { wizard->setStartId(ResearcherWizard::PageSummary); @@ -206,8 +204,7 @@ bool ResearcherModel::actionNeeded() const } if (hasEligibleProjects()) { - return (!hasActiveBeacon() && !hasPendingBeacon()) - || needsV2BeaconUpgrade(); + return !hasActiveBeacon() && !hasPendingBeacon(); } return !hasPoolProjects(); @@ -250,7 +247,7 @@ bool ResearcherModel::hasRAC() const bool ResearcherModel::needsBeaconAuth() const { - if (!hasPendingBeacon() || !IsV11Enabled(nBestHeight + 1)) { + if (!hasPendingBeacon()) { return false; } @@ -261,13 +258,6 @@ bool ResearcherModel::needsBeaconAuth() const return m_beacon->m_public_key != m_pending_beacon->m_public_key; } -bool ResearcherModel::needsV2BeaconUpgrade() const -{ - return m_beacon - && m_beacon->m_timestamp <= g_v11_timestamp - && (!m_pending_beacon || m_pending_beacon->m_timestamp <= g_v11_timestamp); -} - QString ResearcherModel::email() const { return QString::fromStdString(Researcher::Email()); diff --git a/src/qt/researcher/researchermodel.h b/src/qt/researcher/researchermodel.h index 4321fdd820..0b5de28ef9 100644 --- a/src/qt/researcher/researchermodel.h +++ b/src/qt/researcher/researchermodel.h @@ -92,7 +92,6 @@ class ResearcherModel : public QObject bool hasMagnitude() const; bool hasRAC() const; bool needsBeaconAuth() const; - bool needsV2BeaconUpgrade() const; QString email() const; QString formatCpid() const; diff --git a/src/qt/researcher/researcherwizardbeaconpage.cpp b/src/qt/researcher/researcherwizardbeaconpage.cpp index d1364d650e..739c704482 100644 --- a/src/qt/researcher/researcherwizardbeaconpage.cpp +++ b/src/qt/researcher/researcherwizardbeaconpage.cpp @@ -55,10 +55,6 @@ void ResearcherWizardBeaconPage::initializePage() bool ResearcherWizardBeaconPage::isComplete() const { - if (m_researcher_model->needsV2BeaconUpgrade()) { - return m_researcher_model->hasPendingBeacon(); - } - return m_researcher_model->hasActiveBeacon() || m_researcher_model->hasPendingBeacon(); } @@ -85,7 +81,6 @@ void ResearcherWizardBeaconPage::refresh() ui->cpidLabel->setText(m_researcher_model->formatCpid()); ui->sendBeaconButton->setVisible(isEnabled()); - ui->v2BeaconNoticeLabel->setVisible(m_researcher_model->needsV2BeaconUpgrade()); ui->continuePromptWrapper->setVisible(!isEnabled()); emit completeChanged(); diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index d6b7c42d95..bde50523d5 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -622,11 +622,6 @@ UniValue advertisebeacon(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - if (force && !IsV11Enabled(nBestHeight + 1)) { - throw JSONRPCError(RPC_INVALID_REQUEST, - "force not available until block " + std::to_string(Params().GetConsensus().BlockV11Height)); - } - GRC::AdvertiseBeaconResult result = GRC::Researcher::Get()->AdvertiseBeacon(force); if (auto public_key_option = result.TryPublicKey()) { @@ -698,11 +693,6 @@ UniValue revokebeacon(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - if (!IsV11Enabled(nBestHeight + 1)) { - throw JSONRPCError(RPC_INVALID_REQUEST, - "revokebeacon not available until block " + std::to_string(Params().GetConsensus().BlockV11Height)); - } - const GRC::AdvertiseBeaconResult result = GRC::Researcher::Get()->RevokeBeacon(*cpid); if (auto public_key_option = result.TryPublicKey()) { @@ -1255,20 +1245,6 @@ UniValue addkey(const UniValue& params, bool fHelp) GRC::Contract contract; switch (type.Value()) { - case GRC::ContractType::BEACON: { - const auto cpid_option = GRC::MiningId::Parse(params[2].get_str()).TryCpid(); - - if (!cpid_option) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid CPID."); - } - - contract = GRC::MakeContract( - action, - *cpid_option, - GRC::Beacon(ParseHex(params[3].get_str()))); - - break; - } case GRC::ContractType::PROJECT: contract = GRC::MakeContract( action, From aa4d8fe1bac81505670d9273a07da516e99132bc Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Fri, 16 Oct 2020 21:56:49 -0500 Subject: [PATCH 20/53] Remove ability to serialize legacy polls and votes This removes the ability to serialize version 1 poll and vote contracts in the legacy, XML-like string format. --- src/gridcoin/voting/builders.cpp | 60 -------------------------------- src/gridcoin/voting/payloads.h | 2 +- src/gridcoin/voting/poll.cpp | 42 ---------------------- src/gridcoin/voting/poll.h | 15 -------- src/gridcoin/voting/vote.cpp | 18 ---------- src/gridcoin/voting/vote.h | 9 +---- src/rpcvoting.cpp | 18 +++------- 7 files changed, 6 insertions(+), 158 deletions(-) diff --git a/src/gridcoin/voting/builders.cpp b/src/gridcoin/voting/builders.cpp index c86343f321..6cf9aaedad 100644 --- a/src/gridcoin/voting/builders.cpp +++ b/src/gridcoin/voting/builders.cpp @@ -833,58 +833,6 @@ void SelectFinalInputs(CWallet& wallet, CWalletTx& tx) tx.vin = std::move(mock_tx.vin); } - -//! -//! \brief Convert poll choice offsets into a string of labels for legacy votes. -//! -//! \param poll Supplies the choice labels for the legacy string. -//! \param vote Contains the responses to convert into the legacy string. -//! -//! \return A semicolon-delimited string of poll choice labels that match the -//! choices selected for the vote. -//! -std::string MakeLegacyResponsesString(const Poll& poll, const Vote& vote) -{ - std::string out; - auto offset_iter = vote.m_responses.begin(); - - if (offset_iter != vote.m_responses.end()) { - out += poll.Choices().At(*offset_iter)->m_label; - ++offset_iter; - } - - for (; offset_iter != vote.m_responses.end(); ++offset_iter) { - out += ";"; - out += poll.Choices().At(*offset_iter)->m_label; - ++offset_iter; - } - - return out; -} - -//! -//! \brief Convert a vote object into a legacy vote contract. -//! -//! \param wallet Supplies the voter's current GRC balance. -//! \param poll Supplies string elements for the legacy contract. -//! \param vote The vote to convert into a legacy vote contract. -//! -//! \return A contract object with a legacy vote payload for submission in a -//! transaction. -//! -Contract MakeLegacyVote(const CWallet& wallet, const Poll& poll, const Vote& vote) -{ - const ResearcherPtr researcher = Researcher::Get(); - const MiningId mining_id = researcher->Id(); - - return MakeContract( - ContractAction::ADD, - poll.m_title + ";" + DefaultWalletAddress() + ";" + mining_id.ToString(), - mining_id, - (wallet.GetBalance() + wallet.GetStake()) / COIN, - researcher->Magnitude().Floating(), - MakeLegacyResponsesString(poll, vote)); -} } // Anonymous namespace // ----------------------------------------------------------------------------- @@ -1270,14 +1218,6 @@ CWalletTx VoteBuilder::BuildContractTx(CWallet* const pwallet) CWalletTx tx; - // Unlike other contract types, legacy vote contracts cannot be transformed - // into the corresponding binary format in block version 11+: - // - if (!IsV11Enabled(nBestHeight + 1)) { - tx.vContracts.emplace_back(MakeLegacyVote(*pwallet, *m_poll, *m_vote)); - return tx; - } - const VoteClaimBuilder claim_builder(*pwallet, Researcher::Get()); claim_builder.BuildClaim(*m_vote, *m_poll); diff --git a/src/gridcoin/voting/payloads.h b/src/gridcoin/voting/payloads.h index 4c79c74928..dfaf921d74 100644 --- a/src/gridcoin/voting/payloads.h +++ b/src/gridcoin/voting/payloads.h @@ -126,7 +126,7 @@ class PollPayload : public IContractPayload //! std::string LegacyValueString() const override { - return m_poll.ToString(); + return std::string(); // Legacy serialization removed } //! diff --git a/src/gridcoin/voting/poll.cpp b/src/gridcoin/voting/poll.cpp index 026f7482f4..364b44dbcc 100644 --- a/src/gridcoin/voting/poll.cpp +++ b/src/gridcoin/voting/poll.cpp @@ -74,19 +74,6 @@ Poll::ChoiceList ParseChoices(const std::string& value) return choices; } -//! -//! \brief Format the poll expiration timestamp for a legacy poll contract. -//! -//! \param poll The poll object to generate the expiration timestamp for. -//! -//! \return The string representation of the timestamp in seconds at which the -//! poll expires suitable for the "" field of a legacy contract. -//! -std::string FormatLegacyExpiration(const Poll& poll) -{ - return std::to_string(poll.m_timestamp + (poll.m_duration_days * 86400)); -} - //! //! \brief Poll choices to return for polls with a yes/no/abstain response type. //! @@ -220,17 +207,6 @@ const Poll::ChoiceList& Poll::Choices() const return m_choices; } -std::string Poll::ToString() const -{ - return "" + m_title + "" - + "" + std::to_string(m_duration_days) + "" - + "" + m_question + "" - + "" + m_choices.ToString() + "" - + "" + std::to_string(m_weight_type.Raw()) + "" - + "" + m_url + "" - + "" + FormatLegacyExpiration(*this) + ""; -} - std::string Poll::WeightTypeToString() const { switch (m_weight_type.Value()) { @@ -329,21 +305,3 @@ void ChoiceList::Add(std::string label) { m_choices.emplace_back(std::move(label)); } - -std::string ChoiceList::ToString() const -{ - std::string out; - auto iter = m_choices.begin(); - - if (iter != m_choices.end()) { - out += iter->m_label; - ++iter; - } - - for (; iter != m_choices.end(); ++iter) { - out += ";"; - out += iter->m_label; - } - - return out; -} diff --git a/src/gridcoin/voting/poll.h b/src/gridcoin/voting/poll.h index 6e271f0973..4ed774f7a8 100644 --- a/src/gridcoin/voting/poll.h +++ b/src/gridcoin/voting/poll.h @@ -186,14 +186,6 @@ class Poll //! void Add(std::string label); - //! - //! \brief Get the legacy string representation of the choices for the - //! poll. - //! - //! \return The poll choice labels as a semicolon-delimited string. - //! - std::string ToString() const; - ADD_SERIALIZE_METHODS; template @@ -320,13 +312,6 @@ class Poll //! const ChoiceList& Choices() const; - //! - //! \brief Get the legacy string representation of a version 1 poll contract. - //! - //! \return Poll data in the legacy, XML-like string format. - //! - std::string ToString() const; - //! //! \brief Get the string representation of the poll's weight type. //! diff --git a/src/gridcoin/voting/vote.cpp b/src/gridcoin/voting/vote.cpp index 2b2bfe3c9b..51797a9b6b 100644 --- a/src/gridcoin/voting/vote.cpp +++ b/src/gridcoin/voting/vote.cpp @@ -83,21 +83,3 @@ LegacyVote::ParseResponses(const std::map& choice_map) con return responses; } - -std::string LegacyVote::ToString() const -{ - const auto round_to_string = [](const double value) { - return std::to_string(std::nearbyint(value)); - }; - - const std::vector parts = split(m_key, ";"); - const std::string title = parts.size() >= 1 ? parts[0] : ""; - const std::string address = parts.size() >= 2 ? parts[1] : ""; - - return "" + title + "" - + "" + m_responses + "" - + "" + m_mining_id.ToString() + "" - + "" + address + "" - + "" + round_to_string(m_amount) + "" - + "" + round_to_string(m_magnitude) + ""; -} diff --git a/src/gridcoin/voting/vote.h b/src/gridcoin/voting/vote.h index 71c8349d35..10d9773b10 100644 --- a/src/gridcoin/voting/vote.h +++ b/src/gridcoin/voting/vote.h @@ -268,16 +268,9 @@ class LegacyVote : public IContractPayload //! std::string LegacyValueString() const override { - return ToString(); + return std::string(); // Legacy serialization removed } - //! - //! \brief Get the string representation of a legacy vote. - //! - //! \return XML-like string of a vote contract for a legacy contract. - //! - std::string ToString() const; - //! //! \brief Get the burn fee amount required to send a particular contract. //! diff --git a/src/rpcvoting.cpp b/src/rpcvoting.cpp index 499e25567d..decd0fcea7 100644 --- a/src/rpcvoting.cpp +++ b/src/rpcvoting.cpp @@ -247,21 +247,11 @@ UniValue SubmitVote(const Poll& poll, VoteBuilder builder) UniValue responses(UniValue::VARR); - if (result_tx.nVersion >= 2) { - const auto& vote = payload.As(); + const auto& vote = payload.As(); - for (const auto& offset : vote.m_responses) { - if (const Poll::Choice* choice = poll.Choices().At(offset)) { - responses.push_back(choice->m_label); - } - } - } else { - const auto& vote = payload.As(); - - for (const auto& label : split(vote.m_responses, ";")) { - if (const auto offset_option = poll.Choices().OffsetOf(label)) { - responses.push_back(poll.Choices().At(*offset_option)->m_label); - } + for (const auto& offset : vote.m_responses) { + if (const Poll::Choice* choice = poll.Choices().At(offset)) { + responses.push_back(choice->m_label); } } From 983b3cd7a8917fa96187906117f3b665c0871ba2 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Fri, 16 Oct 2020 22:01:06 -0500 Subject: [PATCH 21/53] Remove now unused DefaultWalletAddress() function --- src/main.cpp | 48 ------------------------------------------------ src/main.h | 3 --- 2 files changed, 51 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e4f8f72acc..c46185c762 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -373,54 +373,6 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) return nEvicted; } - - -std::string DefaultWalletAddress() -{ - static std::string sDefaultWalletAddress; - if (!sDefaultWalletAddress.empty()) - return sDefaultWalletAddress; - - try - { - //Gridcoin - Find the default public GRC address (since a user may have many receiving addresses): - for (auto const& item : pwalletMain->mapAddressBook) - { - const CBitcoinAddress& address = item.first; - const std::string& strName = item.second; - isminetype fMine = IsMine(*pwalletMain, address.Get()); - if ((fMine != ISMINE_NO) && strName == "Default") - { - sDefaultWalletAddress=CBitcoinAddress(address).ToString(); - return sDefaultWalletAddress; - } - } - - //Can't Find - for (auto const& item : pwalletMain->mapAddressBook) - { - const CBitcoinAddress& address = item.first; - //const std::string& strName = item.second; - isminetype fMine = IsMine(*pwalletMain, address.Get()); - if (fMine != ISMINE_NO) - { - sDefaultWalletAddress=CBitcoinAddress(address).ToString(); - return sDefaultWalletAddress; - } - } - } - catch (std::exception& e) - { - return "ERROR"; - } - return "NA"; -} - - - - - - ////////////////////////////////////////////////////////////////////////////// // // CTransaction and CTxIndex diff --git a/src/main.h b/src/main.h index 0c8d0ac053..9cd44c327a 100644 --- a/src/main.h +++ b/src/main.h @@ -148,9 +148,6 @@ bool IsInitialBlockDownload(); std::string GetWarnings(std::string strFor); bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock); void ResendWalletTransactions(bool fForce = false); - -std::string DefaultWalletAddress(); - bool OutOfSyncByAge(); /** (try to) add transaction to memory pool **/ From 0a5a1ba84d5c7d9b7a9c9bf65dd7a26a468631d9 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Fri, 16 Oct 2020 22:01:08 -0500 Subject: [PATCH 22/53] Remove transitions for legacy fields in net messages This bumps the protocol version to disconnect any peers running versions lower than 5.0.0.0 and to enable peers to use the version message format cleaned-up for removal of legacy fields. It also removes the transitions for "command nonce" fields expected by pre-v5.0 nodes. --- src/main.cpp | 36 ++---------------------------------- src/net.cpp | 44 +++++++++++--------------------------------- src/version.h | 4 ++-- 3 files changed, 15 insertions(+), 69 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index c46185c762..0c8afe6e03 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4035,15 +4035,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CBlock block; block.ReadFromDisk((*mi).second); - // TODO: drop legacy "command nonce" removal transition in the next - // release after the mandatory version: - // - if (pfrom->nVersion >= PROTOCOL_VERSION) { - pfrom->PushMessage("encrypt", block); - } else { - std::string acid; - pfrom->PushMessage("encrypt", block, acid); - } + pfrom->PushMessage("encrypt", block); // Trigger them to send a getblocks request for the next batch of inventory if (inv.hash == pfrom->hashContinue) @@ -4269,14 +4261,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CBlock block; vRecv >> block; - // TODO: drop legacy "command nonce" removal transition in the next - // release after the mandatory version: - // - if (pfrom->nVersion < PROTOCOL_VERSION) { - std::string acid; - vRecv >> acid; - } - uint256 hashBlock = block.GetHash(true); LogPrintf(" Received block %s; ", hashBlock.ToString()); @@ -4353,14 +4337,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, uint64_t nonce = 0; vRecv >> nonce; - // TODO: drop legacy "command nonce" removal transition in the next - // release after the mandatory version: - // - if (pfrom->nVersion < PROTOCOL_VERSION) { - std::string acid; - vRecv >> acid; - } - // Echo the message back with the nonce. This allows for two useful features: // // 1) A remote node can quickly check if the connection is operational @@ -4653,15 +4629,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) pto->nPingUsecStart = GetTimeMicros(); pto->nPingNonceSent = nonce; - // TODO: drop legacy "command nonce" removal transition in the next - // release after the mandatory version: - // - if (pto->nVersion >= PROTOCOL_VERSION) { - pto->PushMessage("ping", nonce); - } else { - std::string acid; - pto->PushMessage("ping", nonce, acid); - } + pto->PushMessage("ping", nonce); } // Resend wallet transactions that haven't gotten in a block yet diff --git a/src/net.cpp b/src/net.cpp index 4bf65e8e32..dda8972cac 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -729,39 +729,17 @@ void CNode::PushVersion() LogPrint(BCLog::LogFlags::NOISY, "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%s", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), addr.ToString()); - // In the version following 180324 (mandatory v5.0.0 - Fern), we can finally - // drop the garbage legacy fields added to the version message: - // - if (PROTOCOL_VERSION > 180324) { - //TODO: change `PushMessage()` to use ServiceFlags so we don't need to cast nLocalServices - PushMessage( - "aries", - PROTOCOL_VERSION, - (uint64_t)nLocalServices, - nTime, - addrYou, - addrMe, - nLocalHostNonce, - FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector()), - nBestHeight); - } else { - const std::string legacy_dummy; - PushMessage( - "aries", - PROTOCOL_VERSION, - legacy_dummy, // nonce - legacy_dummy, // pw1 - legacy_dummy, // mycpid - legacy_dummy, // enccpid - legacy_dummy, // acid - (uint64_t)nLocalServices, - nTime, - addrYou, - addrMe, - nLocalHostNonce, - FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector()), - nBestHeight); - } + //TODO: change `PushMessage()` to use ServiceFlags so we don't need to cast nLocalServices + PushMessage( + "aries", + PROTOCOL_VERSION, + (uint64_t)nLocalServices, + nTime, + addrYou, + addrMe, + nLocalHostNonce, + FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector()), + nBestHeight); } bool CNode::Misbehaving(int howmuch) diff --git a/src/version.h b/src/version.h index 280243dfa2..0bc3899fde 100644 --- a/src/version.h +++ b/src/version.h @@ -43,9 +43,9 @@ std::string FormatSubVersion(const std::string& name, int nClientVersion, const /////////////////////////////////////////////////////////// // network protocol versioning // // // -static const int PROTOCOL_VERSION = 180324; // +static const int PROTOCOL_VERSION = 180325; // // disconnect from peers older than this proto version // -static const int MIN_PEER_PROTO_VERSION = 180323; // +static const int MIN_PEER_PROTO_VERSION = 180324; // /////////////////////////////////////////////////////////// // initial proto version, to be increased after // // version/verack negotiation // From a54f184b47f562cbd1f18ce33250aa3d3d8af09c Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Fri, 16 Oct 2020 22:01:10 -0500 Subject: [PATCH 23/53] Remove legacy contract signature handling Version 1 contracts signed payloads with a pointless shared key, but removing this validation before the block version 11 hard-fork could disrupt consensus. Public contracts need no signature now. Administrative contracts use a comparison of the master key address for validation. Legacy blocks with administrative contracts must be protected by checkpoints. This trade-off allows us to remove a boat load of code for the validation and parsing of legacy contract signatures that we didn't need in the first place. --- src/gridcoin/contract/contract.cpp | 300 +--------------- src/gridcoin/contract/contract.h | 225 +----------- src/gridcoin/project.h | 2 +- src/main.cpp | 2 +- src/rpcrawtransaction.cpp | 3 - src/test/gridcoin/contract_tests.cpp | 517 +-------------------------- 6 files changed, 22 insertions(+), 1027 deletions(-) diff --git a/src/gridcoin/contract/contract.cpp b/src/gridcoin/contract/contract.cpp index 105e5f1eff..f14e37011b 100644 --- a/src/gridcoin/contract/contract.cpp +++ b/src/gridcoin/contract/contract.cpp @@ -417,8 +417,8 @@ void GRC::ApplyContracts( bool& out_found_contract) { for (const auto& contract : tx.GetContracts()) { - // V2 contract signatures are checked upon receipt: - if (contract.m_version == 1 && !contract.Validate()) { + // V2 contracts are checked upon receipt: + if (contract.m_version == 1 && !contract.WellFormed()) { continue; } @@ -460,8 +460,8 @@ void GRC::RevertContracts(const CTransaction& tx, const CBlockIndex* const pinde { // Reverse the contracts. Reorganize will load any previous versions: for (const auto& contract : tx.GetContracts()) { - // V2 contract signatures are checked upon receipt: - if (contract.m_version == 1 && !contract.VerifySignature()) { + // V2 contracts are checked upon receipt: + if (contract.m_version == 1 && !contract.WellFormed()) { continue; } @@ -480,8 +480,6 @@ Contract::Contract() , m_type(ContractType::UNKNOWN) , m_action(ContractAction::UNKNOWN) , m_body() - , m_signature() - , m_public_key() { } @@ -493,90 +491,19 @@ Contract::Contract( , m_type(type) , m_action(action) , m_body(std::move(body)) - , m_signature() - , m_public_key() { } Contract::Contract( - int version, + uint32_t version, Contract::Type type, Contract::Action action, - Contract::Body body, - Contract::Signature signature, - Contract::PublicKey public_key) + Contract::Body body) : m_version(version) , m_type(type) , m_action(action) , m_body(std::move(body)) - , m_signature(std::move(signature)) - , m_public_key(std::move(public_key)) -{ -} - -const CPubKey& Contract::MessagePublicKey() { - // If the message key changes, add a conditional entry to this method that - // returns the new key for the appropriate height. - - // 044b2938fbc38071f24bede21e838a0758a52a0085f2e034e7f971df445436a25 - // 2467f692ec9c5ba7e5eaa898ab99cbd9949496f7e3cafbf56304b1cc2e5bdf06e - static const CPubKey since_block_0 ({ - 0x04, 0x4b, 0x29, 0x38, 0xfb, 0xc3, 0x80, 0x71, 0xf2, 0x4b, 0xed, - 0xe2, 0x1e, 0x83, 0x8a, 0x07, 0x58, 0xa5, 0x2a, 0x00, 0x85, 0xf2, - 0xe0, 0x34, 0xe7, 0xf9, 0x71, 0xdf, 0x44, 0x54, 0x36, 0xa2, 0x52, - 0x46, 0x7f, 0x69, 0x2e, 0xc9, 0xc5, 0xba, 0x7e, 0x5e, 0xaa, 0x89, - 0x8a, 0xb9, 0x9c, 0xbd, 0x99, 0x49, 0x49, 0x6f, 0x7e, 0x3c, 0xaf, - 0xbf, 0x56, 0x30, 0x4b, 0x1c, 0xc2, 0xe5, 0xbd, 0xf0, 0x6e - }); - - return since_block_0; -} - -const CPrivKey& Contract::MessagePrivateKey() -{ - // If the message key changes, add a conditional entry to this method that - // returns the new key for the appropriate height. - - // 308201130201010420fbd45ffb02ff05a3322c0d77e1e7aea264866c24e81e5ab - // 6a8e150666b4dc6d8a081a53081a2020101302c06072a8648ce3d0101022100ff - // fffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300 - // 604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28 - // d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a685541 - // 99c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af - // 48a03bbfd25e8cd0364141020101a144034200044b2938fbc38071f24bede21e8 - // 38a0758a52a0085f2e034e7f971df445436a252467f692ec9c5ba7e5eaa898ab9 - // 9cbd9949496f7e3cafbf56304b1cc2e5bdf06e - static const CPrivKey since_block_0 { - 0x30, 0x82, 0x01, 0x13, 0x02, 0x01, 0x01, 0x04, 0x20, 0xfb, 0xd4, - 0x5f, 0xfb, 0x02, 0xff, 0x05, 0xa3, 0x32, 0x2c, 0x0d, 0x77, 0xe1, - 0xe7, 0xae, 0xa2, 0x64, 0x86, 0x6c, 0x24, 0xe8, 0x1e, 0x5a, 0xb6, - 0xa8, 0xe1, 0x50, 0x66, 0x6b, 0x4d, 0xc6, 0xd8, 0xa0, 0x81, 0xa5, - 0x30, 0x81, 0xa2, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, - 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x30, 0x06, 0x04, - 0x01, 0x00, 0x04, 0x01, 0x07, 0x04, 0x41, 0x04, 0x79, 0xbe, 0x66, - 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, - 0x0b, 0x07, 0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59, - 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98, 0x48, 0x3a, 0xda, 0x77, - 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, - 0xa8, 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, - 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8, 0x02, 0x21, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, - 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41, 0x02, 0x01, 0x01, - 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x4b, 0x29, 0x38, 0xfb, 0xc3, - 0x80, 0x71, 0xf2, 0x4b, 0xed, 0xe2, 0x1e, 0x83, 0x8a, 0x07, 0x58, - 0xa5, 0x2a, 0x00, 0x85, 0xf2, 0xe0, 0x34, 0xe7, 0xf9, 0x71, 0xdf, - 0x44, 0x54, 0x36, 0xa2, 0x52, 0x46, 0x7f, 0x69, 0x2e, 0xc9, 0xc5, - 0xba, 0x7e, 0x5e, 0xaa, 0x89, 0x8a, 0xb9, 0x9c, 0xbd, 0x99, 0x49, - 0x49, 0x6f, 0x7e, 0x3c, 0xaf, 0xbf, 0x56, 0x30, 0x4b, 0x1c, 0xc2, - 0xe5, 0xbd, 0xf0, 0x6e - }; - - return since_block_0; } bool Contract::Detect(const std::string& message) @@ -599,13 +526,7 @@ Contract Contract::Parse(const std::string& message) Contract::Action::Parse(ExtractXML(message, "", "")), Contract::Body(ContractPayload::Make( ExtractXML(message, "", ""), - ExtractXML(message, "", ""))), - Contract::Signature::Parse(ExtractXML(message, "", "")), - // None of the currently-valid contract types support signing with a - // user-supplied private key, so we can skip parsing the public keys - // altogether. We verify contracts with the master and message keys: - //Contract::PublicKey::Parse(ExtractXML(message, "", "")), - Contract::PublicKey()); + ExtractXML(message, "", "")))); } bool Contract::RequiresMasterKey() const @@ -625,34 +546,6 @@ bool Contract::RequiresMasterKey() const } } -bool Contract::RequiresMessageKey() const -{ - switch (m_type.Value()) { - case ContractType::BEACON: return m_action == ContractAction::ADD; - case ContractType::POLL: return m_action == ContractAction::ADD; - case ContractType::VOTE: return m_action == ContractAction::ADD; - default: return false; - } -} - -bool Contract::RequiresSpecialKey() const -{ - return RequiresMessageKey() || RequiresMasterKey(); -} - -const CPubKey& Contract::ResolvePublicKey() const -{ - if (RequiresMessageKey()) { - return MessagePublicKey(); - } - - if (RequiresMasterKey()) { - return CWallet::MasterPublicKey(); - } - - return m_public_key.Key(); -} - int64_t Contract::RequiredBurnAmount() const { return m_body.m_payload->RequiredBurnAmount(); @@ -663,19 +556,7 @@ bool Contract::WellFormed() const return m_version > 0 && m_version <= Contract::CURRENT_VERSION && m_type != ContractType::UNKNOWN && m_action != ContractAction::UNKNOWN - && m_body.WellFormed(m_action.Value()) - // Version 2+ contracts rely on the signatures in the transactions - // instead of embedding another signature in the contract: - && (m_version > 1 || m_signature.Viable()) - && (m_version > 1 || (RequiresSpecialKey() || m_public_key.Viable())); -} - -bool Contract::Validate() const -{ - return WellFormed() - // Version 2+ contracts rely on the signatures in the transactions - // instead of embedding another signature in the contract: - && (m_version > 1 || VerifySignature()); + && m_body.WellFormed(m_action.Value()); } ContractPayload Contract::SharePayload() const @@ -687,80 +568,17 @@ ContractPayload Contract::SharePayload() const return m_body.ConvertFromLegacy(m_type.Value()); } -bool Contract::Sign(CKey& private_key) -{ - std::vector output; - - if (!private_key.Sign(GetHash(), output)) { - Log("ERROR: Failed to sign contract"); - return false; - } - - m_signature = std::move(output); - - if (!RequiresSpecialKey()) { - m_public_key = private_key.GetPubKey(); - } - - return true; -} - -bool Contract::SignWithMessageKey() -{ - CKey key; - - key.SetPrivKey(MessagePrivateKey()); - - return Sign(key); -} - -bool Contract::VerifySignature() const -{ - CKey key; - - if (!key.SetPubKey(ResolvePublicKey())) { - Log("ERROR: Failed to set contract public key"); - return false; - } - - return key.Verify(GetHash(), m_signature.Raw()); -} - -uint256 Contract::GetHash() const -{ - if (m_version > 1) { - return SerializeHash(*this); - } - - const std::string type_string = m_type.ToString(); - - // We use static_cast here instead of dynamic_cast to avoid the lookup. The - // value of m_payload is guaranteed to be a LegacyPayload for v1 contracts. - // - const auto& payload = static_cast(*m_body.m_payload); - - return Hash( - type_string.begin(), - type_string.end(), - payload.m_key.begin(), - payload.m_key.end(), - payload.m_value.begin(), - payload.m_value.end()); -} - void Contract::Log(const std::string& prefix) const { // TODO: temporary... needs better logging LogPrint(BCLog::LogFlags::CONTRACT, - ": %s: v%d, %s, %s, %s, %s, %s, %s", + ": %s: v%d, %s, %s, %s, %s", prefix, m_version, m_type.ToString(), m_action.ToString(), m_body.m_payload->LegacyKeyString(), - m_body.m_payload->LegacyValueString(), - m_public_key.ToString(), - m_signature.ToString()); + m_body.m_payload->LegacyValueString()); } // ----------------------------------------------------------------------------- @@ -922,104 +740,6 @@ void Contract::Body::ResetType(const ContractType type) } } -// ----------------------------------------------------------------------------- -// Class: Contract::Signature -// ----------------------------------------------------------------------------- - -Contract::Signature::Signature() : m_bytes() -{ -} - -Contract::Signature::Signature(std::vector bytes) - : m_bytes(std::move(bytes)) -{ -} - -Contract::Signature Contract::Signature::Parse(const std::string& input) -{ - if (input.empty()) { - return Contract::Signature(); - } - - bool invalid; - std::vector decoded = DecodeBase64(input.c_str(), &invalid); - - if (invalid) { - return Contract::Signature(); - } - - return Contract::Signature(std::move(decoded)); -} - -bool Contract::Signature::Viable() const -{ - // The DER-encoded ASN.1 ECDSA signatures typically contain 70 or 71 bytes, - // but may hold up to 73. Sizes as low as 68 bytes seen on mainnet. We only - // check the number of bytes here as an early step: - return m_bytes.size() >= 64 && m_bytes.size() <= 73; -} - -const std::vector& Contract::Signature::Raw() const -{ - return m_bytes; -} - -std::string Contract::Signature::ToString() const -{ - if (m_bytes.empty()) { - return std::string(); - } - - return EncodeBase64(m_bytes.data(), m_bytes.size()); -} - -// ----------------------------------------------------------------------------- -// Class: Contract::PublicKey -// ----------------------------------------------------------------------------- - -Contract::PublicKey::PublicKey() : m_key() -{ -} - -Contract::PublicKey::PublicKey(CPubKey key) - : m_key(std::move(key)) -{ -} - -Contract::PublicKey Contract::PublicKey::Parse(const std::string& input) -{ - if (input.empty()) { - return Contract::PublicKey(); - } - - return Contract::PublicKey(CPubKey(ParseHex(input))); -} - -bool Contract::PublicKey::operator==(const CPubKey& other) const -{ - return m_key == other; -} - -bool Contract::PublicKey::operator!=(const CPubKey& other) const -{ - return m_key != other; -} - -bool Contract::PublicKey::Viable() const -{ - return m_key.IsValid(); -} - -const CPubKey& Contract::PublicKey::Key() const -{ - return m_key; -} - -std::string Contract::PublicKey::ToString() const -{ - return HexStr(m_key.Raw()); -} - // ----------------------------------------------------------------------------- // Abstract Class: IContractHandler // ----------------------------------------------------------------------------- diff --git a/src/gridcoin/contract/contract.h b/src/gridcoin/contract/contract.h index 9f6b0ebf38..aa7c4144ef 100644 --- a/src/gridcoin/contract/contract.h +++ b/src/gridcoin/contract/contract.h @@ -4,7 +4,6 @@ #pragma once -#include "key.h" #include "gridcoin/contract/payload.h" #include "gridcoin/support/enumbytes.h" #include "serialize.h" @@ -50,7 +49,10 @@ class Contract //! \brief The amount of coin set for a burn output in a transaction that //! broadcasts a contract in units of 1/100000000 GRC. //! - static constexpr int64_t STANDARD_BURN_AMOUNT = 0.5 * COIN; + // TODO: remove redefinition of the COIN constant when porting amount.h + // from Bitcoin: + // + static constexpr int64_t STANDARD_BURN_AMOUNT = 0.5 * 100000000; //! //! \brief A contract type from a transaction message. @@ -211,129 +213,6 @@ class Contract void ResetType(const ContractType type); }; // Contract::Body - //! - //! \brief Parses and stores a contract message signature in binary format. - //! - struct Signature - { - //! - //! \brief Initialize an empty, invalid \c Signature object. - //! - Signature(); - - //! - //! \brief Initialize a \c Signature object from a series of bytes. - //! - //! \param bytes As DER-encoded ASN.1 ECDSA. - //! - Signature(std::vector bytes); - - //! - //! \brief Create a \c Signature object from its string representation. - //! - //! \param input Base64 encoding of the binary signature. Typically - //! 96 characters. - //! - static Signature Parse(const std::string& input); - - //! - //! \brief Determine whether the object contains a viable signature. - //! - //! This method does NOT verify the signature against a public key. Use - //! only for early checks to determine whether to continue verification. - //! - //! \return \c true if resembles a DER-encoded ASN.1 ECDSA signature. - //! - bool Viable() const; - - //! - //! \brief Get the bytes in the signature. - //! - //! \return Typically 70 to 72 bytes. - //! - const std::vector& Raw() const; - - //! - //! \brief Get the string representation of the signature. - //! - //! \return Base64 encoding of the binary signature. - //! - std::string ToString() const; - - private: - std::vector m_bytes; //!< As DER-encoded ASN.1 ECDSA. - }; // Contract::Signature - - //! - //! \brief Parses and stores the contract public key in binary format. - //! - struct PublicKey - { - //! - //! \brief Initialize an empty, invalid \c PublicKey object. - //! - PublicKey(); - - //! - //! \brief Wrap a \c PublicKey object around a \c CPubKey instance. - //! - //! \param key The public key to wrap. - //! - PublicKey(CPubKey key); - - //! - //! \brief Create a \c PublicKey object from its string representation. - //! - //! \param input Hex string representation of the bytes in the key. - //! - static PublicKey Parse(const std::string& input); - - //! - //! \brief Compare a supplied \CPubKey object for equality. - //! - //! \param other A public key to check equality for. - //! - //! \return \c true if the supplied public key's bytes match. - //! - bool operator==(const CPubKey& other) const; - - //! - //! \brief Compare a supplied \CPubKey object for inequality. - //! - //! \param other A public key to check inequality for. - //! - //! \return \c true if the supplied public key's bytes do not match. - //! - bool operator!=(const CPubKey& other) const; - - //! - //! \brief Determine whether the object contains a viable public key. - //! - //! This method does NOT verify the key's structure. Use only for early - //! checks to determine whether to continue verification. - //! - //! \return \true if resembles a full or compressed public key. - //! - bool Viable() const; - - //! - //! \brief Get the wrapped \c CPubKey object. - //! - //! \return A reference to the wrapped key object. - //! - const CPubKey& Key() const; - - //! - //! \brief Get the string representation of the public key. - //! - //! \return Hex string representation of the bytes in the key. - //! - std::string ToString() const; - - private: - CPubKey m_key; //!< The wrapped public key. - }; // Contract::PublicKey - //! //! \brief Version number of the serialized contract format. //! @@ -352,8 +231,6 @@ class Contract Type m_type; //!< Determines how to handle the contract. Action m_action; //!< Action to perform with the contract. Body m_body; //!< Payload specific to the contract type. - Signature m_signature; //!< Proves authenticity of the contract. - PublicKey m_public_key; //!< Verifies the contract signature. //! //! \brief Initialize an empty \c Contract object. @@ -380,38 +257,14 @@ class Contract //! \param type Contract type parsed from the transaction message. //! \param action Contract action parsed from the transaction message. //! \param body The body payload of the contract. - //! \param signature Proves authenticity of the contract message. - //! \param public_key Optional for some types. Verifies the signature. //! - Contract( - int version, - Type type, - Action action, - Body body, - Signature signature, - PublicKey public_key); - - //! - //! \brief Get the message public key used to verify public contracts. - //! - //! \return A \c CPubKey object containing the message public key. - //! - static const CPubKey& MessagePublicKey(); - - //! - //! \brief Get the message private key used to sign public contracts. - //! - //! The private key is revealed by design, for public messages only. - //! - //! \return The message private key as a secure vector of bytes. - //! - static const CPrivKey& MessagePrivateKey(); + Contract(uint32_t version, Type type, Action action, Body body); //! //! \brief Determine whether the supplied message might contain a contract. //! - //! Call \c Contract::WellFormed() or \c Contract::VerifySignature() to - //! check whether a contract is actually viable. + //! Call \c Contract::WellFormed() to check whether a contract is actually + //! viable. //! //! \param message A message as it exists in a transaction. //! @@ -436,29 +289,6 @@ class Contract //! bool RequiresMasterKey() const; - //! - //! \brief Determine whether the contract shall sign the message or verify - //! the signature using the embedded, shared message keys. - //! - //! \return \c true for certain public actions (add poll, vote, beacon...). - //! - bool RequiresMessageKey() const; - - //! - //! \brief Determine whether the contract shall sign the message or verify - //! the signature using a special (non-user-supplied) key. - //! - //! \return \c true when a contract requires the master or message keys. - //! - bool RequiresSpecialKey() const; - - //! - //! \brief Get the public key used to verify the contract's signature. - //! - //! \return The appropriate public key for the contract type. - //! - const CPubKey& ResolvePublicKey() const; - //! //! \brief Get the burn fee amount required to send a particular contract. //! @@ -478,14 +308,6 @@ class Contract //! bool WellFormed() const; - //! - //! \brief Determine whether a received contract is completely valid. - //! - //! \return \c true if the contract is well-formed and contains a valid - //! signature. - //! - bool Validate() const; - //! //! \brief Get the wrapped contract payload object. //! @@ -562,39 +384,6 @@ class Contract return std::move(static_cast(*SharePayload()));; } - //! - //! \brief Sign the contract using the provided private key. - //! - //! \param private_key The key to sign the message with. - //! - //! \return \c true if the signature was successfully created. - //! - bool Sign(CKey& private_key); - - //! - //! \brief Sign the contract using the shared message private key. - //! - //! \return \c true if the signature was successfully created. - //! - bool SignWithMessageKey(); - - //! - //! \brief Validate the integrity and authenticity of the contract message - //! by verifying its digital signature. - //! - //! \return \c true if the signature validates the contract's claims. - //! - bool VerifySignature() const; - - //! - //! \brief Generate a hash of the contract data as the input to create or - //! verify the contract signature. - //! - //! \return Hash of the contract type, key, and value. Versions 2+ also - //! include the action. - //! - uint256 GetHash() const; - //! //! \brief Write a message to the debug log with the contract data. //! diff --git a/src/gridcoin/project.h b/src/gridcoin/project.h index eade659c5e..ffd6d76688 100644 --- a/src/gridcoin/project.h +++ b/src/gridcoin/project.h @@ -122,7 +122,7 @@ class Project : public IContractPayload //! int64_t RequiredBurnAmount() const override { - return 0.5 * COIN; // TODO: reduce fee for admin contracts? + return Contract::STANDARD_BURN_AMOUNT; } //! diff --git a/src/main.cpp b/src/main.cpp index 0c8afe6e03..65a6812cbc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -707,7 +707,7 @@ bool CTransaction::CheckContracts(const MapPrevTx& inputs) const return DoS(100, error("%s: legacy contract", __func__)); } - if (!contract.Validate()) { + if (!contract.WellFormed()) { return DoS(100, error("%s: malformed contract", __func__)); } diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index ab5d3055d8..ba6a51f8d3 100755 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -267,9 +267,6 @@ UniValue ContractToJson(const GRC::Contract& contract) break; } - out.pushKV("public_key", contract.m_public_key.ToString()); - out.pushKV("signature", contract.m_signature.ToString()); - return out; } diff --git a/src/test/gridcoin/contract_tests.cpp b/src/test/gridcoin/contract_tests.cpp index 8edc35bd47..ed8eb705d2 100644 --- a/src/test/gridcoin/contract_tests.cpp +++ b/src/test/gridcoin/contract_tests.cpp @@ -60,86 +60,6 @@ class TestPayload : public GRC::IContractPayload } }; // TestPayload -//! -//! \brief Provides various public and private key representations for tests. -//! -//! Keys match the shared message keys embedded in the application. -//! -struct TestKey -{ - //! - //! \brief Create a valid private key for tests. - //! - //! \return This is actually the shared message private key. - //! - static CKey Private() - { - std::vector private_key = ParseHex( - "308201130201010420fbd45ffb02ff05a3322c0d77e1e7aea264866c24e81e5ab6" - "a8e150666b4dc6d8a081a53081a2020101302c06072a8648ce3d0101022100ffff" - "fffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604" - "010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959" - "f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47" - "d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03b" - "bfd25e8cd0364141020101a144034200044b2938fbc38071f24bede21e838a0758" - "a52a0085f2e034e7f971df445436a252467f692ec9c5ba7e5eaa898ab99cbd9949" - "496f7e3cafbf56304b1cc2e5bdf06e"); - - CKey key; - key.SetPrivKey(CPrivKey(private_key.begin(), private_key.end())); - - return key; - } - - //! - //! \brief Create a valid public key for tests. - //! - //! \return Complements the private key above. - //! - static CPubKey Public() - { - return CPubKey(std::vector { - 0x04, 0x4b, 0x29, 0x38, 0xfb, 0xc3, 0x80, 0x71, 0xf2, 0x4b, 0xed, - 0xe2, 0x1e, 0x83, 0x8a, 0x07, 0x58, 0xa5, 0x2a, 0x00, 0x85, 0xf2, - 0xe0, 0x34, 0xe7, 0xf9, 0x71, 0xdf, 0x44, 0x54, 0x36, 0xa2, 0x52, - 0x46, 0x7f, 0x69, 0x2e, 0xc9, 0xc5, 0xba, 0x7e, 0x5e, 0xaa, 0x89, - 0x8a, 0xb9, 0x9c, 0xbd, 0x99, 0x49, 0x49, 0x6f, 0x7e, 0x3c, 0xaf, - 0xbf, 0x56, 0x30, 0x4b, 0x1c, 0xc2, 0xe5, 0xbd, 0xf0, 0x6e - }); - } - - //! - //! \brief Create a valid public key for tests. - //! - //! \return Hex-encoded uncompressed key that complements the private key - //! above (and same key as the public key object above). - //! - static std::string PublicString() - { - return "044b2938fbc38071f24bede21e838a0758a52a0085f2e034e7f971df445436a25" - "2467f692ec9c5ba7e5eaa898ab99cbd9949496f7e3cafbf56304b1cc2e5bdf06e"; - } - - //! - //! \brief Create some invalid hex-encoded public key strings for tests. - //! - //! \return A set of various malformed public key strings that should fail - //! validation after parsing. - //! - static std::vector GarbagePublicStrings() - { - return std::vector { - // Too short: 32 bytes (not a real key): - "044b2938fbc38071f24bede21e838a0758a52a0085f2e034e7f971df445436a25", - // Too long: 66 bytes (not a real key): - "044b2938fbc38071f24bede21e838a0758a52a0085f2e034e7f971df445436a252" - "467f692ec9c5ba7e5eaa898ab99cbd9949496f7e3cafbf56304b1cc2e5bdf06e11", - // Garbage: invalid hex characters - "zz4b2938fbc38071f24bede21e838a0758a52a0085f2e034e7f971df445436a252", - }; - } -}; // struct TestKey - //! //! \brief Provides various signature representations for tests. //! @@ -159,25 +79,6 @@ struct TestSig "AiAp7QvHHhf1+xqEB57/k00jZW5RIITaxI9jXaR51Lmfnw=="; } - //! - //! \brief Create a valid signature of a version 1 contract for tests. - //! - //! \return Signature as a vector of bytes. Same signature as the base64 - //! string version above. - //! - static std::vector V1Bytes() - { - return std::vector { - 0x30, 0x44, 0x02, 0x20, 0x70, 0xaf, 0xb6, 0xd6, 0x73, 0x22, 0xb0, - 0x6a, 0x16, 0xdc, 0xbd, 0x10, 0x3f, 0xdf, 0x9f, 0x9c, 0x8c, 0x4b, - 0x34, 0xf3, 0xb9, 0xc8, 0x78, 0x5d, 0xfe, 0x0a, 0xc6, 0x23, 0x49, - 0x8f, 0x0b, 0xcc, 0x02, 0x20, 0x29, 0xed, 0x0b, 0xc7, 0x1e, 0x17, - 0xf5, 0xfb, 0x1a, 0x84, 0x07, 0x9e, 0xff, 0x93, 0x4d, 0x23, 0x65, - 0x6e, 0x51, 0x20, 0x84, 0xda, 0xc4, 0x8f, 0x63, 0x5d, 0xa4, 0x79, - 0xd4, 0xb9, 0x9f, 0x9f - }; - } - //! //! \brief Create an invalid signature for tests. //! @@ -189,47 +90,6 @@ struct TestSig return "MEQCIHCvttZzIrBqFty9ED/fn5yMSzTzuch4Xf4KxiNJjwvM" "AiAp7QvHHhf1+xqEB57/k00jZW5RIITaxI9jXaR51LmfDw=="; } - - //! - //! \brief Create an invalid signature for tests. - //! - //! \return Signature as a vector of bytes. Same signature as the valid - //! version 1 above with the last byte changed. - //! - static std::vector InvalidBytes() - { - return std::vector { - 0x30, 0x44, 0x02, 0x20, 0x70, 0xaf, 0xb6, 0xd6, 0x73, 0x22, 0xb0, - 0x6a, 0x16, 0xdc, 0xbd, 0x10, 0x3f, 0xdf, 0x9f, 0x9c, 0x8c, 0x4b, - 0x34, 0xf3, 0xb9, 0xc8, 0x78, 0x5d, 0xfe, 0x0a, 0xc6, 0x23, 0x49, - 0x8f, 0x0b, 0xcc, 0x02, 0x20, 0x29, 0xed, 0x0b, 0xc7, 0x1e, 0x17, - 0xf5, 0xfb, 0x1a, 0x84, 0x07, 0x9e, 0xff, 0x93, 0x4d, 0x23, 0x65, - 0x6e, 0x51, 0x20, 0x84, 0xda, 0xc4, 0x8f, 0x63, 0x5d, 0xa4, 0x79, - 0xd4, 0xb9, 0x9f, 0x0f - }; - } - - //! - //! \brief Create some invalid base64-encoded signatures for tests. - //! - //! \return A set of various malformed signature strings that should fail - //! validation after parsing. - //! - static std::vector GarbageStrings() - { - return std::vector { - // Too short: 63 bytes, base64-encoded (not a real signature): - "OGU0ZjQwNTE4ODA2NjEyMTIxMDJiYmJlMDMzOTM3ZTJkMTcyNDdjYmQzMDE5OTg5MzI3NTlhNjJkMjNlMGNl", - // Too long: 74 bytes, base64-encoded (not a real signature): - "OGU0ZjQwNTE4ODA2NjEyMTIxMDJiYmJlMDMzOTM3ZTJkMTcyNDdjYmQzMDE5OTg5MzI3NTlhNjJkMjNlMGNlMDk0MGU4Y2EzMjA=", - // Garbage base64-encoded string (one padding removed): - "MEQCIBQji0VFbMdiD5urHGgeq0UaiMB6IfI6+JKCC3Y9gMxCAiBornelAZ2bFusBPiD4DL+HS2SbiVU4j4pmMW4dQiiDIA=", - // Garbage base64-encoded string (one character removed): - "MEQCIBQji0VFbMdiD5urHGgeq0UaiMB6IfI6+JKCC3Y9gMxCAiBornelAZ2bFusBPiD4DL+HS2SbiVU4j4pmMW4dQiiDI==", - // Garbage base64-encoded string (non-base64 character): - "^EQCIBQji0VFbMdiD5urHGgeq0UaiMB6IfI6+JKCC3Y9gMxCAiBornelAZ2bFusBPiD4DL+HS2SbiVU4j4pmMW4dQiiDIA==", - }; - } }; // struct TestSig //! @@ -250,9 +110,7 @@ struct TestMessage GRC::Contract::CURRENT_VERSION, GRC::ContractType::PROJECT, GRC::ContractAction::ADD, - GRC::ContractPayload::Make("test", "test", 123), - GRC::Contract::Signature(), - GRC::Contract::PublicKey()); + GRC::ContractPayload::Make("test", "test", 123)); } //! @@ -611,159 +469,6 @@ BOOST_AUTO_TEST_CASE(it_deserializes_from_a_stream) BOOST_AUTO_TEST_SUITE_END() -// ----------------------------------------------------------------------------- -// Contract::Signature -// ----------------------------------------------------------------------------- - -BOOST_AUTO_TEST_SUITE(Contract__Signature) - -BOOST_AUTO_TEST_CASE(it_initializes_to_an_invalid_signature_by_default) -{ - GRC::Contract::Signature signature; - - BOOST_CHECK(signature.Viable() == false); -} - -BOOST_AUTO_TEST_CASE(it_initializes_with_bytes_in_a_signature) -{ - GRC::Contract::Signature signature(std::vector { 0x05 }); - - BOOST_CHECK(signature.Raw() == std::vector { 0x05 }); -} - -BOOST_AUTO_TEST_CASE(it_parses_a_signature_from_a_v1_base64_encoded_string) -{ - std::string input = TestSig::V1String(); - - GRC::Contract::Signature signature = GRC::Contract::Signature::Parse(input); - - BOOST_CHECK(signature.ToString() == input); - BOOST_CHECK(signature.Raw() == TestSig::V1Bytes()); -} - -BOOST_AUTO_TEST_CASE(it_gives_an_invalid_signature_when_parsing_an_empty_string) -{ - GRC::Contract::Signature signature = GRC::Contract::Signature::Parse(""); - - BOOST_CHECK(signature.Viable() == false); - BOOST_CHECK(signature.ToString() == ""); -} - -BOOST_AUTO_TEST_CASE(it_supports_a_basic_check_for_signature_viability) -{ - // OK: 70 bytes - GRC::Contract::Signature signature(TestSig::V1Bytes()); - - BOOST_CHECK(signature.Viable() == true); - - // OK: 70 bytes (not a real signature) - // Invalid signatures with correct length pass but won't verify against the - // public key when checking the contract. This is just an early check. - signature = GRC::Contract::Signature(TestSig::InvalidBytes()); - - BOOST_CHECK(signature.Viable() == true); - - // BAD: Check some invalid base64-encoded inputs: - for (const auto& garbage : TestSig::GarbageStrings()) { - signature = GRC::Contract::Signature::Parse(garbage); - - BOOST_CHECK(signature.Viable() == false); - } -} - -BOOST_AUTO_TEST_CASE(it_provides_the_bytes_in_the_signature) -{ - GRC::Contract::Signature signature(TestSig::V1Bytes()); - - BOOST_CHECK(signature.Raw() == TestSig::V1Bytes()); -} - -BOOST_AUTO_TEST_CASE(it_represents_itself_as_a_string) -{ - std::vector input = TestSig::V1Bytes(); - - GRC::Contract::Signature signature(input); - - BOOST_CHECK(signature.ToString() == TestSig::V1String()); -} - -BOOST_AUTO_TEST_SUITE_END() - -// ----------------------------------------------------------------------------- -// Contract::PublicKey -// ----------------------------------------------------------------------------- - -BOOST_AUTO_TEST_SUITE(Contract__PublicKey) - -BOOST_AUTO_TEST_CASE(it_initializes_to_an_invalid_key_by_default) -{ - GRC::Contract::PublicKey key; - - BOOST_CHECK(key.Key() == CPubKey()); -} - -BOOST_AUTO_TEST_CASE(it_initializes_by_wrapping_a_provided_key_object) -{ - GRC::Contract::PublicKey key(TestKey::Public()); - - BOOST_CHECK(key.Key() == TestKey::Public()); -} - -BOOST_AUTO_TEST_CASE(it_parses_a_public_key_from_a_hex_encoded_string) -{ - std::string input = TestKey::PublicString(); - - GRC::Contract::PublicKey key = GRC::Contract::PublicKey::Parse(input); - - BOOST_CHECK(key.Key() == TestKey::Public()); -} - -BOOST_AUTO_TEST_CASE(it_gives_an_invalid_key_when_parsing_an_empty_string) -{ - GRC::Contract::PublicKey key = GRC::Contract::PublicKey::Parse(""); - - BOOST_CHECK(key.Viable() == false); - BOOST_CHECK(key.ToString() == ""); -} - -BOOST_AUTO_TEST_CASE(it_supports_a_basic_check_for_key_viability) -{ - // OK: 65 bytes, uncompressed - std::string full_length = TestKey::PublicString(); - GRC::Contract::PublicKey key = GRC::Contract::PublicKey::Parse(full_length); - - BOOST_CHECK(key.Viable() == true); - - // OK: 33 bytes, compressed (not a real key) - key = GRC::Contract::PublicKey::Parse( - "044b2938fbc38071f24bede21e838a0758a52a0085f2e034e7f971df445436a252"); - - BOOST_CHECK(key.Viable() == true); - - // BAD: Check some invalid hex-encoded inputs: - for (const auto& garbage : TestKey::GarbagePublicStrings()) { - key = GRC::Contract::PublicKey::Parse(garbage); - - BOOST_CHECK(key.Viable() == false); - } -} - -BOOST_AUTO_TEST_CASE(it_provides_the_wrapped_key) -{ - GRC::Contract::PublicKey key(TestKey::Public()); - - BOOST_CHECK(key.Key() == TestKey::Public()); -} - -BOOST_AUTO_TEST_CASE(it_represents_itself_as_a_string) -{ - GRC::Contract::PublicKey key(TestKey::Public()); - - BOOST_CHECK(key.ToString() == TestKey::PublicString()); -} - -BOOST_AUTO_TEST_SUITE_END() - // ----------------------------------------------------------------------------- // Contract // ----------------------------------------------------------------------------- @@ -778,8 +483,6 @@ BOOST_AUTO_TEST_CASE(it_initializes_to_an_invalid_contract_by_default) BOOST_CHECK(contract.m_type == GRC::ContractType::UNKNOWN); BOOST_CHECK(contract.m_action == GRC::ContractAction::UNKNOWN); BOOST_CHECK(contract.m_body.WellFormed(contract.m_action.Value()) == false); - BOOST_CHECK(contract.m_signature.Raw().empty() == true); - BOOST_CHECK(contract.m_public_key.Key() == CPubKey()); } BOOST_AUTO_TEST_CASE(it_initializes_with_components_for_a_new_contract) @@ -793,8 +496,6 @@ BOOST_AUTO_TEST_CASE(it_initializes_with_components_for_a_new_contract) BOOST_CHECK(contract.m_type == GRC::ContractType::BEACON); BOOST_CHECK(contract.m_action == GRC::ContractAction::ADD); BOOST_CHECK(contract.m_body.WellFormed(contract.m_action.Value()) == true); - BOOST_CHECK(contract.m_signature.Raw().empty() == true); - BOOST_CHECK(contract.m_public_key.Key() == CPubKey()); } BOOST_AUTO_TEST_CASE(it_initializes_with_components_from_a_contract_message) @@ -803,22 +504,12 @@ BOOST_AUTO_TEST_CASE(it_initializes_with_components_from_a_contract_message) GRC::Contract::CURRENT_VERSION, GRC::ContractType::BEACON, GRC::ContractAction::ADD, - GRC::ContractPayload::Make("test data"), - GRC::Contract::Signature(TestSig::V1Bytes()), - GRC::Contract::PublicKey(TestKey::Public())); + GRC::ContractPayload::Make("test data")); BOOST_CHECK(contract.m_version == GRC::Contract::CURRENT_VERSION); BOOST_CHECK(contract.m_type == GRC::ContractType::BEACON); BOOST_CHECK(contract.m_action == GRC::ContractAction::ADD); BOOST_CHECK(contract.m_body.WellFormed(contract.m_action.Value()) == true); - BOOST_CHECK(contract.m_signature.Raw() == TestSig::V1Bytes()); - BOOST_CHECK(contract.m_public_key.Key() == TestKey::Public()); -} - -BOOST_AUTO_TEST_CASE(it_provides_the_legacy_message_keys) -{ - BOOST_CHECK(GRC::Contract::MessagePrivateKey().size() == 279); - BOOST_CHECK(GRC::Contract::MessagePublicKey().Raw().size() == 65); } BOOST_AUTO_TEST_CASE(it_detects_a_contract_in_a_transaction_message) @@ -851,8 +542,6 @@ BOOST_AUTO_TEST_CASE(it_parses_a_legacy_v1_contract_from_a_transaction_message) BOOST_CHECK(contract.m_action == GRC::ContractAction::ADD); BOOST_CHECK(payload->LegacyKeyString() == "test"); BOOST_CHECK(payload->LegacyValueString() == "test"); - BOOST_CHECK(contract.m_signature.Raw().size() == 70); - BOOST_CHECK(contract.m_public_key.Key().Raw().size() == 0); } BOOST_AUTO_TEST_CASE(it_gives_an_invalid_contract_when_parsing_an_empty_message) @@ -863,8 +552,6 @@ BOOST_AUTO_TEST_CASE(it_gives_an_invalid_contract_when_parsing_an_empty_message) BOOST_CHECK(contract.m_type == GRC::ContractType::UNKNOWN); BOOST_CHECK(contract.m_action == GRC::ContractAction::UNKNOWN); BOOST_CHECK(contract.m_body.WellFormed(contract.m_action.Value()) == false); - BOOST_CHECK(contract.m_signature.Raw().size() == 0); - BOOST_CHECK(contract.m_public_key.Key().Raw().size() == 0); } BOOST_AUTO_TEST_CASE(it_gives_an_invalid_contract_when_parsing_a_non_contract) @@ -875,19 +562,12 @@ BOOST_AUTO_TEST_CASE(it_gives_an_invalid_contract_when_parsing_a_non_contract) BOOST_CHECK(contract.m_type == GRC::ContractType::UNKNOWN); BOOST_CHECK(contract.m_action == GRC::ContractAction::UNKNOWN); BOOST_CHECK(contract.m_body.WellFormed(contract.m_action.Value()) == false); - BOOST_CHECK(contract.m_signature.Raw().size() == 0); - BOOST_CHECK(contract.m_public_key.Key().Raw().size() == 0); } BOOST_AUTO_TEST_CASE(it_determines_whether_a_contract_is_complete) { GRC::Contract contract = TestMessage::Current(); BOOST_CHECK(contract.WellFormed() == true); - - // WellFormed() does NOT verify the signature: - contract = TestMessage::Current(); - contract.m_signature = GRC::Contract::Signature(TestSig::InvalidBytes()); - BOOST_CHECK(contract.WellFormed() == true); } BOOST_AUTO_TEST_CASE(it_determines_whether_a_legacy_v1_contract_is_complete) @@ -909,37 +589,6 @@ BOOST_AUTO_TEST_CASE(it_determines_whether_a_legacy_v1_contract_is_complete) BOOST_CHECK(contract.WellFormed() == false); } -BOOST_AUTO_TEST_CASE(it_determines_whether_a_contract_is_valid) -{ - GRC::Contract contract = TestMessage::Current(); - BOOST_CHECK(contract.Validate() == true); - - // Version 2+ contracts rely on the signatures in the transactions instead - // of embedding another signature in the contract: - contract = TestMessage::Current(); - contract.m_signature = GRC::Contract::Signature(TestSig::InvalidBytes()); - BOOST_CHECK(contract.Validate() == true); -} - -BOOST_AUTO_TEST_CASE(it_determines_whether_a_legacy_v1_contract_is_valid) -{ - GRC::Contract contract = GRC::Contract::Parse(TestMessage::V1String()); - BOOST_CHECK(contract.Validate() == true); - - // Valid() DOES verify the signature: - contract = GRC::Contract::Parse(TestMessage::InvalidV1String()); - BOOST_CHECK(contract.Validate() == false); - - contract = GRC::Contract::Parse(TestMessage::PartialV1String()); - BOOST_CHECK(contract.Validate() == false); - - contract = GRC::Contract::Parse(""); - BOOST_CHECK(contract.Validate() == false); - - contract = GRC::Contract::Parse(""); - BOOST_CHECK(contract.Validate() == false); -} - BOOST_AUTO_TEST_CASE(it_determines_the_requred_burn_fee) { const GRC::Contract contract = TestMessage::Current(); @@ -999,162 +648,6 @@ BOOST_AUTO_TEST_CASE(it_moves_a_cast_or_converted_payload) BOOST_CHECK(contract.WellFormed() == false); } -BOOST_AUTO_TEST_CASE(it_determines_whether_a_contract_needs_a_special_key) -{ - // Note: currently all contract types require either the master or message - // public/private keys. - - GRC::Contract contract; - - // The following tests are not exhaustive for every type/action pair: - contract.m_type = GRC::ContractType::BEACON; - contract.m_action = GRC::ContractAction::ADD; - - BOOST_CHECK(contract.RequiresSpecialKey() == true); - BOOST_CHECK(contract.RequiresMasterKey() == false); - BOOST_CHECK(contract.RequiresMessageKey() == true); - - contract.m_type = GRC::ContractType::PROJECT; - - BOOST_CHECK(contract.RequiresSpecialKey() == true); - BOOST_CHECK(contract.RequiresMasterKey() == true); - BOOST_CHECK(contract.RequiresMessageKey() == false); -} - -BOOST_AUTO_TEST_CASE(it_resolves_the_appropriate_public_key_for_a_contract) -{ - // Note: currently all contracts types require either the master or message - // public/private keys. - - GRC::Contract contract; - - contract.m_type = GRC::ContractType::BEACON; - contract.m_action = GRC::ContractAction::ADD; - - BOOST_CHECK(contract.ResolvePublicKey() == GRC::Contract::MessagePublicKey()); - - contract.m_type = GRC::ContractType::PROJECT; - - BOOST_CHECK(contract.ResolvePublicKey() == CWallet::MasterPublicKey()); -} - -BOOST_AUTO_TEST_CASE(it_signs_a_message_with_a_supplied_private_key) -{ - GRC::Contract contract( - GRC::ContractType::UNKNOWN, - GRC::ContractAction::ADD, - GRC::ContractPayload::Make("test")); - - CKey private_key = TestKey::Private(); - - BOOST_CHECK(contract.Sign(private_key) == true); - - // Build the message body to hash to verify the new signature: - std::vector body { - 0x02, 0x00, 0x00, 0x00, // Version - 0x00, // ContractType::UNKNOWN - 0x01, // ContractAction::ADD - 0x04, 0x74, 0x65, 0x73, 0x74, // "test" preceded by length - }; - - uint256 hashed = Hash(body.begin(), body.end()); - - BOOST_CHECK(contract.m_signature.Viable() == true); - BOOST_CHECK(TestKey::Private().Verify(hashed, contract.m_signature.Raw())); -} - -BOOST_AUTO_TEST_CASE(it_signs_a_legacy_v1_message_with_a_supplied_private_key) -{ - GRC::Contract contract = TestMessage::V1(); - CKey private_key = TestKey::Private(); - - BOOST_CHECK(contract.Sign(private_key) == true); - - // Build the message body to hash to verify the new signature: - std::string body = "projecttesttest"; - uint256 hashed = Hash(body.begin(), body.end()); - - BOOST_CHECK(TestKey::Private().Verify(hashed, contract.m_signature.Raw())); -} - -BOOST_AUTO_TEST_CASE(it_signs_a_message_with_the_shared_message_private_key) -{ - GRC::Contract contract( - GRC::ContractType::BEACON, - GRC::ContractAction::ADD, - GRC::ContractPayload::Make("test")); - - BOOST_CHECK(contract.SignWithMessageKey() == true); - - // Build the message body to hash to verify the new signature: - std::vector body = { - 0x02, 0x00, 0x00, 0x00, // Version - 0x01, // ContractType::BEACON - 0x01, // ContractAction::ADD - 0x04, 0x74, 0x65, 0x73, 0x74, // "test" preceded by length - }; - - uint256 hashed = Hash(body.begin(), body.end()); - CKey key; - key.SetPrivKey(GRC::Contract::MessagePrivateKey()); - - BOOST_CHECK(key.Verify(hashed, contract.m_signature.Raw())); -} - -BOOST_AUTO_TEST_CASE(it_refuses_to_sign_a_message_with_an_invalid_private_key) -{ - GRC::Contract contract( - GRC::ContractType::BEACON, - GRC::ContractAction::ADD, - GRC::ContractPayload::Make("test")); - - CKey key; // Empty key - - BOOST_CHECK(contract.Sign(key) == false); - BOOST_CHECK(contract.m_signature.Raw().size() == 0); -} - -BOOST_AUTO_TEST_CASE(it_verifies_a_legacy_v1_contract_signature) -{ - // Test a message with a valid signature: - GRC::Contract contract = GRC::Contract::Parse(TestMessage::V1String()); - BOOST_CHECK(contract.VerifySignature() == true); - - // Change the previously-signed content: - contract.m_type = GRC::ContractType::PROJECT; - BOOST_CHECK(contract.VerifySignature() == false); - - // Test a message with an invalid signature: - contract = GRC::Contract::Parse(TestMessage::InvalidV1String()); - BOOST_CHECK(contract.VerifySignature() == false); -} - -BOOST_AUTO_TEST_CASE(it_generates_a_hash_of_a_contract_body) -{ - GRC::Contract contract = TestMessage::Current(); - - CHashWriter hasher(SER_NETWORK, PROTOCOL_VERSION); - - hasher << contract.m_version; - hasher << contract.m_type; - hasher << contract.m_action; - contract.m_body.Serialize(hasher, contract.m_action.Value()); - - BOOST_CHECK(contract.GetHash() == hasher.GetHash()); -} - -BOOST_AUTO_TEST_CASE(it_generates_a_hash_of_a_legacy_v1_contract_body) -{ - GRC::Contract contract = TestMessage::V1(); - GRC::ContractPayload payload = contract.m_body.AssumeLegacy(); - - std::string legacy = contract.m_type.ToString(); - legacy += payload->LegacyKeyString(); - legacy += payload->LegacyValueString(); - - BOOST_CHECK(contract.GetHash() == Hash(legacy.begin(), legacy.end())); -} - BOOST_AUTO_TEST_CASE(it_serializes_to_a_stream) { GRC::Contract contract = TestMessage::Current(); @@ -1184,15 +677,11 @@ BOOST_AUTO_TEST_CASE(it_deserializes_from_a_stream) GRC::ContractPayload payload = contract.SharePayload(); - BOOST_CHECK(contract.Validate() == true); // Verifies signature + BOOST_CHECK(contract.WellFormed() == true); BOOST_CHECK(contract.m_version == GRC::Contract::CURRENT_VERSION); BOOST_CHECK(contract.m_type == GRC::ContractType::PROJECT); BOOST_CHECK(contract.m_action == GRC::ContractAction::ADD); BOOST_CHECK(payload->LegacyKeyString() == "test"); - // Version 2+ contracts rely on the signatures in the transactions instead - // of embedding another signature in the contract: - BOOST_CHECK(contract.m_public_key == CPubKey()); - BOOST_CHECK(contract.m_signature.Raw().empty() == true); } BOOST_AUTO_TEST_SUITE_END() From a29819e3e42c014ad09c21ece6c33ea66c1379ed Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Fri, 16 Oct 2020 22:01:12 -0500 Subject: [PATCH 24/53] Remove -usenewnn and -disablenn config options Because nodes validate superblocks from scraper convergences for block version 11+, nodes cannot disable the scraper subscriber thread (named the NN thread before) anymore. Gridcoin init starts the scraper thread or the subscriber thread based on the value of the -scraper option now and stats processing is always active. --- src/gridcoin/gridcoin.cpp | 14 +------------- src/gridcoin/quorum.cpp | 10 ---------- src/gridcoin/quorum.h | 8 -------- src/qt/guiutil.cpp | 14 +++++++------- 4 files changed, 8 insertions(+), 38 deletions(-) diff --git a/src/gridcoin/gridcoin.cpp b/src/gridcoin/gridcoin.cpp index 06accc093f..afda68e4b4 100644 --- a/src/gridcoin/gridcoin.cpp +++ b/src/gridcoin/gridcoin.cpp @@ -36,8 +36,6 @@ namespace { //! void InitializeSuperblockQuorum(const CBlockIndex* pindexBest) { - LogPrintf("Gridcoin: quorum is %sactive", Quorum::Active() ? "" : "in"); - if (IsV9Enabled(pindexBest->nHeight)) { LogPrintf("Gridcoin: Loading superblock cache..."); uiInterface.InitMessage(_("Loading superblock cache...")); @@ -173,9 +171,6 @@ void InitializeScraper() // For example. gridcoinresearch(d) with no args will run the subscriber // but not the scraper. // gridcoinresearch(d) -scraper will run the scraper but not the subscriber. - // gridcoinresearch(d) -scraper -usenewnn will run both the scraper and the - // subscriber. - // -disablenn overrides the -usenewnn directive. if (GetBoolArg("-scraper", false)) { LogPrintf("Gridcoin: scraper enabled"); @@ -197,14 +192,7 @@ void InitializeScraper() //! void InitializeExplorerFeatures() { - // If -disablenn is NOT specified or set to false... - if (!GetBoolArg("-disablenn", false)) { - // Then if -scraper is specified (set to true)... - if (GetBoolArg("-scraper", false)) { - // Activate explorer extended features if -explorer is set - if (GetBoolArg("-explorer", false)) fExplorer = true; - } - } + fExplorer = GetBoolArg("-scraper", false) && GetBoolArg("-explorer", false); } //! diff --git a/src/gridcoin/quorum.cpp b/src/gridcoin/quorum.cpp index fc5796e5e1..794d5f8168 100644 --- a/src/gridcoin/quorum.cpp +++ b/src/gridcoin/quorum.cpp @@ -1481,12 +1481,6 @@ LegacyConsensus g_legacy_consensus; // Class: Quorum // ----------------------------------------------------------------------------- -bool Quorum::Active() -{ - return !GetBoolArg("-disablenn", false) - && (!GetBoolArg("-scraper", false) || GetBoolArg("-usenewnn", false)); -} - bool Quorum::Participating(const std::string& grc_address, const int64_t time) { return LegacyConsensus::Participating(grc_address, time); @@ -1696,10 +1690,6 @@ void Quorum::LoadSuperblockIndex(const CBlockIndex* pindexLast) Superblock Quorum::CreateSuperblock() { - if (!Active()) { - return Superblock(); - } - return ScraperGetSuperblockContract(); } diff --git a/src/gridcoin/quorum.h b/src/gridcoin/quorum.h index 51f6a02204..4310359cd5 100644 --- a/src/gridcoin/quorum.h +++ b/src/gridcoin/quorum.h @@ -62,14 +62,6 @@ class ExplainMagnitudeProject class Quorum { public: - //! - //! \brief Determine whether the quorum system is active. - //! - //! \return \c true if the scraper is disabled or if the quorum system is - //! explicitly configured as active. - //! - static bool Active(); - //! //! \brief Determine whether the provided address participates in the //! quorum consensus at the specified time. diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 26515fb090..238d51e198 100755 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -388,12 +388,12 @@ AutoStartupArguments GetAutoStartupArguments(bool fStartMin = true) { // This helper function checks for the presence of certain startup arguments // to the current running instance that should be relevant for automatic restart - // (currently testnet, datadir, scraper, explorer, usenewnn). It adds -testnet + // (currently testnet, datadir, scraper, explorer). It adds -testnet // to the link name as a suffix if -testnet is specified otherwise adds mainnet, // and then adds the other three as arguments if they were specified for the // running instance. This allows two different automatic startups, one for // mainnet, and the other for testnet, and each of them can have different datadir, - // scraper, explorer, and/or usenewnn arguments. + // scraper, and/or explorer arguments. AutoStartupArguments result; @@ -418,13 +418,13 @@ AutoStartupArguments GetAutoStartupArguments(bool fStartMin = true) result.arguments += " -min"; } -for (const auto& flag : { "-scraper", "-explorer", "-usenewnn" }) -{ - if (GetBoolArg(flag)) + for (const auto& flag : { "-scraper", "-explorer" }) { - (result.arguments += " ") += flag; + if (GetBoolArg(flag)) + { + (result.arguments += " ") += flag; + } } -} return result; } From 046af6bc3633589019466f13ef8045062843bdb0 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Fri, 16 Oct 2020 22:01:14 -0500 Subject: [PATCH 25/53] Fix ability to reorganize contracts Contextual contract validation can prevent nodes from reorganizing when a conflict occurs for contracts since both chains can confirm the same contract transaction. Original validation occurred before disconnecting the tip of the stale chain and reverting the context examined for the checks. --- src/main.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d8478a572e..ff8fa61234 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2302,8 +2302,16 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) } // Validate any contracts published in the transaction: - if (!tx.GetContracts().empty() && !tx.CheckContracts(mapInputs)) { - return false; + if (!tx.GetContracts().empty()) { + if (!tx.CheckContracts(mapInputs)) { + return false; + } + + if (nVersion >= 11 && !GRC::ValidateContracts(tx)) { + return tx.DoS(25, error("%s: invalid contract in tx %s", + __func__, + tx.GetHash().ToString())); + } } if (!tx.ConnectInputs(txdb, mapInputs, mapQueuedChanges, posThisTx, pindex, true, false)) @@ -3038,15 +3046,6 @@ bool CBlock::AcceptBlock(bool generated_by_me) // Check that all transactions are finalized if (!IsFinalTx(tx, nHeight, GetBlockTime())) return DoS(10, error("AcceptBlock() : contains a non-final transaction")); - - if (nVersion >= 9) { - // Perform contextual validation for any contracts: - if (!tx.GetContracts().empty() && !GRC::ValidateContracts(tx)) { - return tx.DoS(25, error("%s: invalid contract in tx %s", - __func__, - tx.GetHash().ToString())); - } - } } // Check that the block chain matches the known block chain up to a checkpoint From 58d19e7a4fcd91ec2ad356b4b6d4181c805e0c67 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Fri, 16 Oct 2020 23:16:56 -0500 Subject: [PATCH 26/53] Decrease poll duration to 90 days This decreases the poll duration that user-facing pieces allow to 90 days. The protocol rule does not change. --- src/gridcoin/voting/builders.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/gridcoin/voting/builders.cpp b/src/gridcoin/voting/builders.cpp index c86343f321..43bb21135f 100644 --- a/src/gridcoin/voting/builders.cpp +++ b/src/gridcoin/voting/builders.cpp @@ -1000,10 +1000,16 @@ PollBuilder PollBuilder::SetDuration(const uint32_t days) std::to_string(Poll::MIN_DURATION_DAYS))); } - if (days > Poll::MAX_DURATION_DAYS) { + // The protocol allows poll durations up to 180 days. To limit unhelpful + // or unintentional poll durations, user-facing pieces discourage a poll + // longer than: + // + constexpr uint32_t max_duration_days = 90; + + if (days > max_duration_days) { throw VotingError(strprintf( _("Poll duration cannot exceed %s days."), - std::to_string(Poll::MAX_DURATION_DAYS))); + std::to_string(max_duration_days))); } m_poll->m_duration_days = days; From edc394435ec86cf824636b24fa3558b5c59d7246 Mon Sep 17 00:00:00 2001 From: div72 <60045611+div72@users.noreply.github.com> Date: Sat, 17 Oct 2020 11:14:55 +0300 Subject: [PATCH 27/53] Port amount.h --- src/amount.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/amount.h diff --git a/src/amount.h b/src/amount.h new file mode 100644 index 0000000000..c2904a2db3 --- /dev/null +++ b/src/amount.h @@ -0,0 +1,28 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2018 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_AMOUNT_H +#define BITCOIN_AMOUNT_H + +#include + +/** Amount in halfords (Can be negative) */ +typedef int64_t CAmount; + +static const CAmount COIN = 100000000; + +/** No amount larger than this (in Halford) is valid. + * + * Note that this constant is *not* the total money supply, which in Gridcoin + * currently happens to be less than 2,000,000,000 GRC for various reasons, but + * rather a sanity check. As this sanity check is used by consensus-critical + * validation code, the exact value of the MAX_MONEY constant is consensus + * critical; in unusual circumstances like a overflow bug that allowed + * for the creation of coins out of thin air modification could lead to a fork. + * */ +static const CAmount MAX_MONEY = 2000000000 * COIN; +inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } + +#endif // BITCOIN_AMOUNT_H From b6b86d446e9b32473e7685ae2fb0a09883b2cdda Mon Sep 17 00:00:00 2001 From: div72 <60045611+div72@users.noreply.github.com> Date: Sat, 17 Oct 2020 11:21:00 +0300 Subject: [PATCH 28/53] Add amount.h to the makefile --- src/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.am b/src/Makefile.am index 5d0757ebe9..9456f856ed 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -60,6 +60,7 @@ GRIDCOIN_CORE_H = \ addrdb.h \ addrman.h \ alert.h \ + amount.h \ arith_uint256.h \ attributes.h \ banman.h \ From 26d15057da0780c29a9ab9983b508afebe1784f8 Mon Sep 17 00:00:00 2001 From: jamescowens Date: Sat, 17 Oct 2020 16:16:36 -0400 Subject: [PATCH 29/53] Adds detection if version is below last mandatory --- src/gridcoin/upgrade.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/gridcoin/upgrade.cpp b/src/gridcoin/upgrade.cpp index 1d2780214f..939c531d53 100644 --- a/src/gridcoin/upgrade.cpp +++ b/src/gridcoin/upgrade.cpp @@ -125,6 +125,7 @@ bool Upgrade::CheckForLatestUpdate(bool ui_dialog, std::string client_message_ou } bool NewVersion = false; + bool NewMandatory = false; try { // Left to right version numbers. @@ -135,7 +136,14 @@ bool Upgrade::CheckForLatestUpdate(bool ui_dialog, std::string client_message_ou break; if (std::stoi(GithubVersion[x]) > LocalVersion[x]) + { NewVersion = true; + + if (x < 2) + { + NewMandatory = true; + } + } } } catch (std::exception& ex) @@ -152,6 +160,11 @@ bool Upgrade::CheckForLatestUpdate(bool ui_dialog, std::string client_message_ou client_message_out.append(_("Github version: ") + GithubReleaseData + "\r\n"); client_message_out.append(_("This update is ") + GithubReleaseType + "\r\n\r\n"); + if (NewMandatory) + { + client_message_out.append(_("Your wallet version is LOWER than the latest mandatory. You MUST UPGRADE YOUR WALLET!\n")); + } + std::string ChangeLog = GithubReleaseBody; if (ui_dialog) From 27d58c5e22c972fe7f63316f3c48dc085e49dffa Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Sat, 10 Oct 2020 21:24:10 -0500 Subject: [PATCH 30/53] Fix snapshot accrual for new CPIDs The snapshot accrual system released with mandatory v5.0.0 contained a bug that prevented a CPID from accruing research rewards earlier than the last superblock if that CPID never staked a block before. --- src/gridcoin/tally.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/gridcoin/tally.cpp b/src/gridcoin/tally.cpp index 78bdb47845..92637ceae8 100644 --- a/src/gridcoin/tally.cpp +++ b/src/gridcoin/tally.cpp @@ -288,11 +288,6 @@ class ResearcherTally assert(account.m_first_block_ptr != nullptr); assert(pindex == account.m_last_block_ptr); - if (pindex == account.m_first_block_ptr) { - m_researchers.erase(iter); - return; - } - account.m_total_research_subsidy -= pindex->nResearchSubsidy; if (pindex->nMagnitude > 0) { @@ -300,6 +295,11 @@ class ResearcherTally account.m_total_magnitude -= pindex->nMagnitude; } + if (pindex == account.m_first_block_ptr) { + account.m_first_block_ptr = nullptr; + return; + } + pindex = pindex->pprev; while (pindex @@ -326,7 +326,7 @@ class ResearcherTally // switch to block version 11. // if (superblock->m_version >= 2) { - TallySuperblockAccrual(superblock.m_timestamp); + TallySuperblockAccrual(superblock); if (!m_snapshots.Store(superblock.m_height, m_researchers)) { return false; @@ -513,13 +513,13 @@ class ResearcherTally //! //! \brief Tally research rewards accrued since the current superblock - //! arrived. + //! arrived for the snapshot accrual system. //! - //! \param payment_time Time of payment to calculate rewards at. + //! \param superblock Incoming superblock to calculate rewards at. //! - void TallySuperblockAccrual(const int64_t payment_time) + void TallySuperblockAccrual(const SuperblockPtr& superblock) { - const SnapshotCalculator calc(payment_time, m_current_superblock); + const SnapshotCalculator calc(superblock.m_timestamp, m_current_superblock); for (auto& account_pair : m_researchers) { const Cpid cpid = account_pair.first; @@ -531,6 +531,16 @@ class ResearcherTally account.m_accrual += calc.AccrualDelta(cpid, account); } + + // Record snapshot accrual for any CPIDs with no accounting record as + // of the last superblock: + // + for (const auto& iter : superblock->m_cpids) { + if (m_researchers.find(iter.Cpid()) == m_researchers.end()) { + ResearchAccount& account = m_researchers[iter.Cpid()]; + account.m_accrual = calc.AccrualDelta(iter.Cpid(), account); + } + } } //! From a5adc2e932e269506bf8cb529afcb2013a862211 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Sat, 10 Oct 2020 21:29:32 -0500 Subject: [PATCH 31/53] Add transition for the new CPID snapshot accrual fix This adds a consensus transition for the activation of a fix for an issue that prevents new CPIDs from accruing research rewards before the latest superblock. This commit can be reverted after the hard-fork. --- src/chainparams.h | 5 +++++ src/gridcoin/tally.cpp | 32 ++++++++++++++++++++++++++++++++ src/gridcoin/tally.h | 10 ++++++++++ src/main.cpp | 13 +++++++++++++ 4 files changed, 60 insertions(+) diff --git a/src/chainparams.h b/src/chainparams.h index 74e5fcd6d4..cf4984511d 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -129,3 +129,8 @@ inline int GetSuperblockAgeSpacing(int nHeight) { return (fTestNet ? 86400 : (nHeight > 364500) ? 86400 : 43200); } + +inline int GetNewbieSnapshotFixHeight() +{ + return fTestNet ? 1393000 : std::numeric_limits::max(); +} diff --git a/src/gridcoin/tally.cpp b/src/gridcoin/tally.cpp index 92637ceae8..de6c981c34 100644 --- a/src/gridcoin/tally.cpp +++ b/src/gridcoin/tally.cpp @@ -23,6 +23,19 @@ using LogFlags = BCLog::LogFlags; extern int64_t g_v11_timestamp; namespace { +//! +//! \brief Determines whether the snapshot accrual system should enable the fix +//! for an issue that prevents new CPIDs from accruing research rewards. +//! +//! The snapshot accrual system released with mandatory v5.0.0 contained a bug +//! that prevented a CPID from accruing research rewards earlier than the last +//! superblock if that CPID never staked a block before. The fix causes a hard +//! fork so this flag controls the activation based on block height. +//! +//! This fix is temporary and can be removed after the next mandatory release. +//! +bool g_newbie_snapshot_fix_enabled; + //! //! \brief Set the correct CPID from the block claim when the block index //! contains a zero CPID. @@ -532,6 +545,15 @@ class ResearcherTally account.m_accrual += calc.AccrualDelta(cpid, account); } + // Versions 5.0.x for the mandatory block version 11 protocol hard-fork + // contain a bug that prevented new CPIDs from accruing rewards earlier + // than the latest superblock because the loop above does not reconcile + // the pending accrual for CPIDs without a research account yet. + // + if (!g_newbie_snapshot_fix_enabled) { + return; + } + // Record snapshot accrual for any CPIDs with no accounting record as // of the last superblock: // @@ -655,6 +677,7 @@ class ResearcherTally return true; } +public: //! //! \brief Wipe out the entire snapshot accrual state and rebuild the //! snapshots and each account's accrual from the initial threshold. @@ -716,6 +739,8 @@ bool Tally::Initialize(CBlockIndex* pindex) return true; } + g_newbie_snapshot_fix_enabled = pindex->nHeight + 1 >= GetNewbieSnapshotFixHeight(); + const int64_t start_time = GetTimeMillis(); g_researcher_tally.Initialize(pindex, Quorum::CurrentSuperblock()); @@ -742,6 +767,13 @@ bool Tally::ActivateSnapshotAccrual(const CBlockIndex* const pindex) Quorum::CurrentSuperblock()); } +bool Tally::FixNewbieSnapshotAccrual() +{ + g_newbie_snapshot_fix_enabled = true; + + return g_researcher_tally.RebuildAccrualSnapshots(); +} + bool Tally::IsLegacyTrigger(const uint64_t height) { return height % TALLY_GRANULARITY == 0; diff --git a/src/gridcoin/tally.h b/src/gridcoin/tally.h index ed550237d5..3382e854ce 100644 --- a/src/gridcoin/tally.h +++ b/src/gridcoin/tally.h @@ -52,6 +52,16 @@ class Tally //! static bool ActivateSnapshotAccrual(const CBlockIndex* const pindex); + //! + //! \brief Activate the fix for an issue that prevents new CPIDs from + //! accruing research rewards earlier than the latest superblock. + //! + //! \param pindex Index of the block to activate the fix for. + //! + //! \return \c false if an error occurs while resetting the snapshot system. + //! + static bool FixNewbieSnapshotAccrual(); + //! //! \brief Check whether the height of the specified block matches the //! tally granularity. diff --git a/src/main.cpp b/src/main.cpp index 4572ff0a2c..b75c6d0c0c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3088,6 +3088,19 @@ bool GridcoinServices() g_v11_timestamp = pindexBest->nTime; } + // Fix ability for new CPIDs to accrue research rewards earlier than one + // superblock. + // + // A bug in the snapshot accrual system for block version 11+ requires a + // consensus change to fix. This activates the solution at the following + // height: + // + if (nBestHeight + 1 == GetNewbieSnapshotFixHeight()) { + if (!GRC::Tally::FixNewbieSnapshotAccrual()) { + return error("%s: Failed to fix newbie snapshot accrual", __func__); + } + } + return true; } From 689e1ff96d96cea52381a4621f995db9090e99ab Mon Sep 17 00:00:00 2001 From: jamescowens Date: Sat, 17 Oct 2020 15:37:21 -0400 Subject: [PATCH 32/53] Clean up getblockstats This corrects the error handling for getblockstats (part II) to prevent divide by zero errors and one block scopes. It also corrects block spacing and superblock spacing calculations --- src/rpcdataacq.cpp | 248 +++++++++++++++++++++++++++++---------------- 1 file changed, 160 insertions(+), 88 deletions(-) diff --git a/src/rpcdataacq.cpp b/src/rpcdataacq.cpp index 78e9981597..592c5d8bc0 100644 --- a/src/rpcdataacq.cpp +++ b/src/rpcdataacq.cpp @@ -29,7 +29,7 @@ using namespace std; extern GRC::BlockFinder RPCBlockFinder; // Brod -static bool compare_second(const pair &p1, const pair &p2) +static bool compare_second(const pair &p1, const pair &p2) { return p1.second > p2.second; } @@ -40,104 +40,139 @@ UniValue rpc_getblockstats(const UniValue& params, bool fHelp) throw runtime_error( "getblockstats mode [startheight [endheight]]\n" "\n" - "Show stats on what wallets and cpids staked recent blocks.\n"); - long mode= params[0].get_int(); - (void)mode; //TODO - long lowheight= 0; - long highheight= INT_MAX; - long maxblocks= 14000; - if (mode==0) + "Show stats on what wallets and cpids staked recent blocks.\n" + "\n" + "Mode 0: Startheight is the starting height, endheight is the chain head if not specfied.\n" + "Mode 1: Startheight is actually the number of blocks back from endheight or the chain \n" + " head if not specified."); + + unsigned int mode = params[0].get_int(); + + int64_t lowheight = 0; + + // Even though these are typed to int64_t for the future, the max here is set to the max for the integer type, + // because CBlockIndex nHeight is still type int. + int64_t highheight = INT_MAX; + + // Default scope to 30000 blocks unless otherwise specified + int64_t maxblocks = 30000; + + if (mode == 0) { - if(params.size()>=2) + if (params.size() >= 2) + { + lowheight = params[1].get_int(); + maxblocks = INT_MAX; + } + + if (params.size() >= 3) { - lowheight= params[1].get_int(); - maxblocks= INT_MAX; + highheight = params[2].get_int(); + + int64_t maxblocks = highheight - lowheight + 1; + + if (maxblocks < 2) + { + throw runtime_error("getblockstats: Number of blocks in scope less than two."); + } } - if(params.size()>=3) - highheight= params[2].get_int(); } - else if(mode==1) + else if (mode == 1) { - /* count highheight */ - maxblocks= 30000; - if(params.size()>=2) - maxblocks= params[1].get_int(); - if(params.size()>=3) - highheight= params[2].get_int(); + if (params.size() >= 2) maxblocks = params[1].get_int(); + if (params.size() >= 3) highheight = params[2].get_int(); + + if (maxblocks < 2) + { + throw runtime_error("getblockstats: number of blocks to look back less than two."); + } } - else throw runtime_error("getblockstats: Invalid mode specified"); + else + { + throw runtime_error("getblockstats: Invalid mode specified"); + } + CBlockIndex* cur; UniValue result1(UniValue::VOBJ); { LOCK(cs_main); - cur= pindexBest; + cur = pindexBest; } int64_t blockcount = 0; int64_t transactioncount = 0; - std::map c_blockversion; - std::map c_version; - std::map c_cpid; - std::map c_org; + std::map c_blockversion; + std::map c_version; + std::map c_cpid; + std::map c_org; int64_t researchcount = 0; int64_t researchtotal = 0; int64_t interesttotal = 0; int64_t minttotal = 0; - //int64_t stakeinputtotal = 0; int64_t poscount = 0; int64_t emptyblockscount = 0; int64_t l_first = INT_MAX; int64_t l_last = 0; unsigned int l_first_time = 0; unsigned int l_last_time = 0; - unsigned size_min_blk=INT_MAX; - unsigned size_max_blk=0; - uint64_t size_sum_blk=0; + unsigned int size_min_blk = INT_MAX; + unsigned int size_max_blk = 0; + uint64_t size_sum_blk = 0; double diff_sum = 0; - double diff_max=0; - double diff_min=INT_MAX; + double diff_max = 0; + double diff_min = INT_MAX; int64_t super_count = 0; - for( ; (cur - &&( cur->nHeight>=lowheight ) - &&( blockcountpprev - ) + int64_t super_first_time = std::numeric_limits::max(); + int64_t super_last_time = 0; + + for (; cur && cur->nHeight >= lowheight && blockcount < maxblocks; cur = cur->pprev) { - if(cur->nHeight>highheight) - continue; - if(l_first>cur->nHeight) + + // cur is initialized to pIndexBest. This gets us to the starting point. + if (cur->nHeight > highheight) continue; + + if (l_first > cur->nHeight) { - l_first=cur->nHeight; - l_first_time=cur->nTime; + l_first = cur->nHeight; + l_first_time = cur->nTime; } - if(l_lastnHeight) + if (l_last < cur->nHeight) { - l_last=cur->nHeight; - l_last_time=cur->nTime; + l_last = cur->nHeight; + l_last_time = cur->nTime; } + blockcount++; + CBlock block; - if(!block.ReadFromDisk(cur->nFile,cur->nBlockPos,true)) - throw runtime_error("failed to read block"); + if (!block.ReadFromDisk(cur->nFile,cur->nBlockPos,true)) + { + throw runtime_error("getblockstats: failed to read block"); + } + assert(block.vtx.size() > 0); + unsigned txcountinblock = 0; - if(block.vtx.size()>=2) + + if (block.vtx.size() >= 2) { - txcountinblock+=block.vtx.size()-2; - if(block.vtx[1].IsCoinStake()) + txcountinblock += block.vtx.size() - 2; + + if (block.vtx[1].IsCoinStake()) { poscount++; - //stakeinputtotal+=block.vtx[1].vin[0].nValue; double diff = GRC::GetDifficulty(cur); diff_sum += diff; - diff_max=std::max(diff_max,diff); - diff_min=std::min(diff_min,diff); + diff_max = std::max(diff_max, diff); + diff_min = std::min(diff_min, diff); } else - txcountinblock+=1; + { + txcountinblock += 1; + } } - transactioncount+=txcountinblock; - emptyblockscount+=(txcountinblock==0); + + transactioncount += txcountinblock; + emptyblockscount += (txcountinblock == 0); c_blockversion[block.nVersion]++; const Claim claim = block.GetClaim(); c_cpid[claim.m_mining_id.ToString()]++; @@ -146,14 +181,27 @@ UniValue rpc_getblockstats(const UniValue& params, bool fHelp) researchtotal += claim.m_research_subsidy; interesttotal += claim.m_block_subsidy; researchcount += claim.HasResearchReward(); - minttotal+=cur->nMint; + minttotal += cur->nMint; unsigned sizeblock = GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION); - size_min_blk=std::min(size_min_blk,sizeblock); - size_max_blk=std::max(size_max_blk,sizeblock); - size_sum_blk+=sizeblock; - super_count += (claim.ContainsSuperblock()); + size_min_blk = std::min(size_min_blk,sizeblock); + size_max_blk = std::max(size_max_blk,sizeblock); + size_sum_blk += sizeblock; + + if (claim.ContainsSuperblock()) + { + ++super_count; + + super_first_time = std::min(cur->nTime, super_first_time); + super_last_time = std::max(cur->nTime, super_last_time); + } + } + + if (blockcount < 2) + { + throw runtime_error("getblockstats: Blockcount of scope is less than two."); } + // general info { UniValue result(UniValue::VOBJ); result.pushKV("blocks", blockcount); @@ -161,13 +209,23 @@ UniValue rpc_getblockstats(const UniValue& params, bool fHelp) result.pushKV("last_height", l_last); result.pushKV("first_time", TimestampToHRDate(l_first_time)); result.pushKV("last_time", TimestampToHRDate(l_last_time)); - result.pushKV("time_span_hour", ((double)l_last_time-(double)l_first_time)/(double)3600); - result.pushKV("min_blocksizek", size_min_blk/(double)1024); - result.pushKV("max_blocksizek", size_max_blk/(double)1024); + result.pushKV("time_span_hour", (l_last_time - l_first_time) / (double) 3600); + + if (super_count) + { + result.pushKV("super_first_time", TimestampToHRDate(super_first_time)); + result.pushKV("super_last_time", TimestampToHRDate(super_last_time)); + result.pushKV("super_time_span_hour", (super_last_time - super_first_time) / (double) 3600); + } + + result.pushKV("min_blocksizek", size_min_blk / (double) 1024); + result.pushKV("max_blocksizek", size_max_blk / (double) 1024); result.pushKV("min_posdiff", diff_min); result.pushKV("max_posdiff", diff_max); result1.pushKV("general", result); } + + // counts { UniValue result(UniValue::VOBJ); result.pushKV("block", blockcount); @@ -178,17 +236,20 @@ UniValue rpc_getblockstats(const UniValue& params, bool fHelp) result.pushKV("super", super_count); result1.pushKV("counts", result); } + + // totals { UniValue result(UniValue::VOBJ); result.pushKV("block", blockcount); result.pushKV("research", ValueFromAmount(researchtotal)); result.pushKV("interest", ValueFromAmount(interesttotal)); result.pushKV("mint", ValueFromAmount(minttotal)); - //result.pushKV("stake_input", stakeinputtotal/(double)COIN); - result.pushKV("blocksizek", size_sum_blk/(double)1024); + result.pushKV("blocksizek", size_sum_blk / (double) 1024); result.pushKV("posdiff", diff_sum); result1.pushKV("totals", result); } + + // averages { UniValue result(UniValue::VOBJ); @@ -198,59 +259,70 @@ UniValue rpc_getblockstats(const UniValue& params, bool fHelp) result.pushKV("research", ValueFromAmount(research_average)); result.pushKV("interest", ValueFromAmount(interesttotal / blockcount)); result.pushKV("mint", ValueFromAmount(minttotal / blockcount)); - //result.pushKV("stake_input", (stakeinputtotal/(double)poscount)/(double)COIN); - result.pushKV("spacing_sec", ((double)l_last_time-(double)l_first_time)/(double)blockcount); - result.pushKV("block_per_day", ((double)blockcount*86400.0)/((double)l_last_time-(double)l_first_time)); + + double spacing_sec = (l_last_time - l_first_time) / (double) (blockcount - 1); + result.pushKV("spacing_sec", spacing_sec); + result.pushKV("block_per_day", 86400.0 / spacing_sec); // check for zero blockcount-emptyblockscount and if so make transaction average 0. double transaction_average = (blockcount - emptyblockscount) ? transactioncount / (double) (blockcount - emptyblockscount) : 0; - result.pushKV("transaction", transaction_average); - result.pushKV("blocksizek", size_sum_blk/(double)blockcount/(double)1024); - result.pushKV("posdiff", diff_sum/(double)poscount); - if (super_count > 0) - result.pushKV("super_spacing_hrs", ((l_last_time-l_first_time)/(double)super_count)/3600.0); + + result.pushKV("blocksizek", size_sum_blk / (double) blockcount / 1024.0); + + result.pushKV("posdiff", diff_sum / poscount); + + if (super_count > 1) + { + result.pushKV("super_spacing_hrs", (super_last_time - super_first_time) / ((double) super_count - 1) / 3600.0); + } result1.pushKV("averages", result); } + + // wallet versions { UniValue result(UniValue::VOBJ); - std::vector list; + std::vector list; std::copy(c_version.begin(), c_version.end(), back_inserter(list)); - std::sort(list.begin(),list.end(),compare_second); + std::sort(list.begin(), list.end(), compare_second); + for (auto const& item : list) { - result.pushKV(item.first, item.second/(double)blockcount); + result.pushKV(item.first, item.second / (double) blockcount); } result1.pushKV("versions", result); } + + // cpids { UniValue result(UniValue::VOBJ); - std::vector list; + std::vector list; std::copy(c_cpid.begin(), c_cpid.end(), back_inserter(list)); - std::sort(list.begin(),list.end(),compare_second); - int limit=64; + std::sort(list.begin(), list.end(), compare_second); + for (auto const& item : list) { - if(!(limit--)) break; - result.pushKV(item.first, item.second/(double)blockcount); + result.pushKV(item.first, item.second / (double) blockcount); } result1.pushKV("cpids", result); } + + // orgs { UniValue result(UniValue::VOBJ); - std::vector list; + std::vector list; std::copy(c_org.begin(), c_org.end(), back_inserter(list)); - std::sort(list.begin(),list.end(),compare_second); - int limit=64; + std::sort(list.begin(), list.end(), compare_second); + for (auto const& item : list) { - if(!(limit--)) break; - result.pushKV(item.first, item.second/(double)blockcount); + result.pushKV(item.first, item.second / (double) blockcount); } result1.pushKV("orgs", result); } + return result1; } From 16bac3c12be0ea1f55613b0391cf1dd619cc757a Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 18 Oct 2020 21:01:49 -0400 Subject: [PATCH 33/53] Change upgrade warning message to lower case Co-authored-by: Cy Rossignol --- src/gridcoin/upgrade.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gridcoin/upgrade.cpp b/src/gridcoin/upgrade.cpp index 939c531d53..f0e1914be3 100644 --- a/src/gridcoin/upgrade.cpp +++ b/src/gridcoin/upgrade.cpp @@ -162,7 +162,7 @@ bool Upgrade::CheckForLatestUpdate(bool ui_dialog, std::string client_message_ou if (NewMandatory) { - client_message_out.append(_("Your wallet version is LOWER than the latest mandatory. You MUST UPGRADE YOUR WALLET!\n")); + client_message_out.append(_("WARNING: A mandatory release is available. Please upgrade as soon as possible.\n")); } std::string ChangeLog = GithubReleaseBody; From 6efc662ea96cab0b0b81b59ffeeb58f051ddf356 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 18 Oct 2020 21:18:18 -0400 Subject: [PATCH 34/53] Change to use language standard type maximums --- src/rpcdataacq.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rpcdataacq.cpp b/src/rpcdataacq.cpp index 592c5d8bc0..5107942a4e 100644 --- a/src/rpcdataacq.cpp +++ b/src/rpcdataacq.cpp @@ -52,7 +52,7 @@ UniValue rpc_getblockstats(const UniValue& params, bool fHelp) // Even though these are typed to int64_t for the future, the max here is set to the max for the integer type, // because CBlockIndex nHeight is still type int. - int64_t highheight = INT_MAX; + int64_t highheight = std::numeric_limits::max(); // Default scope to 30000 blocks unless otherwise specified int64_t maxblocks = 30000; @@ -62,7 +62,7 @@ UniValue rpc_getblockstats(const UniValue& params, bool fHelp) if (params.size() >= 2) { lowheight = params[1].get_int(); - maxblocks = INT_MAX; + maxblocks = std::numeric_limits::max(); } if (params.size() >= 3) @@ -110,16 +110,16 @@ UniValue rpc_getblockstats(const UniValue& params, bool fHelp) int64_t minttotal = 0; int64_t poscount = 0; int64_t emptyblockscount = 0; - int64_t l_first = INT_MAX; + int64_t l_first = std::numeric_limits::max(); int64_t l_last = 0; unsigned int l_first_time = 0; unsigned int l_last_time = 0; - unsigned int size_min_blk = INT_MAX; + unsigned int size_min_blk = std::numeric_limits::max(); unsigned int size_max_blk = 0; uint64_t size_sum_blk = 0; double diff_sum = 0; double diff_max = 0; - double diff_min = INT_MAX; + double diff_min = std::numeric_limits::max(); int64_t super_count = 0; int64_t super_first_time = std::numeric_limits::max(); int64_t super_last_time = 0; From 3622d409f3eb4bfb38b967933e989f3f301d87f5 Mon Sep 17 00:00:00 2001 From: jamescowens Date: Sun, 18 Oct 2020 22:13:54 -0400 Subject: [PATCH 35/53] Increment version to 5.0.2.2 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e7012b1fa3..34ced8ecfc 100755 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 5) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 2) -define(_CLIENT_VERSION_BUILD, 1) +define(_CLIENT_VERSION_BUILD, 2) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2020) define(_COPYRIGHT_HOLDERS,[The %s developers]) From 9184cb07601464a2026fa569c09eeab1bced8f5b Mon Sep 17 00:00:00 2001 From: jamescowens Date: Mon, 19 Oct 2020 22:51:03 -0400 Subject: [PATCH 36/53] Correct missing mScraperStats initialization The Initialization of the ConvergedScraperStats which takes an argument of nTime and a ConvergedManifest was missing the population of the scraper statistics map. This was causing the convergencereport to leave the magnitudes and projects blank in the past convergences rendered as superblocks in detail mode. --- src/gridcoin/scraper/scraper.cpp | 2 -- src/gridcoin/superblock.h | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gridcoin/scraper/scraper.cpp b/src/gridcoin/scraper/scraper.cpp index b0cca5da00..94ba2d70ec 100755 --- a/src/gridcoin/scraper/scraper.cpp +++ b/src/gridcoin/scraper/scraper.cpp @@ -5321,8 +5321,6 @@ UniValue ConvergedScraperStatsToJson(ConvergedScraperStats& ConvergedScraperStat const ConvergedManifest& PastConvergence = iter.second.second; - ScraperStats mScraperConvergedStats = GetScraperStatsByConvergedManifest(PastConvergence).mScraperStats; - entry.pushKV("past_convergence_timestamp", PastConvergence.timestamp); entry.pushKV("past_convergence_datetime", DateTimeStrFormat("%x %H:%M:%S UTC", PastConvergence.timestamp)); diff --git a/src/gridcoin/superblock.h b/src/gridcoin/superblock.h index 447e0ea435..a366b68f81 100644 --- a/src/gridcoin/superblock.h +++ b/src/gridcoin/superblock.h @@ -20,6 +20,7 @@ extern int64_t SCRAPER_CMANIFEST_RETENTION_TIME; extern std::vector GetVerifiedBeaconIDs(const ConvergedManifest& StructConvergedManifest); extern std::vector GetVerifiedBeaconIDs(const ScraperPendingBeaconMap& VerifiedBeaconMap); +extern ScraperStatsAndVerifiedBeacons GetScraperStatsByConvergedManifest(const ConvergedManifest& StructConvergedManifest); class CBlockIndex; class ConvergedScraperStats; // Forward for Superblock @@ -1561,6 +1562,8 @@ struct ConvergedScraperStats bClean = false; nTime = nTime_in; + + mScraperConvergedStats = GetScraperStatsByConvergedManifest(Convergence).mScraperStats; } // Flag to indicate cache is clean or dirty (i.e. state change of underlying statistics has occurred. From e913c14861fd3c45f6d1d6fa7a0ece5a5bf0ec82 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Wed, 21 Oct 2020 03:19:53 -0500 Subject: [PATCH 37/53] Revert "Adjust threading for Gridcoin services" This reverts commit 8f2bdb176a7e8e43c239f9f9f2f0f34098ec0504. --- src/gridcoin/gridcoin.cpp | 17 +++++++---------- src/gridcoin/gridcoin.h | 3 ++- src/init.cpp | 4 ++-- src/net.cpp | 4 ---- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/gridcoin/gridcoin.cpp b/src/gridcoin/gridcoin.cpp index afda68e4b4..eeef5090e5 100644 --- a/src/gridcoin/gridcoin.cpp +++ b/src/gridcoin/gridcoin.cpp @@ -23,8 +23,6 @@ extern unsigned int nScraperSleep; extern unsigned int nActiveBeforeSB; extern bool fScraperActive; -extern ThreadHandler* netThreads; - void Scraper(bool bSingleShot = false); void ScraperSubscriber(); @@ -155,7 +153,9 @@ void ThreadScraperSubscriber(void* parg) //! //! \brief Configure and initialize the scraper system. //! -void InitializeScraper() +//! \param threads Used to start the scraper housekeeping threads. +//! +void InitializeScraper(ThreadHandlerPtr threads) { // Default to 300 sec (5 min), clamp to 60 minimum, 600 maximum - converted to milliseconds. nScraperSleep = std::min(std::max(GetArg("-scrapersleep", 300), 60), 600) * 1000; @@ -174,14 +174,14 @@ void InitializeScraper() if (GetBoolArg("-scraper", false)) { LogPrintf("Gridcoin: scraper enabled"); - if (!netThreads->createThread(ThreadScraper, nullptr, "ThreadScraper")) { + if (!threads->createThread(ThreadScraper, nullptr, "ThreadScraper")) { LogPrintf("ERROR: createThread(ThreadScraper) failed"); } } else { LogPrintf("Gridcoin: scraper disabled"); LogPrintf("Gridcoin: scraper subscriber housekeeping thread enabled"); - if (!netThreads->createThread(ThreadScraperSubscriber, nullptr, "ScraperSubscriber")) { + if (!threads->createThread(ThreadScraperSubscriber, nullptr, "ScraperSubscriber")) { LogPrintf("ERROR: createThread(ScraperSubscriber) failed"); } } @@ -272,7 +272,7 @@ bool fSnapshotRequest = false; // Functions // ----------------------------------------------------------------------------- -bool GRC::Initialize(CBlockIndex* pindexBest) +bool GRC::Initialize(ThreadHandlerPtr threads, CBlockIndex* pindexBest) { LogPrintf("Gridcoin: initializing..."); @@ -284,10 +284,7 @@ bool GRC::Initialize(CBlockIndex* pindexBest) InitializeContracts(pindexBest); InitializeResearcherContext(); - - // The scraper is run on the netThreads group, because it shares data structures - // with scraper_net, which is run as part of the network node threads. - InitializeScraper(); + InitializeScraper(threads); InitializeExplorerFeatures(); return true; diff --git a/src/gridcoin/gridcoin.h b/src/gridcoin/gridcoin.h index 7f324c9f5e..3f18141926 100644 --- a/src/gridcoin/gridcoin.h +++ b/src/gridcoin/gridcoin.h @@ -11,11 +11,12 @@ namespace GRC { //! //! \brief Initialize Gridcoin-specific components and services. //! +//! \param threads Used to start Gridcoin threads. //! \param pindexBest Block index for the tip of the chain. //! //! \return \c false if a problem occurs during initialization. //! -bool Initialize(CBlockIndex* pindexBest); +bool Initialize(ThreadHandlerPtr threads, CBlockIndex* pindexBest); //! //! \brief Set up Gridcoin-specific background jobs. diff --git a/src/init.cpp b/src/init.cpp index 560809a566..fe3e78b0d5 100755 --- a/src/init.cpp +++ b/src/init.cpp @@ -107,9 +107,7 @@ void Shutdown(void* parg) bitdb.Flush(false); StopNode(); bitdb.Flush(true); - StopRPCThreads(); - boost::filesystem::remove(GetPidFile()); UnregisterWallet(pwalletMain); delete pwalletMain; @@ -1087,6 +1085,8 @@ bool AppInit2(ThreadHandlerPtr threads) RandAddSeedPerfmon(); + GRC::Initialize(threads, pindexBest); + //// debug print if (LogInstance().WillLogCategory(BCLog::LogFlags::VERBOSE)) { diff --git a/src/net.cpp b/src/net.cpp index dda8972cac..2918ca2f68 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -13,7 +13,6 @@ #include "init.h" #include "ui_interface.h" #include "util.h" -#include "gridcoin/gridcoin.h" #include // for to_lower() #include @@ -2297,9 +2296,6 @@ void StartNode(void* parg) else if (!netThreads->createThread(ThreadStakeMiner,pwalletMain,"ThreadStakeMiner")) LogPrintf("Error: createThread(ThreadStakeMiner) failed"); - - // Initialize GRC services. - GRC::Initialize(pindexBest); } bool StopNode() From 8cb89e0e7da3d32804c92df44443c3f6d820391f Mon Sep 17 00:00:00 2001 From: raphahus <9782029+Pythonix@users.noreply.github.com> Date: Mon, 14 Sep 2020 21:18:30 +0200 Subject: [PATCH 38/53] add menu option to open config file --- src/qt/bitcoingui.cpp | 17 ++++++++++++++++- src/qt/bitcoingui.h | 29 ++++++++++++++++------------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 8f40fd2012..1d57ad8277 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -181,7 +181,7 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): rpcConsole = new RPCConsole(this); connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show())); - diagnosticsDialog = new DiagnosticsDialog(this); + diagnosticsDialog = new DiagnosticsDialog(this); // Clicking on "Verify Message" in the address book sends you to the verify message tab connect(addressBookPage, SIGNAL(verifyMessage(QString)), this, SLOT(gotoVerifyMessageTab(QString))); @@ -195,6 +195,8 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): QObject::connect(overview_update_timer, SIGNAL(timeout()), this, SLOT(updateGlobalStatus())); + connect(openConfigAction, SIGNAL(triggered()), this, SLOT(openConfigClicked())); + gotoOverviewPage(); } @@ -320,6 +322,9 @@ void BitcoinGUI::createActions() optionsAction = new QAction(tr("&Options..."), this); optionsAction->setToolTip(tr("Modify configuration options for Gridcoin")); optionsAction->setMenuRole(QAction::PreferencesRole); + openConfigAction = new QAction(tr("Open config &file"), this); + optionsAction->setToolTip(tr("Open the config file in your standard editor")); + openConfigAction->setMenuRole(QAction::PreferencesRole); researcherAction = new QAction(tr("&Researcher Wizard..."), this); researcherAction->setToolTip(tr("Open BOINC and beacon settings for Gridcoin")); researcherAction->setMenuRole(QAction::PreferencesRole); @@ -392,6 +397,7 @@ void BitcoinGUI::setIcons() exportAction->setIcon(QPixmap(":/icons/export")); openRPCConsoleAction->setIcon(QPixmap(":/icons/debugwindow")); snapshotAction->setIcon(QPixmap(":/images/gridcoin")); + openConfigAction->setIcon(QPixmap(":/icons/edit")); } void BitcoinGUI::createMenuBar() @@ -430,6 +436,7 @@ void BitcoinGUI::createMenuBar() settings->addAction(researcherAction); settings->addSeparator(); settings->addAction(optionsAction); + settings->addAction(openConfigAction); QMenu *community = appMenuBar->addMenu(tr("&Community")); community->addAction(bxAction); @@ -731,6 +738,14 @@ void BitcoinGUI::optionsClicked() dlg.exec(); } +void BitcoinGUI::openConfigClicked() +{ + boost::filesystem::path pathConfig = GetConfigFile(); + /* Open gridcoinresearch.conf with the associated application */ + if (boost::filesystem::exists(pathConfig)) + QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(pathConfig.string()))); +} + void BitcoinGUI::researcherClicked() { if (!researcherModel || !walletModel) { diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index d65965e816..19035c0e53 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -96,18 +96,19 @@ class BitcoinGUI : public QMainWindow QAction *sendCoinsAction; QAction *addressBookAction; QAction *signMessageAction; - QAction *bxAction; - QAction *websiteAction; - QAction *boincAction; - QAction *chatAction; - QAction *exchangeAction; + QAction *bxAction; + QAction *websiteAction; + QAction *boincAction; + QAction *chatAction; + QAction *exchangeAction; QAction *votingAction; - QAction *diagnosticsAction; + QAction *diagnosticsAction; QAction *verifyMessageAction; QAction *aboutAction; QAction *receiveCoinsAction; QAction *researcherAction; QAction *optionsAction; + QAction *openConfigAction; QAction *toggleHideAction; QAction *exportAction; QAction *encryptWalletAction; @@ -174,7 +175,7 @@ public slots: */ void askFee(qint64 nFeeRequired, bool *payFee); - void askQuestion(std::string caption, std::string body, bool *result); + void askQuestion(std::string caption, std::string body, bool *result); void handleURI(QString strURI); void setOptionsStyleSheet(QString qssFileName); @@ -204,13 +205,15 @@ private slots: void researcherClicked(); /** Show about dialog */ void aboutClicked(); + /** Open config file */ + void openConfigClicked(); - void bxClicked(); - void websiteClicked(); - void exchangeClicked(); - void boincClicked(); + void bxClicked(); + void websiteClicked(); + void exchangeClicked(); + void boincClicked(); void boincStatsClicked(); - void chatClicked(); + void chatClicked(); void diagnosticsClicked(); void peersClicked(); void snapshotClicked(); @@ -245,7 +248,7 @@ private slots: void updateScraperIcon(int scraperEventtype, int status); void updateBeaconIcon(); - QString GetEstimatedStakingFrequency(unsigned int nEstimateTime); + QString GetEstimatedStakingFrequency(unsigned int nEstimateTime); void updateGlobalStatus(); }; From 3bbbbf520798876cafcddd79e805e5edc8b696b0 Mon Sep 17 00:00:00 2001 From: raphahus <9782029+Pythonix@users.noreply.github.com> Date: Mon, 5 Oct 2020 20:16:58 +0200 Subject: [PATCH 39/53] make open config work on windows --- src/qt/bitcoingui.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 1d57ad8277..2626407edf 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -742,8 +742,19 @@ void BitcoinGUI::openConfigClicked() { boost::filesystem::path pathConfig = GetConfigFile(); /* Open gridcoinresearch.conf with the associated application */ - if (boost::filesystem::exists(pathConfig)) - QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(pathConfig.string()))); + bool res = QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(pathConfig.string()))); + #ifdef Q_OS_WIN + // Workaround for windows specific behaviour + if(!res) { + res = QProcess::startDetached("C:\\Windows\\system32\\notepad.exe", QStringList{QString::fromStdString(pathConfig.string())}); + } + #endif + #ifdef Q_OS_MAC + // Workaround for macOS-specific behaviour; see https://github.com/bitcoin/bitcoin/issues/15409 + if (!res) { + res = QProcess::startDetached("/usr/bin/open", QStringList{"-t", QString::fromStdString(pathConfig.string())}); + } + #endif } void BitcoinGUI::researcherClicked() From 2cd7ffa5add5a90f100293de82f0a39378f0cbad Mon Sep 17 00:00:00 2001 From: raphahus <9782029+Pythonix@users.noreply.github.com> Date: Wed, 21 Oct 2020 13:18:31 +0200 Subject: [PATCH 40/53] changed text to match style for context change --- src/qt/bitcoingui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 2626407edf..bae75bd5d1 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -322,7 +322,7 @@ void BitcoinGUI::createActions() optionsAction = new QAction(tr("&Options..."), this); optionsAction->setToolTip(tr("Modify configuration options for Gridcoin")); optionsAction->setMenuRole(QAction::PreferencesRole); - openConfigAction = new QAction(tr("Open config &file"), this); + openConfigAction = new QAction(tr("Open config &file..."), this); optionsAction->setToolTip(tr("Open the config file in your standard editor")); openConfigAction->setMenuRole(QAction::PreferencesRole); researcherAction = new QAction(tr("&Researcher Wizard..."), this); From dbdc30ca3d365353a9e8cf43dfb50f491cba7060 Mon Sep 17 00:00:00 2001 From: div72 <60045611+div72@users.noreply.github.com> Date: Sat, 17 Oct 2020 12:59:35 +0300 Subject: [PATCH 41/53] Use CAmount --- src/amount.h | 1 + src/gridcoin/account.h | 5 +++-- src/gridcoin/accrual/computer.h | 13 +++++++------ src/gridcoin/accrual/newbie.h | 13 +++++++------ src/gridcoin/accrual/null.h | 13 +++++++------ src/gridcoin/accrual/research_age.h | 21 +++++++++++---------- src/gridcoin/accrual/snapshot.h | 19 ++++++++++--------- src/gridcoin/beacon.h | 3 ++- src/gridcoin/claim.cpp | 3 ++- src/gridcoin/claim.h | 14 +++++--------- src/gridcoin/contract/contract.cpp | 9 +++++---- src/gridcoin/contract/contract.h | 8 +++----- src/gridcoin/contract/message.cpp | 9 +++++---- src/gridcoin/contract/payload.h | 3 ++- src/gridcoin/project.h | 3 ++- src/gridcoin/researcher.cpp | 2 +- src/gridcoin/researcher.h | 3 ++- src/gridcoin/staking/difficulty.cpp | 9 +++++---- src/gridcoin/staking/kernel.cpp | 3 ++- src/gridcoin/staking/kernel.h | 1 + src/gridcoin/staking/reward.cpp | 18 +++++++++--------- src/gridcoin/staking/reward.h | 6 ++++-- src/gridcoin/tally.cpp | 7 ++++--- src/gridcoin/tally.h | 5 +++-- src/gridcoin/voting/builders.cpp | 11 ++++++----- src/gridcoin/voting/claims.h | 13 +++++++------ src/gridcoin/voting/fwd.h | 4 +++- src/gridcoin/voting/payloads.h | 2 +- src/gridcoin/voting/registry.cpp | 3 ++- src/gridcoin/voting/result.cpp | 22 +++++++++++----------- src/gridcoin/voting/vote.h | 10 +++------- src/main.cpp | 1 + src/main.h | 5 ++--- src/miner.cpp | 1 + src/rpcserver.cpp | 1 + src/util.cpp | 1 + src/util.h | 4 ---- src/wallet/wallet.h | 2 ++ 38 files changed, 144 insertions(+), 127 deletions(-) diff --git a/src/amount.h b/src/amount.h index c2904a2db3..81415f981f 100644 --- a/src/amount.h +++ b/src/amount.h @@ -12,6 +12,7 @@ typedef int64_t CAmount; static const CAmount COIN = 100000000; +static const CAmount CENT = 1000000; /** No amount larger than this (in Halford) is valid. * diff --git a/src/gridcoin/account.h b/src/gridcoin/account.h index 7c4a3c7e06..3bf749db56 100644 --- a/src/gridcoin/account.h +++ b/src/gridcoin/account.h @@ -4,6 +4,7 @@ #pragma once +#include "amount.h" #include #include @@ -32,8 +33,8 @@ typedef boost::optional BlockPtrOption; class ResearchAccount { public: - int64_t m_accrual; //!< Research accrued last superblock. - int64_t m_total_research_subsidy; //!< Total lifetime research paid. + CAmount m_accrual; //!< Research accrued last superblock. + CAmount m_total_research_subsidy; //!< Total lifetime research paid. uint32_t m_total_magnitude; //!< Total lifetime magnitude sum. uint32_t m_accuracy; //!< Non-zero magnitude payment count. diff --git a/src/gridcoin/accrual/computer.h b/src/gridcoin/accrual/computer.h index eb6200d4bf..e5ade056d7 100644 --- a/src/gridcoin/accrual/computer.h +++ b/src/gridcoin/accrual/computer.h @@ -4,6 +4,7 @@ #pragma once +#include "amount.h" #include "gridcoin/account.h" #include @@ -26,7 +27,7 @@ class IAccrualComputer //! //! \return Max reward allowed in units of 1/100000000 GRC. //! - virtual int64_t MaxReward() const = 0; + virtual CAmount MaxReward() const = 0; //! //! \brief Get the magnitude unit factored into the reward calculation. @@ -60,14 +61,14 @@ class IAccrualComputer //! //! \return Average research payment in units of 1/100000000 GRC. //! - virtual int64_t PaymentPerDay() const = 0; + virtual CAmount PaymentPerDay() const = 0; //! //! \brief Get the average daily research payment limit of the account. //! //! \return Payment per day limit in units of 1/100000000 GRC. //! - virtual int64_t PaymentPerDayLimit() const = 0; + virtual CAmount PaymentPerDayLimit() const = 0; //! //! \brief Determine whether the account exceeded the daily payment limit. @@ -83,7 +84,7 @@ class IAccrualComputer //! //! \return Expected daily payment in units of 1/100000000 GRC. //! - virtual int64_t ExpectedDaily() const = 0; + virtual CAmount ExpectedDaily() const = 0; //! //! \brief Get the pending research reward for the account without applying @@ -91,7 +92,7 @@ class IAccrualComputer //! //! \return Pending payment in units of 1/100000000 GRC. //! - virtual int64_t RawAccrual() const = 0; + virtual CAmount RawAccrual() const = 0; //! //! \brief Get the pending research reward for the account as expected by @@ -99,7 +100,7 @@ class IAccrualComputer //! //! \return Pending payment in units of 1/100000000 GRC. //! - virtual int64_t Accrual() const = 0; + virtual CAmount Accrual() const = 0; }; //! diff --git a/src/gridcoin/accrual/newbie.h b/src/gridcoin/accrual/newbie.h index 0f47b65c21..74d5409fdd 100644 --- a/src/gridcoin/accrual/newbie.h +++ b/src/gridcoin/accrual/newbie.h @@ -4,6 +4,7 @@ #pragma once +#include "amount.h" #include "gridcoin/accrual/computer.h" #include "gridcoin/beacon.h" @@ -43,7 +44,7 @@ class NewbieAccrualComputer : public IAccrualComputer { } - int64_t MaxReward() const override + CAmount MaxReward() const override { return 500 * COIN; } @@ -72,12 +73,12 @@ class NewbieAccrualComputer : public IAccrualComputer return 0; } - int64_t PaymentPerDay() const override + CAmount PaymentPerDay() const override { return 0; } - int64_t PaymentPerDayLimit() const override + CAmount PaymentPerDayLimit() const override { return MaxReward(); } @@ -87,17 +88,17 @@ class NewbieAccrualComputer : public IAccrualComputer return RawAccrual() > PaymentPerDayLimit(); } - int64_t ExpectedDaily() const override + CAmount ExpectedDaily() const override { return m_magnitude * m_magnitude_unit * COIN; } - int64_t RawAccrual() const override + CAmount RawAccrual() const override { return AccrualDays() * ExpectedDaily(); } - int64_t Accrual() const override + CAmount Accrual() const override { if (m_magnitude <= 0) { return 0; diff --git a/src/gridcoin/accrual/null.h b/src/gridcoin/accrual/null.h index 8bd6d79152..b3690270fd 100644 --- a/src/gridcoin/accrual/null.h +++ b/src/gridcoin/accrual/null.h @@ -4,6 +4,7 @@ #pragma once +#include "amount.h" #include "gridcoin/accrual/computer.h" namespace { @@ -20,7 +21,7 @@ class NullAccrualComputer : public IAccrualComputer // See IAccrualComputer for inherited API documentation. public: - int64_t MaxReward() const override + CAmount MaxReward() const override { return 0; } @@ -45,12 +46,12 @@ class NullAccrualComputer : public IAccrualComputer return 0; } - int64_t PaymentPerDay() const override + CAmount PaymentPerDay() const override { return 0; } - int64_t PaymentPerDayLimit() const override + CAmount PaymentPerDayLimit() const override { return 0; } @@ -60,17 +61,17 @@ class NullAccrualComputer : public IAccrualComputer return false; } - int64_t ExpectedDaily() const override + CAmount ExpectedDaily() const override { return 0; } - int64_t RawAccrual() const override + CAmount RawAccrual() const override { return 0; } - int64_t Accrual() const override + CAmount Accrual() const override { return 0; } diff --git a/src/gridcoin/accrual/research_age.h b/src/gridcoin/accrual/research_age.h index cca53f520d..d8c7349f03 100644 --- a/src/gridcoin/accrual/research_age.h +++ b/src/gridcoin/accrual/research_age.h @@ -4,6 +4,7 @@ #pragma once +#include "amount.h" #include "gridcoin/accrual/computer.h" namespace { @@ -19,10 +20,10 @@ using namespace GRC; //! \return A value in units of GRC that represents the maximum research reward //! expected per block. //! -int64_t GetMaxResearchSubsidy(const int64_t nTime) +CAmount GetMaxResearchSubsidy(const int64_t nTime) { // Gridcoin Global Daily Maximum Researcher Subsidy Schedule - int MaxSubsidy = 500; + CAmount MaxSubsidy = 500; if (nTime > 1447977700) MaxSubsidy = 50; // from 11-20-2015 forever else if (nTime >= 1445309276 && nTime <= 1447977700) MaxSubsidy = 75; // between 10-20-2015 and 11-20-2015 @@ -78,7 +79,7 @@ class ResearchAgeComputer : public IAccrualComputer //! //! \return Max reward allowed in units of 1/100000000 GRC. //! - int64_t MaxReward() const override + CAmount MaxReward() const override { return GetMaxResearchSubsidy(m_payment_time) * 255 * COIN; } @@ -135,7 +136,7 @@ class ResearchAgeComputer : public IAccrualComputer //! //! \return Average research payment in units of 1/100000000 GRC. //! - int64_t PaymentPerDay() const override + CAmount PaymentPerDay() const override { if (m_account.IsNew()) { return 0; @@ -158,7 +159,7 @@ class ResearchAgeComputer : public IAccrualComputer //! //! \return Payment per day limit in units of 1/100000000 GRC. //! - int64_t PaymentPerDayLimit() const override + CAmount PaymentPerDayLimit() const override { return m_account.AverageLifetimeMagnitude() * m_magnitude_unit * COIN * 5; } @@ -180,7 +181,7 @@ class ResearchAgeComputer : public IAccrualComputer //! //! \return Expected daily payment in units of 1/100000000 GRC. //! - int64_t ExpectedDaily() const override + CAmount ExpectedDaily() const override { return m_magnitude * m_magnitude_unit * COIN; } @@ -191,7 +192,7 @@ class ResearchAgeComputer : public IAccrualComputer //! //! \return Pending payment in units of 1/100000000 GRC. //! - int64_t RawAccrual() const override + CAmount RawAccrual() const override { double current_avg_magnitude = AverageMagnitude(); @@ -209,7 +210,7 @@ class ResearchAgeComputer : public IAccrualComputer //! //! \return Pending payment in units of 1/100000000 GRC. //! - int64_t Accrual() const override + CAmount Accrual() const override { // Note that if the RA block span < 10, we want to return 0 for the // accrual amount so the CPID can still receive an accurate accrual @@ -250,8 +251,8 @@ class ResearchAgeComputer : public IAccrualComputer return 0; } - const int64_t accrual = RawAccrual(); - const int64_t max_reward = MaxReward(); + const CAmount accrual = RawAccrual(); + const CAmount max_reward = MaxReward(); if (accrual > max_reward) { return max_reward; diff --git a/src/gridcoin/accrual/snapshot.h b/src/gridcoin/accrual/snapshot.h index f818484d39..a3e02f409d 100644 --- a/src/gridcoin/accrual/snapshot.h +++ b/src/gridcoin/accrual/snapshot.h @@ -4,6 +4,7 @@ #pragma once +#include "amount.h" #include "arith_uint256.h" #include "fs.h" #include "gridcoin/account.h" @@ -102,7 +103,7 @@ class SnapshotCalculator //! //! \return Accrual earned in units of 1/100000000 GRC. //! - int64_t AccrualDelta(const Cpid& cpid, const ResearchAccount& account) const + CAmount AccrualDelta(const Cpid& cpid, const ResearchAccount& account) const { int64_t accrual_timespan; @@ -244,7 +245,7 @@ class SnapshotAccrualComputer : public IAccrualComputer, SnapshotCalculator { } - int64_t MaxReward() const override + CAmount MaxReward() const override { // The maximum accrual that a CPID can claim in one block is limited to // the amount of accrual that a CPID can collect over two days when the @@ -328,7 +329,7 @@ class SnapshotAccrualComputer : public IAccrualComputer, SnapshotCalculator return m_last_height - m_account.LastRewardHeight(); } - int64_t PaymentPerDay() const override + CAmount PaymentPerDay() const override { if (m_account.IsNew()) { return 0; @@ -344,7 +345,7 @@ class SnapshotAccrualComputer : public IAccrualComputer, SnapshotCalculator return m_account.m_total_research_subsidy / lifetime_days; } - int64_t PaymentPerDayLimit() const override + CAmount PaymentPerDayLimit() const override { return MaxReward(); } @@ -354,7 +355,7 @@ class SnapshotAccrualComputer : public IAccrualComputer, SnapshotCalculator return RawAccrual() > PaymentPerDayLimit(); } - int64_t ExpectedDaily() const override + CAmount ExpectedDaily() const override { // Since this informational value is not consensus-critical, we use // floating-point arithmetic for readability: @@ -362,7 +363,7 @@ class SnapshotAccrualComputer : public IAccrualComputer, SnapshotCalculator return CurrentMagnitude(m_cpid).Floating() * MagnitudeUnit() * COIN; } - int64_t RawAccrual() const override + CAmount RawAccrual() const override { if (m_account.LastRewardHeight() >= m_superblock.m_height) { return AccrualDelta(m_cpid, m_account); @@ -371,9 +372,9 @@ class SnapshotAccrualComputer : public IAccrualComputer, SnapshotCalculator return m_account.m_accrual + AccrualDelta(m_cpid, m_account); } - int64_t Accrual() const override + CAmount Accrual() const override { - const int64_t accrual = RawAccrual(); + const CAmount accrual = RawAccrual(); if (accrual > MaxReward()) { return MaxReward(); @@ -489,7 +490,7 @@ class AccrualSnapshot //! \return Accrued research rewards at the time of the snapshot in units //! of 1/100000000 GRC or zero if the CPID does not exist in the snapshot. //! - int64_t GetAccrual(const Cpid cpid) const + CAmount GetAccrual(const Cpid cpid) const { auto iter = m_records.find(cpid); diff --git a/src/gridcoin/beacon.h b/src/gridcoin/beacon.h index 96acec209c..0192740cae 100644 --- a/src/gridcoin/beacon.h +++ b/src/gridcoin/beacon.h @@ -4,6 +4,7 @@ #pragma once +#include "amount.h" #include "key.h" #include "gridcoin/contract/handler.h" #include "gridcoin/contract/payload.h" @@ -325,7 +326,7 @@ class BeaconPayload : public IContractPayload //! //! \return Burn fee in units of 1/100000000 GRC. //! - int64_t RequiredBurnAmount() const override + CAmount RequiredBurnAmount() const override { return 0.5 * COIN; } diff --git a/src/gridcoin/claim.cpp b/src/gridcoin/claim.cpp index f94267d601..68336b98f1 100644 --- a/src/gridcoin/claim.cpp +++ b/src/gridcoin/claim.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" #include "key.h" #include "main.h" #include "gridcoin/claim.h" @@ -185,7 +186,7 @@ bool Claim::ContainsSuperblock() const return m_superblock->WellFormed(); } -int64_t Claim::TotalSubsidy() const +CAmount Claim::TotalSubsidy() const { return m_block_subsidy + m_research_subsidy; } diff --git a/src/gridcoin/claim.h b/src/gridcoin/claim.h index 33354e3f1f..acd2e34f93 100644 --- a/src/gridcoin/claim.h +++ b/src/gridcoin/claim.h @@ -4,6 +4,7 @@ #pragma once +#include "amount.h" #include "gridcoin/contract/payload.h" #include "gridcoin/cpid.h" #include "gridcoin/superblock.h" @@ -114,7 +115,7 @@ class Claim : public IContractPayload //! incoming reward claims and can index those calculated values without //! this field. It can be considered informational. //! - int64_t m_block_subsidy; + CAmount m_block_subsidy; //! //! \brief The value of the research rewards claimed by the node in units @@ -127,7 +128,7 @@ class Claim : public IContractPayload //! incoming reward claims and can index those calculated values without //! this field. It can be considered informational. //! - int64_t m_research_subsidy; + CAmount m_research_subsidy; //! //! \brief The researcher magnitude value from the superblock at the time @@ -262,13 +263,8 @@ class Claim : public IContractPayload //! //! \return Burn fee in units of 1/100000000 GRC. //! - int64_t RequiredBurnAmount() const override + CAmount RequiredBurnAmount() const override { - // TODO: remove redefinition of this constant when porting amount.h - // from Bitcoin: - // - constexpr int64_t MAX_MONEY = 2000000000 * COIN; - // Prevent users from sending this contract manually: return MAX_MONEY; } @@ -294,7 +290,7 @@ class Claim : public IContractPayload //! \return The sum of the block subsidy and research subsidy declared in //! the claim. //! - int64_t TotalSubsidy() const; + CAmount TotalSubsidy() const; //! //! \brief Sign an instance that claims research rewards. diff --git a/src/gridcoin/contract/contract.cpp b/src/gridcoin/contract/contract.cpp index f14e37011b..7d3439acc4 100644 --- a/src/gridcoin/contract/contract.cpp +++ b/src/gridcoin/contract/contract.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" #include "main.h" #include "gridcoin/appcache.h" #include "gridcoin/claim.h" @@ -50,7 +51,7 @@ class EmptyPayload : public IContractPayload return ""; } - int64_t RequiredBurnAmount() const override + CAmount RequiredBurnAmount() const override { return MAX_MONEY; } @@ -120,7 +121,7 @@ class LegacyPayload : public IContractPayload return m_value; } - int64_t RequiredBurnAmount() const override + CAmount RequiredBurnAmount() const override { return Contract::STANDARD_BURN_AMOUNT; } @@ -473,7 +474,7 @@ void GRC::RevertContracts(const CTransaction& tx, const CBlockIndex* const pinde // Class: Contract // ----------------------------------------------------------------------------- -constexpr int64_t Contract::STANDARD_BURN_AMOUNT; // for clang +constexpr CAmount Contract::STANDARD_BURN_AMOUNT; // for clang Contract::Contract() : m_version(Contract::CURRENT_VERSION) @@ -546,7 +547,7 @@ bool Contract::RequiresMasterKey() const } } -int64_t Contract::RequiredBurnAmount() const +CAmount Contract::RequiredBurnAmount() const { return m_body.m_payload->RequiredBurnAmount(); } diff --git a/src/gridcoin/contract/contract.h b/src/gridcoin/contract/contract.h index aa7c4144ef..cb880ffb38 100644 --- a/src/gridcoin/contract/contract.h +++ b/src/gridcoin/contract/contract.h @@ -4,6 +4,7 @@ #pragma once +#include "amount.h" #include "gridcoin/contract/payload.h" #include "gridcoin/support/enumbytes.h" #include "serialize.h" @@ -49,10 +50,7 @@ class Contract //! \brief The amount of coin set for a burn output in a transaction that //! broadcasts a contract in units of 1/100000000 GRC. //! - // TODO: remove redefinition of the COIN constant when porting amount.h - // from Bitcoin: - // - static constexpr int64_t STANDARD_BURN_AMOUNT = 0.5 * 100000000; + static constexpr CAmount STANDARD_BURN_AMOUNT = 0.5 * COIN; //! //! \brief A contract type from a transaction message. @@ -294,7 +292,7 @@ class Contract //! //! \return Burn fee in units of 1/100000000 GRC. //! - int64_t RequiredBurnAmount() const; + CAmount RequiredBurnAmount() const; //! //! \brief Determine whether the instance represents a complete contract. diff --git a/src/gridcoin/contract/message.cpp b/src/gridcoin/contract/message.cpp index 3585528233..e3e7184d8a 100644 --- a/src/gridcoin/contract/message.cpp +++ b/src/gridcoin/contract/message.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" #include "gridcoin/contract/message.h" #include "gridcoin/contract/contract.h" #include "script.h" @@ -60,10 +61,10 @@ bool SelectMasterInputOutput(CCoinControl& coin_control) //! //! \return \c true if coin selection succeeded. //! -bool CreateContractTx(CWalletTx& wtx_out, CReserveKey reserve_key, int64_t burn_fee) +bool CreateContractTx(CWalletTx& wtx_out, CReserveKey reserve_key, CAmount burn_fee) { CCoinControl coin_control_out; - int64_t applied_fee_out; // Unused + CAmount applied_fee_out; // Unused bool admin = false; // If the input transaction already selected some inputs, ensure that we @@ -120,8 +121,8 @@ std::string SendContractTx(CWalletTx& wtx_new) return strError; } - int64_t balance = pwalletMain->GetBalance(); - int64_t burn_fee = 0; + CAmount balance = pwalletMain->GetBalance(); + CAmount burn_fee = 0; for (const auto& contract : wtx_new.vContracts) { burn_fee += contract.RequiredBurnAmount(); diff --git a/src/gridcoin/contract/payload.h b/src/gridcoin/contract/payload.h index 6dc2face72..0179cf211a 100644 --- a/src/gridcoin/contract/payload.h +++ b/src/gridcoin/contract/payload.h @@ -4,6 +4,7 @@ #pragma once +#include "amount.h" #include "streams.h" #include @@ -125,7 +126,7 @@ class IContractPayload //! //! \return Burn fee in units of 1/100000000 GRC. //! - virtual int64_t RequiredBurnAmount() const = 0; + virtual CAmount RequiredBurnAmount() const = 0; //! //! \brief Serialize the contract to the provided file. diff --git a/src/gridcoin/project.h b/src/gridcoin/project.h index ffd6d76688..5301a34f08 100644 --- a/src/gridcoin/project.h +++ b/src/gridcoin/project.h @@ -4,6 +4,7 @@ #pragma once +#include "amount.h" #include "gridcoin/contract/handler.h" #include "gridcoin/contract/payload.h" #include "serialize.h" @@ -120,7 +121,7 @@ class Project : public IContractPayload //! //! \return Burn fee in units of 1/100000000 GRC. //! - int64_t RequiredBurnAmount() const override + CAmount RequiredBurnAmount() const override { return Contract::STANDARD_BURN_AMOUNT; } diff --git a/src/gridcoin/researcher.cpp b/src/gridcoin/researcher.cpp index 826e017167..8b3b521d0b 100644 --- a/src/gridcoin/researcher.cpp +++ b/src/gridcoin/researcher.cpp @@ -1273,7 +1273,7 @@ bool Researcher::HasRAC() const return false; } -int64_t Researcher::Accrual() const +CAmount Researcher::Accrual() const { const CpidOption cpid = m_mining_id.TryCpid(); diff --git a/src/gridcoin/researcher.h b/src/gridcoin/researcher.h index 130a2433b6..25917089f6 100644 --- a/src/gridcoin/researcher.h +++ b/src/gridcoin/researcher.h @@ -4,6 +4,7 @@ #pragma once +#include "amount.h" #include "key.h" #include "gridcoin/cpid.h" @@ -498,7 +499,7 @@ class Researcher //! //! \return Research reward accrual in units of 1/100000000 GRC. //! - int64_t Accrual() const; + CAmount Accrual() const; //! //! \brief Get a value that indicates how the wallet participates in the diff --git a/src/gridcoin/staking/difficulty.cpp b/src/gridcoin/staking/difficulty.cpp index 88c1b36e2c..14af0390e0 100644 --- a/src/gridcoin/staking/difficulty.cpp +++ b/src/gridcoin/staking/difficulty.cpp @@ -3,6 +3,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" #include "bignum.h" #include "init.h" #include "gridcoin/staking/difficulty.h" @@ -283,7 +284,7 @@ double GRC::GetEstimatedTimetoStake(bool ignore_staking_status, double dDiff, do return result; } - int64_t nValue = 0; + CAmount nValue = 0; int64_t nCurrentTime = GetAdjustedTime(); LogPrint(BCLog::LogFlags::NOISY, "GetEstimatedTimetoStake debug: nCurrentTime = %i", nCurrentTime); @@ -295,7 +296,7 @@ double GRC::GetEstimatedTimetoStake(bool ignore_staking_status, double dDiff, do const int ETTS_TIMESTAMP_MASK = (16 * (GRC::STAKE_TIMESTAMP_MASK + 1)) - 1; LogPrint(BCLog::LogFlags::NOISY, "GetEstimatedTimetoStake debug: ETTS_TIMESTAMP_MASK = %x", ETTS_TIMESTAMP_MASK); - int64_t BalanceAvailForStaking = 0; + CAmount BalanceAvailForStaking = 0; std::vector vCoins; { @@ -319,7 +320,7 @@ double GRC::GetEstimatedTimetoStake(bool ignore_staking_status, double dDiff, do // An efficient local structure to store the UTXO's with the bare minimum info we need. - typedef std::vector< std::pair > vCoinsExt; + typedef std::vector< std::pair > vCoinsExt; vCoinsExt vUTXO; // A local ordered set to store the unique "bins" corresponding to the UTXO transaction times. We are going to use this // for the outer loop. @@ -360,7 +361,7 @@ double GRC::GetEstimatedTimetoStake(bool ignore_staking_status, double dDiff, do // nValue >= 1250000. if (BalanceAvailForStaking >= nValue && nValue >= 1250000) { - vUTXO.push_back(std::pair( nTime, nValue)); + vUTXO.push_back(std::pair( nTime, nValue)); LogPrint(BCLog::LogFlags::NOISY, "GetEstimatedTimetoStake debug: pair (relative to current time: <%i, %i>", nTime - nCurrentTime, nValue); // Only record a time below if it is after nCurrentTime, because UTXO's that have matured already are already stakeable and can be grouped (will be found) diff --git a/src/gridcoin/staking/kernel.cpp b/src/gridcoin/staking/kernel.cpp index 8600ce50ec..479f15bbb0 100644 --- a/src/gridcoin/staking/kernel.cpp +++ b/src/gridcoin/staking/kernel.cpp @@ -3,6 +3,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" #include "arith_uint256.h" #include "gridcoin/staking/kernel.h" #include "txdb.h" @@ -529,7 +530,7 @@ uint256 GRC::CalculateStakeHashV8( int64_t GRC::CalculateStakeWeightV8(const CTransaction &CoinTx, unsigned CoinTxN) { - int64_t nValueIn = CoinTx.vout[CoinTxN].nValue; + CAmount nValueIn = CoinTx.vout[CoinTxN].nValue; nValueIn /= 1250000; return nValueIn; } diff --git a/src/gridcoin/staking/kernel.h b/src/gridcoin/staking/kernel.h index 4964a80423..9e6575532b 100644 --- a/src/gridcoin/staking/kernel.h +++ b/src/gridcoin/staking/kernel.h @@ -5,6 +5,7 @@ #pragma once +#include "amount.h" #include "main.h" namespace GRC { diff --git a/src/gridcoin/staking/reward.cpp b/src/gridcoin/staking/reward.cpp index 6682d674fe..ff37d8863d 100644 --- a/src/gridcoin/staking/reward.cpp +++ b/src/gridcoin/staking/reward.cpp @@ -2,19 +2,19 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" #include "gridcoin/appcache.h" #include "gridcoin/staking/reward.h" #include "main.h" namespace { -int64_t GetCoinYearReward(int64_t nTime) +CAmount GetCoinYearReward(int64_t nTime) { // Gridcoin Global Interest Rate Schedule - int64_t INTEREST = 9; + CAmount INTEREST = 9; if (nTime >= 1410393600 && nTime <= 1417305600) INTEREST = 9 * CENT; // 09% between inception and 11-30-2014 - if (nTime >= 1417305600 && nTime <= 1419897600) INTEREST = 8 * CENT; // 08% between 11-30-2014 and 12-30-2014 - if (nTime >= 1419897600 && nTime <= 1422576000) INTEREST = 8 * CENT; // 08% between 12-30-2014 and 01-30-2015 + if (nTime >= 1417305600 && nTime <= 1422576000) INTEREST = 8 * CENT; // 08% between 11-30-2014 and 01-30-2015 if (nTime >= 1422576000 && nTime <= 1425254400) INTEREST = 7 * CENT; // 07% between 01-30-2015 and 02-30-2015 if (nTime >= 1425254400 && nTime <= 1427673600) INTEREST = 6 * CENT; // 06% between 02-30-2015 and 03-30-2015 if (nTime >= 1427673600 && nTime <= 1430352000) INTEREST = 5 * CENT; // 05% between 03-30-2015 and 04-30-2015 @@ -30,17 +30,17 @@ int64_t GetCoinYearReward(int64_t nTime) // Functions // ----------------------------------------------------------------------------- -int64_t GRC::GetConstantBlockReward(const CBlockIndex* index) +CAmount GRC::GetConstantBlockReward(const CBlockIndex* index) { // The constant block reward is set to a default, voted on value, but this can // be overridden using an admin message. This allows us to change the reward // amount without having to release a mandatory with updated rules. In the case // there is a breach or leaked admin keys the rewards are clamped to twice that // of the default value. - const int64_t MIN_CBR = 0; - const int64_t MAX_CBR = DEFAULT_CBR * 2; + const CAmount MIN_CBR = 0; + const CAmount MAX_CBR = DEFAULT_CBR * 2; - int64_t reward = DEFAULT_CBR; + CAmount reward = DEFAULT_CBR; AppCacheEntry oCBReward = ReadCache(Section::PROTOCOL, "blockreward1"); //TODO: refactor the expire checking to subroutine @@ -55,7 +55,7 @@ int64_t GRC::GetConstantBlockReward(const CBlockIndex* index) return reward; } -int64_t GRC::GetProofOfStakeReward( +CAmount GRC::GetProofOfStakeReward( const uint64_t nCoinAge, const int64_t nTime, const CBlockIndex* const pindexLast) diff --git a/src/gridcoin/staking/reward.h b/src/gridcoin/staking/reward.h index 26abfecc35..2e9779de45 100644 --- a/src/gridcoin/staking/reward.h +++ b/src/gridcoin/staking/reward.h @@ -4,13 +4,15 @@ #pragma once +#include "amount.h" + class CBlockIndex; namespace GRC { -int64_t GetProofOfStakeReward( +CAmount GetProofOfStakeReward( uint64_t nCoinAge, int64_t nTime, const CBlockIndex* const pindexLast); -int64_t GetConstantBlockReward(const CBlockIndex* index); +CAmount GetConstantBlockReward(const CBlockIndex* index); } // namespace GRC diff --git a/src/gridcoin/tally.cpp b/src/gridcoin/tally.cpp index 78bdb47845..53442ad7e1 100644 --- a/src/gridcoin/tally.cpp +++ b/src/gridcoin/tally.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" #include "chainparams.h" #include "main.h" #include "gridcoin/accrual/newbie.h" @@ -748,7 +749,7 @@ CBlockIndex* Tally::FindLegacyTrigger(CBlockIndex* pindex) return pindex; } -int64_t Tally::MaxEmission(const int64_t payment_time) +CAmount Tally::MaxEmission(const int64_t payment_time) { return NetworkTally::MaxEmission(payment_time) * COIN; } @@ -772,7 +773,7 @@ const ResearchAccount& Tally::GetAccount(const Cpid cpid) return g_researcher_tally.GetAccount(cpid); } -int64_t Tally::GetAccrual( +CAmount Tally::GetAccrual( const Cpid cpid, const int64_t payment_time, const CBlockIndex* const last_block_ptr) @@ -914,7 +915,7 @@ void Tally::LegacyRecount(const CBlockIndex* pindex) g_network_tally.ApplySuperblock(Quorum::CurrentSuperblock()); } - int64_t total_research_subsidy = 0; + CAmount total_research_subsidy = 0; while (pindex->nHeight > min_depth) { if (!pindex->pprev) { diff --git a/src/gridcoin/tally.h b/src/gridcoin/tally.h index ed550237d5..71454a5dbe 100644 --- a/src/gridcoin/tally.h +++ b/src/gridcoin/tally.h @@ -4,6 +4,7 @@ #pragma once +#include "amount.h" #include "gridcoin/account.h" #include "gridcoin/accrual/computer.h" @@ -78,7 +79,7 @@ class Tally //! //! \return Maximum daily emission in units of 1/100000000 GRC. //! - static int64_t MaxEmission(const int64_t payment_time); + static CAmount MaxEmission(const int64_t payment_time); //! //! \brief Get the current network magnitude unit. @@ -116,7 +117,7 @@ class Tally //! //! \return Research reward accrual in units of 1/100000000 GRC. //! - static int64_t GetAccrual( + static CAmount GetAccrual( const Cpid cpid, const int64_t payment_time, const CBlockIndex* const last_block_ptr); diff --git a/src/gridcoin/voting/builders.cpp b/src/gridcoin/voting/builders.cpp index 74a28b634a..21dc59cf06 100644 --- a/src/gridcoin/voting/builders.cpp +++ b/src/gridcoin/voting/builders.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" #include "init.h" #include "main.h" #include "gridcoin/beacon.h" @@ -46,8 +47,8 @@ class AddressOutputs public: CKeyID m_key_id; //!< Address of the outputs. std::vector m_outpoints; //!< Outputs for the address. - std::vector m_amounts; //!< Amounts for each output. - int64_t m_total_amount; //!< Total amount of the outputs. + std::vector m_amounts; //!< Amounts for each output. + CAmount m_total_amount; //!< Total amount of the outputs. //! //! \brief Initialize an output address grouping. @@ -694,7 +695,7 @@ class PollClaimBuilder static bool TryTrimAddress(AddressOutputs& address) { std::vector& outpoints = address.m_outpoints; - std::vector& amounts = address.m_amounts; + std::vector& amounts = address.m_amounts; while (outpoints.size() > PollEligibilityClaim::MAX_OUTPOINTS) { address.m_total_amount -= amounts.back(); @@ -812,9 +813,9 @@ void SelectFinalInputs(CWallet& wallet, CWalletTx& tx) // contract.SharePayload().As().m_claim.ExpandDummySignatures(); - const int64_t burn_fee = contract.RequiredBurnAmount(); + const CAmount burn_fee = contract.RequiredBurnAmount(); CReserveKey reserve_key(&wallet); // unused - int64_t out_applied_fee; + CAmount out_applied_fee; if (!wallet.CreateTransaction( CScript() << OP_RETURN, diff --git a/src/gridcoin/voting/claims.h b/src/gridcoin/voting/claims.h index 8bfa230522..6ca988eb02 100644 --- a/src/gridcoin/voting/claims.h +++ b/src/gridcoin/voting/claims.h @@ -4,6 +4,7 @@ #pragma once +#include "amount.h" #include "key.h" #include "gridcoin/cpid.h" #include "gridcoin/magnitude.h" @@ -88,7 +89,7 @@ class AddressClaim //! //! \return Burn fee in units of 1/100000000 GRC. //! - int64_t RequiredBurnAmount() const + CAmount RequiredBurnAmount() const { // 0.001 GRC per claimed UTXO: return m_outpoints.size() * COIN / 1000; @@ -182,9 +183,9 @@ class BalanceClaim //! //! \return Burn fee in units of 1/100000000 GRC. //! - int64_t RequiredBurnAmount() const + CAmount RequiredBurnAmount() const { - int64_t amount = 0; + CAmount amount = 0; for (const auto& claim : m_address_claims) { // 0.01 per address + a scaled fee based on the number of outputs: @@ -246,7 +247,7 @@ class MagnitudeClaim //! //! \return Burn fee in units of 1/100000000 GRC. //! - int64_t RequiredBurnAmount() const + CAmount RequiredBurnAmount() const { if (m_mining_id.Which() == MiningId::Kind::CPID) { // Flat 0.01 GRC: @@ -351,7 +352,7 @@ class PollEligibilityClaim //! //! \return Burn fee in units of 1/100000000 GRC. //! - int64_t RequiredBurnAmount() const + CAmount RequiredBurnAmount() const { // A scaled fee based on the number of claimed outputs: return m_address_claim.RequiredBurnAmount(); @@ -420,7 +421,7 @@ class VoteWeightClaim //! //! \return Burn fee in units of 1/100000000 GRC. //! - int64_t RequiredBurnAmount() const + CAmount RequiredBurnAmount() const { return m_magnitude_claim.RequiredBurnAmount() + m_balance_claim.RequiredBurnAmount(); diff --git a/src/gridcoin/voting/fwd.h b/src/gridcoin/voting/fwd.h index 7c63391dd2..3b86ba190a 100644 --- a/src/gridcoin/voting/fwd.h +++ b/src/gridcoin/voting/fwd.h @@ -4,6 +4,8 @@ #pragma once +#include "amount.h" + #include namespace GRC { @@ -19,7 +21,7 @@ using PollResultOption = boost::optional; //! //! \brief The unspent amount that a poll creator must hold in an address. //! -constexpr int64_t POLL_REQUIRED_BALANCE = 100000 * COIN; +constexpr CAmount POLL_REQUIRED_BALANCE = 100000 * COIN; //! //! \brief The maximum number of choices that a poll can contain. diff --git a/src/gridcoin/voting/payloads.h b/src/gridcoin/voting/payloads.h index dfaf921d74..3086ace2cb 100644 --- a/src/gridcoin/voting/payloads.h +++ b/src/gridcoin/voting/payloads.h @@ -134,7 +134,7 @@ class PollPayload : public IContractPayload //! //! \return Burn fee in units of 1/100000000 GRC. //! - int64_t RequiredBurnAmount() const override + CAmount RequiredBurnAmount() const override { // 50 GRC + a scaled fee based on the number of claimed outputs: return (50 * COIN) + m_claim.RequiredBurnAmount(); diff --git a/src/gridcoin/voting/registry.cpp b/src/gridcoin/voting/registry.cpp index 00a5d13dce..5345e2e743 100644 --- a/src/gridcoin/voting/registry.cpp +++ b/src/gridcoin/voting/registry.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" #include "main.h" #include "gridcoin/contract/contract.h" #include "gridcoin/voting/payloads.h" @@ -107,7 +108,7 @@ class PollClaimValidator } const CTxDestination address = claim.m_public_key.GetID(); - int64_t amount = 0; + CAmount amount = 0; for (const auto& txo : claim.m_outpoints) { amount += Resolve(txo, address); diff --git a/src/gridcoin/voting/result.cpp b/src/gridcoin/voting/result.cpp index 82cc444e22..bfa05600d2 100644 --- a/src/gridcoin/voting/result.cpp +++ b/src/gridcoin/voting/result.cpp @@ -284,9 +284,9 @@ class VoteResolver //! //! \return Claimed amount in units of 1/100000000 GRC. //! - int64_t Resolve(const BalanceClaim& claim, const ClaimMessage& message) + CAmount Resolve(const BalanceClaim& claim, const ClaimMessage& message) { - int64_t amount = 0; + CAmount amount = 0; for (const auto& address_claim : claim.m_address_claims) { amount += Resolve(address_claim, message); @@ -306,7 +306,7 @@ class VoteResolver //! \throws InvalidVoteError If the vote fails to validate or if an IO //! error occurs. //! - int64_t Resolve(const AddressClaim& claim, const ClaimMessage& message) + CAmount Resolve(const AddressClaim& claim, const ClaimMessage& message) { if (!claim.VerifySignature(message)) { LogPrint(LogFlags::VOTE, "%s: bad address signature", __func__); @@ -314,7 +314,7 @@ class VoteResolver } const CTxDestination address = claim.m_public_key.GetID(); - int64_t amount = 0; + CAmount amount = 0; for (const auto& txo : claim.m_outpoints) { amount += Resolve(txo, address); @@ -334,7 +334,7 @@ class VoteResolver //! \throws InvalidVoteError If the vote fails to validate or if an IO //! error occurs. //! - int64_t Resolve(const COutPoint& txo, const CTxDestination& address) + CAmount Resolve(const COutPoint& txo, const CTxDestination& address) { if (m_seen_txos.find(txo) != m_seen_txos.end()) { LogPrint(LogFlags::VOTE, "%s: duplicate txo", __func__); @@ -447,10 +447,10 @@ class VoteResolver //! \throws InvalidVoteError If the vote fails to validate or if an IO //! error occurs. //! - int64_t ResolveAmount( + CAmount ResolveAmount( const CTxDestination& address, const CDiskTxPos& disk_pos, - int64_t amount) + CAmount amount) { // Although this routine could make a nice recursive algorithm, we need // to ensure that it won't overflow the stack. Instead, we implement an @@ -461,9 +461,9 @@ class VoteResolver struct TxoFrame { CDiskTxPos m_pos; - int64_t m_amount; + CAmount m_amount; - TxoFrame(const CDiskTxPos pos, int64_t amount) + TxoFrame(const CDiskTxPos pos, CAmount amount) : m_pos(pos), m_amount(amount) { } @@ -529,7 +529,7 @@ class VoteResolver const uint256 tx_hash = tx.GetHash(); // Intermediate mapping of output offsets to amounts: - std::vector> next_txos; + std::vector> next_txos; // Find outputs for the same address: for (uint32_t i = 0; i < tx.vout.size(); ++i) { @@ -1024,7 +1024,7 @@ SuperblockPtr ResolveSuperblockForPoll(const Poll& poll) //! \return Money supply as of the last block in the poll window in units of //! 1/100000000 GRC. //! -int64_t ResolveMoneySupplyForPoll(const Poll& poll) +CAmount ResolveMoneySupplyForPoll(const Poll& poll) { if (!poll.Expired(pindexBest->nTime)) { return pindexBest->nMoneySupply; diff --git a/src/gridcoin/voting/vote.h b/src/gridcoin/voting/vote.h index 10d9773b10..f71f32c458 100644 --- a/src/gridcoin/voting/vote.h +++ b/src/gridcoin/voting/vote.h @@ -4,6 +4,7 @@ #pragma once +#include "amount.h" #include "gridcoin/contract/payload.h" #include "gridcoin/voting/claims.h" #include "serialize.h" @@ -140,7 +141,7 @@ class Vote : public IContractPayload //! //! \return Burn fee in units of 1/100000000 GRC. //! - int64_t RequiredBurnAmount() const override + CAmount RequiredBurnAmount() const override { // 0.01 GRC for the vote contract + the scaled claim fee: return (COIN / 100) + m_claim.RequiredBurnAmount(); @@ -276,13 +277,8 @@ class LegacyVote : public IContractPayload //! //! \return Burn fee in units of 1/100000000 GRC. //! - int64_t RequiredBurnAmount() const override + CAmount RequiredBurnAmount() const override { - // TODO: remove redefinition of this constant when porting amount.h - // from Bitcoin: - // - constexpr int64_t MAX_MONEY = 2000000000 * COIN; - // Prevent users from sending this contract manually: return MAX_MONEY; } diff --git a/src/main.cpp b/src/main.cpp index 4572ff0a2c..d11645dcfe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" #include "util.h" #include "net.h" #include "streams.h" diff --git a/src/main.h b/src/main.h index 9cd44c327a..0f8c299ec4 100644 --- a/src/main.h +++ b/src/main.h @@ -5,6 +5,7 @@ #ifndef BITCOIN_MAIN_H #define BITCOIN_MAIN_H +#include "amount.h" #include "arith_uint256.h" #include "chainparams.h" #include "consensus/consensus.h" @@ -42,9 +43,7 @@ typedef boost::optional ClaimOption; } static const int64_t DEFAULT_CBR = 10 * COIN; -/** No amount larger than this (in satoshi) is valid */ -static const int64_t MAX_MONEY = 2000000000 * COIN; -inline bool MoneyRange(int64_t nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } + /** Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp. */ static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC diff --git a/src/miner.cpp b/src/miner.cpp index c877c416ad..682ff4e97f 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -4,6 +4,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" #include "txdb.h" #include "miner.h" #include "main.h" diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 2da2265a10..d8066267cf 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -3,6 +3,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" #include "init.h" #include "sync.h" #include "ui_interface.h" diff --git a/src/util.cpp b/src/util.cpp index 095d5fc043..eaa7897252 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -3,6 +3,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" #include "netbase.h" // for AddTimeData #include "sync.h" #include "version.h" diff --git a/src/util.h b/src/util.h index 94ece2dd3d..fceb917a9b 100644 --- a/src/util.h +++ b/src/util.h @@ -50,10 +50,6 @@ #include #include -static const int64_t COIN = 100000000; -static const int64_t COIN_PLACES = 8; -static const int64_t CENT = 1000000; - #define BEGIN(a) ((char*)&(a)) #define END(a) ((char*)&((&(a))[1])) #define UBEGIN(a) ((unsigned char*)&(a)) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 5bd8507a10..5b58f10bbd 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -9,6 +9,8 @@ #include #include #include + +#include "amount.h" #include "gridcoin/staking/status.h" #include "main.h" #include "key.h" From 9940414279a912718303a2080c036000c9de2141 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Wed, 21 Oct 2020 06:38:28 -0500 Subject: [PATCH 42/53] Normalize boost::filesystem to fs namespace This replaces remaining references to the boost::filesystem namespace with fs. The change abstracts filesystem operations from a particular library and prepares the codebase for newer Bitcoin code. It may also help to facilitate a transition to std::filesystem in the future. --- src/gridcoin/backup.cpp | 48 ++++++++++++-------------- src/gridcoin/backup.h | 7 ++-- src/gridcoin/scraper/http.cpp | 2 +- src/gridcoin/scraper/scraper.cpp | 8 +++-- src/gridcoin/scraper/scraper.h | 16 --------- src/gridcoin/upgrade.cpp | 37 +++++++++----------- src/gridcoinresearchd.cpp | 2 +- src/init.cpp | 14 +++----- src/logging.cpp | 1 - src/main.cpp | 4 +-- src/qt/bitcoin.cpp | 2 +- src/qt/bitcoingui.cpp | 3 -- src/qt/diagnosticsdialog.cpp | 9 +++-- src/qt/guiutil.cpp | 38 +++++++++----------- src/qt/upgradeqt.cpp | 10 +++--- src/rpcclient.cpp | 2 -- src/rpcdataacq.cpp | 7 ++-- src/rpcmining.cpp | 4 +-- src/rpcprotocol.cpp | 2 -- src/rpcrawtransaction.cpp | 4 +-- src/rpcserver.cpp | 14 ++++---- src/test/gridcoin/researcher_tests.cpp | 23 ++++++------ src/test/script_tests.cpp | 2 -- src/txdb-leveldb.cpp | 13 ++++--- src/util.h | 3 -- src/wallet/rpcdump.cpp | 13 +++---- src/wallet/walletdb.cpp | 2 -- 27 files changed, 118 insertions(+), 172 deletions(-) diff --git a/src/gridcoin/backup.cpp b/src/gridcoin/backup.cpp index 5bbc133c85..5049ebe666 100644 --- a/src/gridcoin/backup.cpp +++ b/src/gridcoin/backup.cpp @@ -9,17 +9,13 @@ #include "util.h" #include "util/time.h" -#include - -#include #include using namespace GRC; -using namespace boost; -boost::filesystem::path GRC::GetBackupPath() +fs::path GRC::GetBackupPath() { - filesystem::path defaultDir = GetDataDir() / "walletbackups"; + fs::path defaultDir = GetDataDir() / "walletbackups"; return GetArg("-backupdir", defaultDir.string()); } @@ -32,7 +28,7 @@ std::string GRC::GetBackupFilename(const std::string& basename, const std::strin char boTime[200]; strftime(boTime, sizeof(boTime), "%Y-%m-%dT%H-%M-%S", blTime); std::string sBackupFilename; - filesystem::path rpath; + fs::path rpath; sBackupFilename = basename + "-" + std::string(boTime); if (!suffix.empty()) sBackupFilename = sBackupFilename + "-" + suffix; @@ -120,22 +116,22 @@ bool GRC::BackupConfigFile(const std::string& strDest) { // Check to see if there is a parent_path in strDest to support custom locations by ui - bug fix - filesystem::path ConfigSource = GetConfigFile(); - filesystem::path ConfigTarget = strDest; - filesystem::create_directories(ConfigTarget.parent_path()); + fs::path ConfigSource = GetConfigFile(); + fs::path ConfigTarget = strDest; + fs::create_directories(ConfigTarget.parent_path()); try { #if BOOST_VERSION >= 107400 - filesystem::copy_file(ConfigSource, ConfigTarget, filesystem::copy_options::overwrite_existing); + fs::copy_file(ConfigSource, ConfigTarget, fs::copy_options::overwrite_existing); #elif BOOST_VERSION >= 104000 - filesystem::copy_file(ConfigSource, ConfigTarget, filesystem::copy_option::overwrite_if_exists); + fs::copy_file(ConfigSource, ConfigTarget, fs::copy_option::overwrite_if_exists); #else - filesystem::copy_file(ConfigSource, ConfigTarget); + fs::copy_file(ConfigSource, ConfigTarget); #endif LogPrintf("BackupConfigFile: Copied gridcoinresearch.conf to %s", ConfigTarget.string()); return true; } - catch(const filesystem::filesystem_error &e) + catch(const fs::filesystem_error &e) { LogPrintf("BackupConfigFile: Error copying gridcoinresearch.conf to %s - %s", ConfigTarget.string(), e.what()); return false; @@ -159,23 +155,23 @@ bool GRC::BackupWallet(const CWallet& wallet, const std::string& strDest) bitdb.mapFileUseCount.erase(wallet.strWalletFile); // Copy wallet.dat - filesystem::path WalletSource = GetDataDir() / wallet.strWalletFile; - filesystem::path WalletTarget = strDest; - filesystem::create_directories(WalletTarget.parent_path()); - if (filesystem::is_directory(WalletTarget)) + fs::path WalletSource = GetDataDir() / wallet.strWalletFile; + fs::path WalletTarget = strDest; + fs::create_directories(WalletTarget.parent_path()); + if (fs::is_directory(WalletTarget)) WalletTarget /= wallet.strWalletFile; try { #if BOOST_VERSION >= 107400 - filesystem::copy_file(WalletSource, WalletTarget, filesystem::copy_options::overwrite_existing); + fs::copy_file(WalletSource, WalletTarget, fs::copy_options::overwrite_existing); #elif BOOST_VERSION >= 104000 - filesystem::copy_file(WalletSource, WalletTarget, filesystem::copy_option::overwrite_if_exists); + fs::copy_file(WalletSource, WalletTarget, fs::copy_option::overwrite_if_exists); #else - filesystem::copy_file(WalletSource, WalletTarget); + fs::copy_file(WalletSource, WalletTarget); #endif LogPrintf("BackupWallet: Copied wallet.dat to %s", WalletTarget.string()); } - catch(const filesystem::filesystem_error &e) { + catch(const fs::filesystem_error &e) { LogPrintf("BackupWallet: Error copying wallet.dat to %s - %s", WalletTarget.string(), e.what()); return false; } @@ -186,7 +182,7 @@ bool GRC::BackupWallet(const CWallet& wallet, const std::string& strDest) return false; } -bool GRC::MaintainBackups(filesystem::path wallet_backup_path, std::vector backup_file_type, +bool GRC::MaintainBackups(fs::path wallet_backup_path, std::vector backup_file_type, unsigned int retention_by_num, unsigned int retention_by_days, std::vector& files_removed) { // Backup file retention maintainer. Adapted from the scraper/main log archiver core. @@ -327,7 +323,7 @@ bool GRC::MaintainBackups(filesystem::path wallet_backup_path, std::vector -#include class CWallet; namespace GRC { std::string GetBackupFilename(const std::string& basename, const std::string& suffix = ""); -boost::filesystem::path GetBackupPath(); +fs::path GetBackupPath(); bool BackupsEnabled(); int64_t GetBackupInterval(); void RunBackupJob(); bool BackupConfigFile(const std::string& strDest); -bool MaintainBackups(boost::filesystem::path wallet_backup_path, std::vector backup_file_type, +bool MaintainBackups(fs::path wallet_backup_path, std::vector backup_file_type, unsigned int retention_by_num, unsigned int retention_by_days, std::vector& files_removed); bool BackupWallet(const CWallet& wallet, const std::string& strDest); bool BackupPrivateKeys(const CWallet& wallet, std::string& sTarget, std::string& sErrors); diff --git a/src/gridcoin/scraper/http.cpp b/src/gridcoin/scraper/http.cpp index 174003f44f..fc931fe008 100644 --- a/src/gridcoin/scraper/http.cpp +++ b/src/gridcoin/scraper/http.cpp @@ -303,7 +303,7 @@ void Http::DownloadSnapshot() { std::string url = GetArg("-snapshoturl", "https://download.gridcoin.us/download/downloadstake/signed/snapshot.zip"); - boost::filesystem::path destination = GetDataDir() / "snapshot.zip"; + fs::path destination = GetDataDir() / "snapshot.zip"; ScopedFile fp(fsbridge::fopen(destination, "wb"), &fclose); diff --git a/src/gridcoin/scraper/scraper.cpp b/src/gridcoin/scraper/scraper.cpp index 94ba2d70ec..e73e37fd49 100755 --- a/src/gridcoin/scraper/scraper.cpp +++ b/src/gridcoin/scraper/scraper.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include using namespace GRC; +namespace boostio = boost::iostreams; // These are initialized empty. GetDataDir() cannot be called here. It is too early. fs::path pathDataDir = {}; @@ -2401,7 +2403,7 @@ uint256 GetFileHash(const fs::path& inputfile) return nHash; // use file size to size memory buffer - int dataSize = boost::filesystem::file_size(inputfile); + int dataSize = fs::file_size(inputfile); std::vector vchData; vchData.resize(dataSize); @@ -4030,7 +4032,7 @@ bool ScraperSendFileManifestContents(CBitcoinAddress& Address, CKey& Key) } // use file size to size memory buffer - int dataSize = boost::filesystem::file_size(inputfilewpath); + int dataSize = fs::file_size(inputfilewpath); std::vector vchData; vchData.resize(dataSize); @@ -4121,7 +4123,7 @@ bool ScraperSendFileManifestContents(CBitcoinAddress& Address, CKey& Key) } // use file size to size memory buffer - int dataSize = boost::filesystem::file_size(inputfilewpath); + int dataSize = fs::file_size(inputfilewpath); std::vector vchData; vchData.resize(dataSize); diff --git a/src/gridcoin/scraper/scraper.h b/src/gridcoin/scraper/scraper.h index 8111bd86b2..7773da05fd 100644 --- a/src/gridcoin/scraper/scraper.h +++ b/src/gridcoin/scraper/scraper.h @@ -5,20 +5,12 @@ #pragma once #include -#include #include #include #include #include #include #include -#include -#include -#include -#include -#include -#include -#include #include "sync.h" #include "wallet/wallet.h" @@ -31,14 +23,6 @@ #include "gridcoin/scraper/fwd.h" #include "gridcoin/superblock.h" -/********************* -* Scraper Namespace * -*********************/ - -namespace fs = boost::filesystem; -namespace boostio = boost::iostreams; - - /********************* * Global Defaults * *********************/ diff --git a/src/gridcoin/upgrade.cpp b/src/gridcoin/upgrade.cpp index f0e1914be3..f66f813c8c 100644 --- a/src/gridcoin/upgrade.cpp +++ b/src/gridcoin/upgrade.cpp @@ -10,14 +10,11 @@ #include #include #include -#include #include #include -#include #include #include -#include #include using namespace GRC; @@ -311,7 +308,7 @@ bool Upgrade::VerifySHA256SUM() SHA256_CTX ctx; SHA256_Init(&ctx); - boost::filesystem::path fileloc = GetDataDir() / "snapshot.zip"; + fs::path fileloc = GetDataDir() / "snapshot.zip"; unsigned char *buffer[32768]; int bytesread = 0; @@ -351,31 +348,31 @@ bool Upgrade::VerifySHA256SUM() bool Upgrade::CleanupBlockchainData() { - boost::filesystem::path CleanupPath = GetDataDir(); + fs::path CleanupPath = GetDataDir(); // We must delete previous blockchain data // txleveldb // blk*.dat - boost::filesystem::directory_iterator IterEnd; + fs::directory_iterator IterEnd; try { // Remove the files. We iterate as we know blk* will exist more and more in future as well - for (boost::filesystem::directory_iterator Iter(CleanupPath); Iter != IterEnd; ++Iter) + for (fs::directory_iterator Iter(CleanupPath); Iter != IterEnd; ++Iter) { - if (boost::filesystem::is_directory(Iter->path())) + if (fs::is_directory(Iter->path())) { size_t DirLoc = Iter->path().string().find("txleveldb"); if (DirLoc != std::string::npos) - if (!boost::filesystem::remove_all(*Iter)) + if (!fs::remove_all(*Iter)) return false; continue; } - else if (boost::filesystem::is_regular_file(*Iter)) + else if (fs::is_regular_file(*Iter)) { size_t FileLoc = Iter->path().filename().string().find("blk"); @@ -384,7 +381,7 @@ bool Upgrade::CleanupBlockchainData() std::string filetocheck = Iter->path().filename().string(); // Check it ends with .dat and starts with blk if (filetocheck.substr(0, 3) == "blk" && filetocheck.substr(filetocheck.length() - 4, 4) == ".dat") - if (!boost::filesystem::remove(*Iter)) + if (!fs::remove(*Iter)) return false; } continue; @@ -392,7 +389,7 @@ bool Upgrade::CleanupBlockchainData() } } - catch (boost::filesystem::filesystem_error &ex) + catch (fs::filesystem_error &ex) { LogPrintf("Snapshot (CleanupBlockchainData): Exception occurred: %s", ex.what()); @@ -406,7 +403,7 @@ bool Upgrade::ExtractSnapshot() { std::string ArchiveFileString = GetDataDir().string() + "/snapshot.zip"; const char* ArchiveFile = ArchiveFileString.c_str(); - boost::filesystem::path ExtractPath = GetDataDir(); + fs::path ExtractPath = GetDataDir(); struct zip* ZipArchive; struct zip_file* ZipFile; struct zip_stat ZipStat; @@ -463,7 +460,7 @@ bool Upgrade::ExtractSnapshot() { // Does this require a directory if (ZipStat.name[strlen(ZipStat.name) - 1] == '/') - boost::filesystem::create_directory(ExtractPath / ZipStat.name); + fs::create_directory(ExtractPath / ZipStat.name); else { @@ -478,7 +475,7 @@ bool Upgrade::ExtractSnapshot() return false; } - boost::filesystem::path ExtractFileString = ExtractPath / ZipStat.name; + fs::path ExtractFileString = ExtractPath / ZipStat.name; FILE* ExtractFile = fsbridge::fopen(ExtractFileString, "wb"); @@ -553,14 +550,14 @@ void Upgrade::DeleteSnapshot() // File is out of scope now check if it exists and if so delete it. try { - boost::filesystem::path snapshotpath = GetDataDir() / "snapshot.zip"; + fs::path snapshotpath = GetDataDir() / "snapshot.zip"; - if (boost::filesystem::exists(snapshotpath)) - if (boost::filesystem::is_regular_file(snapshotpath)) - boost::filesystem::remove(snapshotpath); + if (fs::exists(snapshotpath)) + if (fs::is_regular_file(snapshotpath)) + fs::remove(snapshotpath); } - catch (boost::filesystem::filesystem_error& e) + catch (fs::filesystem_error& e) { LogPrintf("Snapshot Downloader: Exception occurred while attempting to delete snapshot (%s)", e.code().message()); } diff --git a/src/gridcoinresearchd.cpp b/src/gridcoinresearchd.cpp index d65f6d2370..89c7c42dc5 100644 --- a/src/gridcoinresearchd.cpp +++ b/src/gridcoinresearchd.cpp @@ -90,7 +90,7 @@ bool AppInit(int argc, char* argv[]) return false; } - if (!boost::filesystem::is_directory(GetDataDir(false))) + if (!fs::is_directory(GetDataDir(false))) { fprintf(stderr, "Error: Specified directory does not exist\n"); Shutdown(NULL); diff --git a/src/init.cpp b/src/init.cpp index fe3e78b0d5..4fd7cbb045 100755 --- a/src/init.cpp +++ b/src/init.cpp @@ -16,9 +16,6 @@ #include "scheduler.h" #include "gridcoin/gridcoin.h" -#include -#include -#include #include #include @@ -37,7 +34,6 @@ bool IsConfigFileEmpty(); #endif using namespace std; -using namespace boost; CWallet* pwalletMain; CClientUIInterface uiInterface; extern bool fQtActive; @@ -108,7 +104,7 @@ void Shutdown(void* parg) StopNode(); bitdb.Flush(true); StopRPCThreads(); - boost::filesystem::remove(GetPidFile()); + fs::remove(GetPidFile()); UnregisterWallet(pwalletMain); delete pwalletMain; // close transaction database to prevent lock issue on restart @@ -744,7 +740,7 @@ bool AppInit2(ThreadHandlerPtr threads) return false; } - if (filesystem::exists(GetDataDir() / walletFileName)) + if (fs::exists(GetDataDir() / walletFileName)) { CDBEnv::VerifyResult r = bitdb.Verify(walletFileName.string(), CWalletDB::Recover); if (r == CDBEnv::RECOVER_OK) @@ -1047,13 +1043,13 @@ bool AppInit2(ThreadHandlerPtr threads) exit(0); } - filesystem::path pathBootstrap = GetDataDir() / "bootstrap.dat"; - if (filesystem::exists(pathBootstrap)) { + fs::path pathBootstrap = GetDataDir() / "bootstrap.dat"; + if (fs::exists(pathBootstrap)) { uiInterface.InitMessage(_("Importing bootstrap blockchain data file.")); FILE *file = fsbridge::fopen(pathBootstrap, "rb"); if (file) { - filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; + fs::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; LoadExternalBlockFile(file); RenameOver(pathBootstrap, pathBootstrapOld); } diff --git a/src/logging.cpp b/src/logging.cpp index d7befa462f..50532a42be 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -9,7 +9,6 @@ #include #include -#include #include #include diff --git a/src/main.cpp b/src/main.cpp index b75c6d0c0c..0a340ba93d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3287,7 +3287,7 @@ bool CBlock::CheckBlockSignature() const bool CheckDiskSpace(uint64_t nAdditionalBytes) { - uint64_t nFreeBytesAvailable = filesystem::space(GetDataDir()).available; + uint64_t nFreeBytesAvailable = fs::space(GetDataDir()).available; // Check for nMinDiskSpace bytes (currently 50MB) if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes) @@ -3303,7 +3303,7 @@ bool CheckDiskSpace(uint64_t nAdditionalBytes) return true; } -static filesystem::path BlockFilePath(unsigned int nFile) +static fs::path BlockFilePath(unsigned int nFile) { string strBlockFn = strprintf("blk%04u.dat", nFile); return GetDataDir() / strBlockFn; diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 3b4b7926ca..9d424f469c 100755 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -357,7 +357,7 @@ int StartGridcoinQt(int argc, char *argv[]) app.installNativeEventFilter(new WinShutdownMonitor()); #endif - if (!boost::filesystem::is_directory(GetDataDir(false))) + if (!fs::is_directory(GetDataDir(false))) { QMessageBox::critical(0, "Gridcoin", QString("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"]))); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 8f40fd2012..60b4df11c5 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -9,8 +9,6 @@ #include #include -#include - #include "bitcoingui.h" #include "transactiontablemodel.h" #include "addressbookpage.h" @@ -83,7 +81,6 @@ #include "gridcoin/staking/status.h" #include "gridcoin/superblock.h" -#include #include // for to_lower() #include #include "util.h" diff --git a/src/qt/diagnosticsdialog.cpp b/src/qt/diagnosticsdialog.cpp index 7b7b7ad0fd..b6508c14d3 100644 --- a/src/qt/diagnosticsdialog.cpp +++ b/src/qt/diagnosticsdialog.cpp @@ -2,11 +2,11 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "fs.h" #include "main.h" #include "util.h" #include -#include #include #include "diagnosticsdialog.h" @@ -18,7 +18,6 @@ #include "qt/researcher/researchermodel.h" #include -#include DiagnosticsDialog::DiagnosticsDialog(QWidget *parent, ResearcherModel* researcher_model) : QDialog(parent), @@ -190,14 +189,14 @@ void DiagnosticsDialog::DisplayOverallDiagnosticResult() bool DiagnosticsDialog::VerifyBoincPath() { - boost::filesystem::path boincPath = (boost::filesystem::path) GRC::GetBoincDataDir(); + fs::path boincPath = (fs::path) GRC::GetBoincDataDir(); if (boincPath.empty()) - boincPath = (boost::filesystem::path) GetArgument("boincdatadir", ""); + boincPath = (fs::path) GetArgument("boincdatadir", ""); boincPath = boincPath / "client_state.xml"; - return boost::filesystem::exists(boincPath); + return fs::exists(boincPath); } bool DiagnosticsDialog::VerifyIsCPIDValid() diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 238d51e198..863209134d 100755 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -1,3 +1,4 @@ +#include "fs.h" #include "guiutil.h" #include "bitcoinaddressvalidator.h" #include "walletmodel.h" @@ -20,9 +21,6 @@ #include #include -#include -#include - #ifdef WIN32 #ifdef _WIN32_WINNT #undef _WIN32_WINNT @@ -326,10 +324,10 @@ bool isObscured(QWidget *w) void openDebugLogfile() { - boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; + fs::path pathDebug = GetDataDir() / "debug.log"; /* Open debug.log with the associated application */ - if (boost::filesystem::exists(pathDebug)) + if (fs::exists(pathDebug)) QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(pathDebug.string()))); } @@ -380,7 +378,7 @@ bool WindowContextHelpButtonHintFilter::eventFilter (QObject *obj, QEvent *event struct AutoStartupArguments { std::string link_name_suffix; - boost::filesystem::path data_dir; + fs::path data_dir; std::string arguments; }; @@ -430,12 +428,12 @@ AutoStartupArguments GetAutoStartupArguments(bool fStartMin = true) } #ifdef WIN32 -boost::filesystem::path static StartupShortcutLegacyPath() +fs::path static StartupShortcutLegacyPath() { return GetSpecialFolderPath(CSIDL_STARTUP) / "Gridcoin.lnk"; } -boost::filesystem::path static StartupShortcutPath() +fs::path static StartupShortcutPath() { std::string link_name_suffix = GetAutoStartupArguments().link_name_suffix; std::string link_name_root = "Gridcoin"; @@ -446,16 +444,16 @@ boost::filesystem::path static StartupShortcutPath() bool GetStartOnSystemStartup() { // check for Gridcoin.lnk - return boost::filesystem::exists(StartupShortcutPath()); + return fs::exists(StartupShortcutPath()); } bool SetStartOnSystemStartup(bool fAutoStart, bool fStartMin) { // Remove the legacy shortcut unconditionally. - boost::filesystem::remove(StartupShortcutLegacyPath()); + fs::remove(StartupShortcutLegacyPath()); // If the shortcut exists already, remove it for updating - boost::filesystem::remove(StartupShortcutPath()); + fs::remove(StartupShortcutPath()); // Get auto startup arguments AutoStartupArguments autostartup = GetAutoStartupArguments(fStartMin); @@ -533,10 +531,8 @@ bool SetStartOnSystemStartup(bool fAutoStart, bool fStartMin) // Follow the Desktop Application Autostart Spec: // http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html -boost::filesystem::path static GetAutostartDir() +fs::path static GetAutostartDir() { - namespace fs = boost::filesystem; - char* pszConfigHome = getenv("XDG_CONFIG_HOME"); if (pszConfigHome) return fs::path(pszConfigHome) / "autostart"; char* pszHome = getenv("HOME"); @@ -544,12 +540,12 @@ boost::filesystem::path static GetAutostartDir() return fs::path(); } -boost::filesystem::path static GetAutostartLegacyFilePath() +fs::path static GetAutostartLegacyFilePath() { return GetAutostartDir() / "gridcoin.desktop"; } -boost::filesystem::path static GetAutostartFilePath() +fs::path static GetAutostartFilePath() { std::string link_name_suffix = GetAutoStartupArguments().link_name_suffix; std::string link_name_root = "gridcoin"; @@ -579,13 +575,13 @@ bool GetStartOnSystemStartup() bool SetStartOnSystemStartup(bool fAutoStart, bool fStartMin) { // Remove legacy autostart path if it exists. - if (boost::filesystem::exists(GetAutostartLegacyFilePath())) + if (fs::exists(GetAutostartLegacyFilePath())) { - boost::filesystem::remove(GetAutostartLegacyFilePath()); + fs::remove(GetAutostartLegacyFilePath()); } if (!fAutoStart) - boost::filesystem::remove(GetAutostartFilePath()); + fs::remove(GetAutostartFilePath()); else { char pszExePath[MAX_PATH+1]; @@ -595,7 +591,7 @@ bool SetStartOnSystemStartup(bool fAutoStart, bool fStartMin) AutoStartupArguments autostartup = GetAutoStartupArguments(fStartMin); - boost::filesystem::create_directories(GetAutostartDir()); + fs::create_directories(GetAutostartDir()); fsbridge::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc); if (!optionFile.good()) @@ -604,7 +600,7 @@ bool SetStartOnSystemStartup(bool fAutoStart, bool fStartMin) optionFile << "[Desktop Entry]\n"; optionFile << "Type=Application\n"; optionFile << "Name=Gridcoin" + autostartup.link_name_suffix + "\n"; - optionFile << "Exec=" << static_cast(pszExePath); + optionFile << "Exec=" << static_cast(pszExePath); if (!autostartup.data_dir.empty()) { diff --git a/src/qt/upgradeqt.cpp b/src/qt/upgradeqt.cpp index 6181ea9afa..851481391c 100644 --- a/src/qt/upgradeqt.cpp +++ b/src/qt/upgradeqt.cpp @@ -338,14 +338,14 @@ void UpgradeQt::DeleteSnapshot() try { - boost::filesystem::path snapshotpath = GetDataDir() / snapshotfile; + fs::path snapshotpath = GetDataDir() / snapshotfile; - if (boost::filesystem::exists(snapshotpath)) - if (boost::filesystem::is_regular_file(snapshotpath)) - boost::filesystem::remove(snapshotpath); + if (fs::exists(snapshotpath)) + if (fs::is_regular_file(snapshotpath)) + fs::remove(snapshotpath); } - catch (boost::filesystem::filesystem_error& e) + catch (fs::filesystem_error& e) { LogPrintf("Snapshot Downloader: Exception occurred while attempting to delete snapshot (%s)", e.code().message()); } diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 1293294fe2..6c9efa097f 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -18,12 +18,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include diff --git a/src/rpcdataacq.cpp b/src/rpcdataacq.cpp index 5107942a4e..56ba548ea8 100644 --- a/src/rpcdataacq.cpp +++ b/src/rpcdataacq.cpp @@ -14,11 +14,8 @@ #include "gridcoin/support/block_finder.h" #include "util.h" -#include -#include #include // for to_lower() #include -#include #include #include @@ -558,8 +555,8 @@ UniValue rpc_exportstats(const UniValue& params, bool fHelp) unsigned long points = 0; double samples = 0; /* this is double for easy division */ fsbridge::ofstream Output; - boost::filesystem::path o_path = GetDataDir() / "reports" / ( "export_" + std::to_string(GetTime()) + ".txt" ); - boost::filesystem::create_directories(o_path.parent_path()); + fs::path o_path = GetDataDir() / "reports" / ( "export_" + std::to_string(GetTime()) + ".txt" ); + fs::create_directories(o_path.parent_path()); Output.open (o_path); Output.imbue(std::locale::classic()); Output << std::fixed << std::setprecision(4); diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index d8a20c80ac..8ce5eb7565 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -453,9 +453,9 @@ UniValue parseaccrualsnapshotfile(const UniValue& params, bool fHelp) UniValue res(UniValue::VOBJ); - boost::filesystem::path snapshot_path = params[0].get_str(); + const fs::path snapshot_path = params[0].get_str(); - if (!boost::filesystem::is_regular_file(snapshot_path)) + if (!fs::is_regular_file(snapshot_path)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid snapshot file specified."); } diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp index 0ee00040fc..aaa8a33a1f 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -14,12 +14,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index ba6a51f8d3..7812fd5130 100755 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -1158,7 +1158,7 @@ UniValue scanforunspent(const UniValue& params, bool fHelp) fsbridge::ofstream dataout; // We will place this in wallet backups as a safer location then in main data directory - boost::filesystem::path exportpath; + fs::path exportpath; time_t biTime; struct tm * blTime; @@ -1177,7 +1177,7 @@ UniValue scanforunspent(const UniValue& params, bool fHelp) else exportpath = fs::path(backupdir) / exportfile; - boost::filesystem::create_directory(exportpath.parent_path()); + fs::create_directory(exportpath.parent_path()); dataout.open(exportpath); diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 2da2265a10..03ab620874 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -16,12 +16,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include @@ -619,14 +617,14 @@ void StartRPCThreads() { rpc_ssl_context->set_options(ssl::context::no_sslv2); - filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert")); - if (!pathCertFile.is_absolute()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile; - if (filesystem::exists(pathCertFile)) rpc_ssl_context->use_certificate_chain_file(pathCertFile.string()); + fs::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert")); + if (!pathCertFile.is_absolute()) pathCertFile = fs::path(GetDataDir()) / pathCertFile; + if (fs::exists(pathCertFile)) rpc_ssl_context->use_certificate_chain_file(pathCertFile.string()); else LogPrintf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string()); - filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem")); - if (!pathPKFile.is_absolute()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile; - if (filesystem::exists(pathPKFile)) rpc_ssl_context->use_private_key_file(pathPKFile.string(), ssl::context::pem); + fs::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem")); + if (!pathPKFile.is_absolute()) pathPKFile = fs::path(GetDataDir()) / pathPKFile; + if (fs::exists(pathPKFile)) rpc_ssl_context->use_private_key_file(pathPKFile.string(), ssl::context::pem); else LogPrintf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string()); string strCiphers = GetArg("-rpcsslciphers", "TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH"); diff --git a/src/test/gridcoin/researcher_tests.cpp b/src/test/gridcoin/researcher_tests.cpp index 2597aeda82..7ffbade53c 100644 --- a/src/test/gridcoin/researcher_tests.cpp +++ b/src/test/gridcoin/researcher_tests.cpp @@ -10,7 +10,6 @@ #include "gridcoin/researcher.h" #include "util.h" -#include #include #include #include @@ -23,31 +22,31 @@ namespace { //! //! \return Path to the test data directory containing the stub. //! -boost::filesystem::path ResolveStubDir() +fs::path ResolveStubDir() { - const boost::filesystem::path cwd = boost::filesystem::current_path(); - const boost::filesystem::path data_dir("src/test/data"); + const fs::path cwd = fs::current_path(); + const fs::path data_dir("src/test/data"); const std::string stub = "client_state.xml"; // Test harness run from subdirectory of repo root (src/, build/, etc.): - if (boost::filesystem::exists(cwd / ".." / data_dir / stub)) { - return boost::filesystem::canonical(cwd / ".." / data_dir); + if (fs::exists(cwd / ".." / data_dir / stub)) { + return fs::canonical(cwd / ".." / data_dir); } // Test harness run from platform-specific build sub-directory // (ex: build/gridcoin-x86_64-unknown-linux-gnu/) - if (boost::filesystem::exists(cwd / ".." / ".." / data_dir / stub)) { - return boost::filesystem::canonical(cwd / ".." / ".." / data_dir); + if (fs::exists(cwd / ".." / ".." / data_dir / stub)) { + return fs::canonical(cwd / ".." / ".." / data_dir); } // Test harness run from sub-directory in a platform-specific build sub- // directory (Travis; ex: build/gridcoin-x86_64-unknown-linux-gnu/src) - if (boost::filesystem::exists(cwd / ".." / ".." / ".." / data_dir / stub)) { - return boost::filesystem::canonical(cwd / ".." / ".." / ".." / data_dir); + if (fs::exists(cwd / ".." / ".." / ".." / data_dir / stub)) { + return fs::canonical(cwd / ".." / ".." / ".." / data_dir); } // Test harness run from test directory (src/test/): - if (boost::filesystem::exists(cwd / "data" / stub)) { + if (fs::exists(cwd / "data" / stub)) { return cwd / "data"; } @@ -1589,7 +1588,7 @@ void it_resets_to_investor_mode_when_explicitly_configured() //! BOOST_AUTO_TEST_CASE(client_state_stub_exists) { - if (boost::filesystem::exists(ResolveStubDir() / "client_state.xml")) { + if (fs::exists(ResolveStubDir() / "client_state.xml")) { boost::unit_test::framework::master_test_suite().add(BOOST_TEST_CASE(&it_parses_project_xml_from_a_client_state_xml_file)); boost::unit_test::framework::master_test_suite().add(BOOST_TEST_CASE(&it_resets_to_investor_mode_when_explicitly_configured)); } else { diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 30c712c1ce..e9a9f7ea71 100755 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -1,5 +1,3 @@ -#include -#include #include #include #include diff --git a/src/txdb-leveldb.cpp b/src/txdb-leveldb.cpp index cf1bcbc3af..6bee408fc7 100644 --- a/src/txdb-leveldb.cpp +++ b/src/txdb-leveldb.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include @@ -36,27 +35,27 @@ static leveldb::Options GetOptions() { void init_blockindex(leveldb::Options& options, bool fRemoveOld = false) { // First time init. - filesystem::path directory = GetDataDir() / "txleveldb"; + fs::path directory = GetDataDir() / "txleveldb"; if (fRemoveOld) { - filesystem::remove_all(directory); // remove directory + fs::remove_all(directory); // remove directory unsigned int nFile = 1; while (true) { - filesystem::path strBlockFile = GetDataDir() / strprintf("blk%04u.dat", nFile); + fs::path strBlockFile = GetDataDir() / strprintf("blk%04u.dat", nFile); // Break if no such file - if( !filesystem::exists( strBlockFile ) ) + if( !fs::exists( strBlockFile ) ) break; - filesystem::remove(strBlockFile); + fs::remove(strBlockFile); nFile++; } } - filesystem::create_directory(directory); + fs::create_directory(directory); LogPrintf("Opening LevelDB in %s", directory.string()); leveldb::Status status = leveldb::DB::Open(options, directory.string(), &txdb); if (!status.ok()) { diff --git a/src/util.h b/src/util.h index 94ece2dd3d..4951ba96df 100644 --- a/src/util.h +++ b/src/util.h @@ -18,12 +18,9 @@ #include #include #include -#include #include #include -#include -#include #include #include #include diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 5e6a8c2358..3b481fc1ac 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -2,9 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include -#include - +#include "fs.h" #include "init.h" // for pwalletMain #include "rpcserver.h" #include "rpcprotocol.h" @@ -14,7 +12,6 @@ #include #include #include -#include using namespace std; @@ -187,8 +184,8 @@ UniValue importwallet(const UniValue& params, bool fHelp) "Imports keys from a wallet dump file (see dumpwallet)\n" "If a path is not specified in the filename, the data directory is used."); - boost::filesystem::path PathForImport = boost::filesystem::path(params[0].get_str()); - boost::filesystem::path DefaultPathDataDir = GetDataDir(); + fs::path PathForImport = fs::path(params[0].get_str()); + fs::path DefaultPathDataDir = GetDataDir(); // If provided filename does not have a path, then append parent path, otherwise leave alone. if (PathForImport.parent_path().empty()) @@ -320,8 +317,8 @@ UniValue dumpwallet(const UniValue& params, bool fHelp) EnsureWalletIsUnlocked(); - boost::filesystem::path PathForDump = boost::filesystem::path(params[0].get_str()); - boost::filesystem::path DefaultPathDataDir = GetDataDir(); + fs::path PathForDump = fs::path(params[0].get_str()); + fs::path DefaultPathDataDir = GetDataDir(); // If provided filename does not have a path, then append parent path, otherwise leave alone. if (PathForDump.parent_path().empty()) diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index cc1107c4bf..c286bf51bf 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -7,10 +7,8 @@ #include "wallet/walletdb.h" #include "wallet/wallet.h" #include "init.h" -#include using namespace std; -using namespace boost; static uint64_t nAccountingEntryNumber = 0; extern bool fWalletUnlockStakingOnly; From c3f9cc6114ed70fef1d2b276b9f36fffd18c4cb4 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Wed, 21 Oct 2020 13:55:09 -0500 Subject: [PATCH 43/53] Reimplement legacy administrative contract validation This adds a stripped-down function that verifies the signature of version 1 administrative contracts to replace the contract signature verification code removed in an earlier commit. It prevents invalid historical testnet contracts from interfering with the initial sync. --- src/gridcoin/contract/contract.cpp | 61 +++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/src/gridcoin/contract/contract.cpp b/src/gridcoin/contract/contract.cpp index 7d3439acc4..7aa080ae56 100644 --- a/src/gridcoin/contract/contract.cpp +++ b/src/gridcoin/contract/contract.cpp @@ -331,6 +331,63 @@ class Dispatcher //! Dispatcher g_dispatcher; +//! +//! \brief Validate a legacy contract message. +//! +//! This function performs a sanity check for historical contract messages. It +//! verifies the contract signature for administrative contracts only. Version +//! 2 contracts undergo much more robust validation. Testnet contains some bad +//! administrative contracts that this routine filters out. +//! +//! \param contract The version 1 contract to validate. +//! \param tx The transaction that contains the contract. +//! +//! \return \c true if the contract passes validation. +//! +bool CheckLegacyContract(const Contract& contract, const CTransaction& tx) +{ + if (!contract.WellFormed()) { + return false; + } + + if (!contract.RequiresMasterKey()) { + return true; + } + + const std::string base64_sig = ExtractXML(tx.hashBoinc, "", ""); + + if (base64_sig.empty()) { + return false; + } + + bool invalid; + const std::vector sig = DecodeBase64(base64_sig.c_str(), &invalid); + + if (invalid) { + return false; + } + + const std::string type_string = contract.m_type.ToString(); + + // We use static_cast here instead of dynamic_cast to avoid the lookup. The + // value of m_payload is guaranteed to be a LegacyPayload for v1 contracts: + // + const ContractPayload payload = contract.m_body.AssumeLegacy(); + const auto& body = static_cast(*payload); + + const uint256 body_hash = Hash( + type_string.begin(), + type_string.end(), + body.m_key.begin(), + body.m_key.end(), + body.m_value.begin(), + body.m_value.end()); + + CKey key; + key.SetPubKey(CWallet::MasterPublicKey()); + + return key.Verify(body_hash, sig); +} } // anonymous namespace // ----------------------------------------------------------------------------- @@ -419,7 +476,7 @@ void GRC::ApplyContracts( { for (const auto& contract : tx.GetContracts()) { // V2 contracts are checked upon receipt: - if (contract.m_version == 1 && !contract.WellFormed()) { + if (contract.m_version == 1 && !CheckLegacyContract(contract, tx)) { continue; } @@ -462,7 +519,7 @@ void GRC::RevertContracts(const CTransaction& tx, const CBlockIndex* const pinde // Reverse the contracts. Reorganize will load any previous versions: for (const auto& contract : tx.GetContracts()) { // V2 contracts are checked upon receipt: - if (contract.m_version == 1 && !contract.WellFormed()) { + if (contract.m_version == 1 && !CheckLegacyContract(contract, tx)) { continue; } From 78d81da1fb3960624808b99a93a6b76ac9e0fcac Mon Sep 17 00:00:00 2001 From: jamescowens Date: Wed, 21 Oct 2020 21:27:25 -0400 Subject: [PATCH 44/53] Increment version to 5.0.2.3 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 34ced8ecfc..6da269434f 100755 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 5) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 2) -define(_CLIENT_VERSION_BUILD, 2) +define(_CLIENT_VERSION_BUILD, 3) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2020) define(_COPYRIGHT_HOLDERS,[The %s developers]) From 8a9819f3b7ed2a59eb74d9e3eb14b050d70270eb Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Sun, 25 Oct 2020 09:48:30 -0500 Subject: [PATCH 45/53] Apply accrual for new CPIDs from existing snapshots This fixes a detail that I missed for #1901. It ensures that snapshot accrual reloads stored accrual for CPIDs that never staked a block before when applying a snapshot from disk. --- src/gridcoin/accrual/snapshot.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/gridcoin/accrual/snapshot.h b/src/gridcoin/accrual/snapshot.h index a3e02f409d..f273babb99 100644 --- a/src/gridcoin/accrual/snapshot.h +++ b/src/gridcoin/accrual/snapshot.h @@ -1416,6 +1416,15 @@ class AccrualSnapshotRepository account.m_accrual = snapshot.GetAccrual(cpid); } + // Apply snapshot accrual for any CPIDs with no accounting record as + // of the last superblock: + // + for (const auto& cpid_pair : snapshot.m_records) { + if (accounts.find(cpid_pair.first) == accounts.end()) { + accounts[cpid_pair.first].m_accrual = cpid_pair.second; + } + } + return true; } From a89c6cc79313bd0a553c17c31c00fb5d902848ae Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Sun, 25 Oct 2020 10:28:30 -0500 Subject: [PATCH 46/53] Disconnect outdated forked peers after a grace period This adds a grace period after which a node will immediately disconnect peers running a version lower than the latest mandatory release. --- src/main.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index b29ee7c643..0db17aed89 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3756,6 +3756,18 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->fDisconnect = true; return false; } + else if (pfrom->nVersion < PROTOCOL_VERSION && nBestHeight > GetNewbieSnapshotFixHeight() + 2000) + { + // Immediately disconnect peers running a protocol version lower than + // the latest hard-fork after a grace period for the transition. + // + // TODO: increment MIN_PEER_PROTO_VERSION and remove this condition in + // the release that follows the mandatory version: + // + LogPrint(BCLog::LogFlags::NOISY, "Disconnecting forked peer protocol version %i: %s", pfrom->nVersion, pfrom->addr.ToString()); + pfrom->fDisconnect = true; + return false; + } if (!vRecv.empty()) vRecv >> addrFrom >> nNonce; From bf0adf2b5bebaf74696f5182da67628ebf11f5ba Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Sun, 25 Oct 2020 16:32:20 -0500 Subject: [PATCH 47/53] Set mainnet height for newbie accrual fix activation --- src/chainparams.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chainparams.h b/src/chainparams.h index cf4984511d..0c87ab50e4 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -132,5 +132,5 @@ inline int GetSuperblockAgeSpacing(int nHeight) inline int GetNewbieSnapshotFixHeight() { - return fTestNet ? 1393000 : std::numeric_limits::max(); + return fTestNet ? 1393000 : 2090000; } From a28f17827c9d7bd8b656d33323b05ebc4e43b1bc Mon Sep 17 00:00:00 2001 From: jamescowens Date: Sun, 25 Oct 2020 17:43:09 -0400 Subject: [PATCH 48/53] Increment version to 5.0.2.4 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 6da269434f..785a5b88ae 100755 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 5) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 2) -define(_CLIENT_VERSION_BUILD, 3) +define(_CLIENT_VERSION_BUILD, 4) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2020) define(_COPYRIGHT_HOLDERS,[The %s developers]) From c484d134b2b5cf469482da3f436a753e3fdd2c80 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Sat, 31 Oct 2020 23:31:49 -0500 Subject: [PATCH 49/53] Reset research account when disconnecting first block This tweaks the change in commit 27d58c5 to reset the entire research account instead of just the account's first block while disconnecting the first block that a CPID claimed research rewards for to guarantee that the tally system treats the account as a new CPID. Only the snapshot accrual information is retained to enable new CPIDs to carry pending accrual before staking the first block. --- src/gridcoin/account.h | 8 ++++++-- src/gridcoin/tally.cpp | 13 ++++++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/gridcoin/account.h b/src/gridcoin/account.h index 3bf749db56..c47828573f 100644 --- a/src/gridcoin/account.h +++ b/src/gridcoin/account.h @@ -44,8 +44,12 @@ class ResearchAccount //! //! \brief Initialize an empty research account. //! - ResearchAccount() - : m_accrual(0) + //! \param accrual Research reward accrued as of the last superblock. New + //! accounts may carry pending accrual even though the CPIDs never staked + //! a block before. + //! + ResearchAccount(const CAmount accrual = 0) + : m_accrual(accrual) , m_total_research_subsidy(0) , m_total_magnitude(0) , m_accuracy(0) diff --git a/src/gridcoin/tally.cpp b/src/gridcoin/tally.cpp index 6a14d274fd..66ae5bfc3f 100644 --- a/src/gridcoin/tally.cpp +++ b/src/gridcoin/tally.cpp @@ -302,6 +302,14 @@ class ResearcherTally assert(account.m_first_block_ptr != nullptr); assert(pindex == account.m_last_block_ptr); + // When disconnecting a CPID's first block, reset the account, but + // retain the pending snapshot accrual amount: + // + if (pindex == account.m_first_block_ptr) { + account = ResearchAccount(account.m_accrual); + return; + } + account.m_total_research_subsidy -= pindex->nResearchSubsidy; if (pindex->nMagnitude > 0) { @@ -309,11 +317,6 @@ class ResearcherTally account.m_total_magnitude -= pindex->nMagnitude; } - if (pindex == account.m_first_block_ptr) { - account.m_first_block_ptr = nullptr; - return; - } - pindex = pindex->pprev; while (pindex From 7c8e1d3247a5d3563544b59197301637d401dc72 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Sat, 31 Oct 2020 23:46:01 -0500 Subject: [PATCH 50/53] Raise newbie snapshot accrual fix activation height This changes the height for the activation of a fix for snapshot accrual for new CPIDs to provide an upgrade grace period of one month instead of two weeks. --- src/chainparams.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chainparams.h b/src/chainparams.h index 0c87ab50e4..4fde700ebc 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -132,5 +132,5 @@ inline int GetSuperblockAgeSpacing(int nHeight) inline int GetNewbieSnapshotFixHeight() { - return fTestNet ? 1393000 : 2090000; + return fTestNet ? 1393000 : 2104000; } From b1ecdcd592aa5cc620224d7b2db48b9f5f01b2a3 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Sun, 1 Nov 2020 00:04:39 -0500 Subject: [PATCH 51/53] Add poll choices to "gettransaction" contract JSON This adds the available poll answers to the contract information included in the output of the "gettransaction" RPC. This may support explorers that need the information at the time that the transaction arrives. --- src/rpcrawtransaction.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 7812fd5130..be129bd2fe 100755 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -176,6 +176,18 @@ UniValue PollPayloadToJson(const GRC::ContractPayload& payload) out.pushKV("response_type", (int)poll.m_poll.m_response_type.Raw()); out.pushKV("duration_days", (int)poll.m_poll.m_duration_days); + UniValue choices(UniValue::VARR); + + for (size_t i = 0; i < poll.m_poll.Choices().size(); ++i) { + UniValue choice(UniValue::VOBJ); + choice.pushKV("id", (int)i); + choice.pushKV("label", poll.m_poll.Choices().At(i)->m_label); + + choices.push_back(choice); + } + + out.pushKV("choices", choices); + return out; } From a91b25002f249b9c2bf331b3aafc9ddd7d4ecf68 Mon Sep 17 00:00:00 2001 From: jamescowens Date: Sun, 1 Nov 2020 10:29:39 -0500 Subject: [PATCH 52/53] Update changelog for release --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36a8d9d113..72ba3d7dbd 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,35 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [5.1.0.0] 2020-11-01, mandatory, "Gladys" +### Added + - rpc: Add out-of-sync status to "getinfo" and "getblockchaininfo" #1925 (@cyrossignol) + - gui: add autocomplete to rpc console #1927 (@Pythonix) + - consensus: Add checkpoint post block v11 transition #1919 (@cyrossignol) + - researcher: Add -forcecpid configuration option #1935 (@cyrossignol) + - gui: Adds detection if version is below last mandatory #1939 (@jamescowens) + - contract: Reimplement legacy administrative contract validation #1943 (@cyrossignol) + - voting: Add poll choices to "gettransaction" RPC contract output #1948 (@cyrossignol) + +### Changed + - doc: Fix link in build-openbsd.md #1924 (@Pythonix) + - voting: Decrease poll duration to 90 days #1936 (@cyrossignol) + - refactor: Revert init order to fix rejected net messages @1941 (@cyrossignol) + - refactor: port amount.h #1937 (@div72) + - refactor: Normalize boost::filesystem to fs namespace #1942 (@cyrossignol) + - accrual: Apply accrual for new CPIDs from existing snapshots #1944 (@cyrossignol) + - accrual: Reset research account when disconnecting first block #1947 (@cyrossignol) + +### Removed + - refactor: Clean up transitional code for block version 11 #1933 (@cyrossignol) + +### Fixed + - Modify depends packages for openSUSE and other Redhat like distributions and fix mingw bdb53 compile #1932 (@jamescowens) + - contract: Fix ability to reorganize contracts #1934 (@cyrossignol) + - accrual: Fix snapshot accrual for new CPIDs #1931 (@cyrossignol) + - rpc: Clean up getblockstats #1938 (@jamescowens) + - scraper, rpc: Correct missing mScraperStats initialization in ConvergedScraperStats (@jamescowens) + ## [5.0.2.0] 2020-10-08, leisure ### Added - trivial: Add and update copyright headers in Gridcoin files #1897 (@cyrossignol) From dd84c7d319a7d712315103330cfe4ffe5cd91c4b Mon Sep 17 00:00:00 2001 From: jamescowens Date: Sun, 1 Nov 2020 10:31:10 -0500 Subject: [PATCH 53/53] Increment version to 5.1.0.0 for mandatory release --- configure.ac | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 785a5b88ae..98ca28293a 100755 --- a/configure.ac +++ b/configure.ac @@ -1,10 +1,10 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 5) -define(_CLIENT_VERSION_MINOR, 0) -define(_CLIENT_VERSION_REVISION, 2) -define(_CLIENT_VERSION_BUILD, 4) -define(_CLIENT_VERSION_IS_RELEASE, false) +define(_CLIENT_VERSION_MINOR, 1) +define(_CLIENT_VERSION_REVISION, 0) +define(_CLIENT_VERSION_BUILD, 0) +define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2020) define(_COPYRIGHT_HOLDERS,[The %s developers]) define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[Gridcoin]])