From e9b2e1ac806120cdfd7272393a78f5e643d5af81 Mon Sep 17 00:00:00 2001 From: RoboticMind <30132912+RoboticMind@users.noreply.github.com> Date: Sun, 28 Feb 2021 10:29:58 -0500 Subject: [PATCH 01/13] Fix Word Spacing in Peer Tab --- src/qt/peertablemodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index c6163d4143..53d3213c49 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -108,7 +108,7 @@ PeerTableModel::PeerTableModel(ClientModel *parent) : clientModel(parent), timer(nullptr) { - columns << tr("NodeId") << tr("Node/Service") << tr("Ping") << tr("Sent") << tr("Received") << tr("User Agent"); + columns << tr("Node ID") << tr("Node/Service") << tr("Ping") << tr("Sent") << tr("Received") << tr("User Agent"); priv.reset(new PeerTablePriv()); // set up timer for auto refresh From 432dca74fba260b39542a3fbe31b8acb44bf5c17 Mon Sep 17 00:00:00 2001 From: jamescowens Date: Sun, 28 Feb 2021 16:36:29 -0500 Subject: [PATCH 02/13] Increment version to 5.1.0.13. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 3cf0c57658..c95d1d77a4 100755 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 5) define(_CLIENT_VERSION_MINOR, 1) define(_CLIENT_VERSION_REVISION, 0) -define(_CLIENT_VERSION_BUILD, 12) +define(_CLIENT_VERSION_BUILD, 13) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2020) define(_COPYRIGHT_HOLDERS,[The %s developers]) From 9f8e00d724ecaaa36e58befebffadc40611c7e40 Mon Sep 17 00:00:00 2001 From: Cy Rossignol Date: Sat, 6 Mar 2021 17:16:56 -0600 Subject: [PATCH 03/13] Add wait warning to voting tab loading message The voting tab can take several minutes to load on systems with slow disks. This changes the loading label to communicate the expectation to the user. This is a quick way to address the issue until I can finish the poll weight caching and optimizations. --- src/qt/votingdialog.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/qt/votingdialog.cpp b/src/qt/votingdialog.cpp index 3ce99ddbd6..025b6d0493 100644 --- a/src/qt/votingdialog.cpp +++ b/src/qt/votingdialog.cpp @@ -427,7 +427,9 @@ VotingDialog::VotingDialog(QWidget *parent) watcher.setProperty("running", false); connect(&watcher, SIGNAL(finished()), this, SLOT(onLoadingFinished())); loadingIndicator = new QLabel(this); - loadingIndicator->move(50,170); + loadingIndicator->setWordWrap(true); + + groupboxvlayout->addWidget(loadingIndicator); chartDialog_ = new VotingChartDialog(this); voteDialog_ = new VotingVoteDialog(this); @@ -449,7 +451,8 @@ void VotingDialog::loadPolls(bool history) bool isRunning = watcher.property("running").toBool(); if (tableModel_&& !isRunning) { - loadingIndicator->setText(tr("...loading data!")); + loadingIndicator->setText(tr("Recalculating voting weights... This can take several minutes, and the wallet may not respond until finished.")); + tableView_->hide(); loadingIndicator->show(); QFuture future = QtConcurrent::run(tableModel_, &VotingTableModel::resetData, history); watcher.setProperty("running", true); @@ -474,6 +477,7 @@ void VotingDialog::onLoadingFinished(void) int rowsCount = tableView_->verticalHeader()->count(); if (rowsCount > 0) { loadingIndicator->hide(); + tableView_->show(); } else { loadingIndicator->setText(tr("No polls !")); } From 380f354d58ccf88f9ebbfcab2c3a8d5978f481bf Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sat, 6 Mar 2021 19:20:15 -0500 Subject: [PATCH 04/13] Adds transaction hash and fees paid to consolidateunspent Also uses FormatMoney() for display of amounts to avoid floating point rounding errors. --- src/rpc/rawtransaction.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 804d23ea8a..433db85296 100755 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -797,8 +797,10 @@ UniValue consolidateunspent(const UniValue& params, bool fHelp) " here."); result.pushKV("result", true); - result.pushKV("UTXOs consolidated", (uint64_t) iInputCount); - result.pushKV("Output UTXO value", (double)(nAmount - nFeeRequired) / COIN); + result.pushKV("UTXOs_consolidated", (uint64_t) iInputCount); + result.pushKV("output_UTXO_value", FormatMoney(nAmount - nFeeRequired)); + result.pushKV("fees_paid", FormatMoney(nFeeRequired)); + result.pushKV("transaction_hash", wtxNew.GetHash().GetHex()); return result; } From 1c4f621149200ab664c853b48d588872e211dfad Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Thu, 4 Mar 2021 03:46:46 -0500 Subject: [PATCH 05/13] Minor corrections to beacon db storage --- src/gridcoin/beacon.cpp | 56 ++++++++++++++++++++++++++---- src/gridcoin/beacon.h | 9 +++++ src/gridcoin/contract/contract.cpp | 8 ++--- 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/src/gridcoin/beacon.cpp b/src/gridcoin/beacon.cpp index 33d6b22e51..f359a6856e 100644 --- a/src/gridcoin/beacon.cpp +++ b/src/gridcoin/beacon.cpp @@ -367,7 +367,15 @@ bool BeaconRegistry::TryRenewal(Beacon_ptr& current_beacon_ptr, int& height, con renewal.m_prev_beacon_hash = current_beacon_ptr->m_hash; // Put the renewal beacon into the db. - m_beacon_db.update(renewal.m_hash, height, renewal); + if (!m_beacon_db.insert(renewal.m_hash, height, renewal)) + { + LogPrint(LogFlags::BEACON, "WARNING: %s: In renewal of beacon for cpid %s, address %s, hash %s, beacon db record " + "already exists.", + __func__, + renewal.m_cpid.ToString(), + renewal.GetAddress().ToString(), + renewal.m_hash.GetHex()); + } // Get the iterator to the renewal beacon. auto renewal_iter = m_beacon_db.find(renewal.m_hash); @@ -989,6 +997,35 @@ int BeaconRegistry::BeaconDB::Initialize(PendingBeaconMap& m_pending, BeaconMap& { bool status = true; int height = 0; + uint32_t version = 0; + + // First load the beacon db version from leveldb and check it against the constant in the class. + { + CTxDB txdb("r"); + + std::pair key = std::make_pair("beacon_db", "version"); + + bool status = txdb.ReadGenericSerializable(key, version); + + if (!status) version = 0; + } + + if (version != CURRENT_VERSION) + { + LogPrint(LogFlags::BEACON, "WARNING: %s: Version level of the beacon db stored in leveldb, %u, does not " + "match that required in this code level, version %u. Clearing the leveldb beacon " + "storage and setting version level to match this code level.", + __func__, + version, + CURRENT_VERSION); + + clear_leveldb(); + + LogPrint(LogFlags::BEACON, "INFO: %s: Leveldb beacon area cleared. Version level set to %u.", + __func__, + CURRENT_VERSION); + } + // If LoadDBHeight not successful or height is zero then leveldb has not been initialized before. // LoadDBHeight will also set the private member variable m_height_stored from leveldb for this first call. @@ -1175,6 +1212,9 @@ void BeaconRegistry::ResetInMemoryOnly() m_beacon_db.clear_in_memory_only(); } +// Required to make the linker happy. +constexpr uint32_t BeaconRegistry::BeaconDB::CURRENT_VERSION; + void BeaconRegistry::BeaconDB::clear_in_memory_only() { m_historical.clear(); @@ -1189,15 +1229,19 @@ bool BeaconRegistry::BeaconDB::clear_leveldb() CTxDB txdb("rw"); - std::string key_type = "beacon_db"; + std::string key_type = "beacon"; + uint256 start_key_hint_beacon = uint256(); + + status &= txdb.EraseGenericSerializablesByKeyType(key_type, start_key_hint_beacon); + + key_type = "beacon_db"; std::string start_key_hint_beacon_db {}; status &= txdb.EraseGenericSerializablesByKeyType(key_type, start_key_hint_beacon_db); - key_type = "beacon"; - uint256 start_key_hint_beacon = uint256(); - - status &= txdb.EraseGenericSerializablesByKeyType(key_type, start_key_hint_beacon); + // We want to write back into leveldb the revision level of the db in the running code. + std::pair key = std::make_pair(key_type, "version"); + status &= txdb.WriteGenericSerializable(key, CURRENT_VERSION); m_height_stored = 0; m_recnum_stored = 0; diff --git a/src/gridcoin/beacon.h b/src/gridcoin/beacon.h index 7aeb68b8d3..62a43b0b10 100644 --- a/src/gridcoin/beacon.h +++ b/src/gridcoin/beacon.h @@ -707,6 +707,15 @@ class BeaconRegistry : public IContractHandler class BeaconDB { public: + //! + //! \brief Version number of the beacon db. + //! + //! CONSENSUS: Increment this value when introducing a breaking change to the beacon db. This + //! will ensure that when the wallet is restarted, the level db beacon storage will be cleared and + //! reloaded from the contract replay with the correct lookback scope. + //! + static constexpr uint32_t CURRENT_VERSION = 1; + //! //! \brief Initializes the Beacon Registry map structures from the replay of the beacon states stored //! in the beacon database. diff --git a/src/gridcoin/contract/contract.cpp b/src/gridcoin/contract/contract.cpp index 7d66b52109..e7a592fcbc 100644 --- a/src/gridcoin/contract/contract.cpp +++ b/src/gridcoin/contract/contract.cpp @@ -463,8 +463,7 @@ void GRC::ReplayContracts(const CBlockIndex* pindex_end, const CBlockIndex* pind // Only apply activations that have not already been stored/loaded into // the beacon DB. This is at the block level, so we have to be careful here. // If the pindex->nHeight is equal to the beacon_db_height, then the ActivatePending - // has already been replayed. This is different than below in ApplyContracts, where - // there can be more than one contract in a block, so the condition is subtly different. + // has already been replayed. if (pindex->nHeight > beacon_db_height) { GetBeaconRegistry().ActivatePending( @@ -510,9 +509,8 @@ void GRC::ApplyContracts( { for (const auto& contract : tx.GetContracts()) { // Do not (re)apply contracts that have already been stored/loeaded into - // the beacon DB. Note here if pindex->nHeight == beacon_db_height, the contract - // will be replayed. This is because there can be more than one contract per block. - if ((pindex->nHeight < beacon_db_height) && contract.m_type == ContractType::BEACON) + // the beacon DB. + if ((pindex->nHeight <= beacon_db_height) && contract.m_type == ContractType::BEACON) { LogPrint(BCLog::LogFlags::CONTRACT, "INFO: %s: ApplyContract tx skipped: " "pindex->height = %i <= beacon_db_height = %i and " From d0442d50eeb1e0bedba3e77c7f3e4d365fda7c4d Mon Sep 17 00:00:00 2001 From: jamescowens Date: Fri, 5 Mar 2021 18:03:05 -0500 Subject: [PATCH 06/13] Add capability to close researcher repository This adds the capability to close the researcher registry file to remove the lock on that file so that the snapshot cleanup will succeed when using the snapshot download functionality. It also changes the Qt snapshot upgrader class to use the existing QApplication app instead of a new one, because earlier to support the data directory dialog box the place where QApplication app was instantiated was changed to much earlier. Having another QApplication on top of the existing one was causing a segfault at exit. --- src/gridcoin/accrual/snapshot.h | 5 +++++ src/gridcoin/gridcoin.cpp | 5 +++++ src/gridcoin/gridcoin.h | 6 ++++++ src/gridcoin/tally.cpp | 10 ++++++++++ src/gridcoin/tally.h | 8 ++++++++ src/gridcoin/upgrade.cpp | 2 ++ src/init.cpp | 5 +++++ src/qt/bitcoin.cpp | 4 +++- src/qt/upgradeqt.cpp | 11 +---------- src/qt/upgradeqt.h | 3 ++- 10 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/gridcoin/accrual/snapshot.h b/src/gridcoin/accrual/snapshot.h index 04a473d6ea..c11c45b8e3 100644 --- a/src/gridcoin/accrual/snapshot.h +++ b/src/gridcoin/accrual/snapshot.h @@ -1456,6 +1456,11 @@ class AccrualSnapshotRepository return m_registry.Deregister(height); } + bool CloseRegistryFile() + { + return m_registry.Close(); + } + private: AccrualSnapshotRegistry m_registry; //!< Tracks snapshot files state. }; // AccrualSnapshotRepository diff --git a/src/gridcoin/gridcoin.cpp b/src/gridcoin/gridcoin.cpp index a75b25dcf5..e928bdb60e 100644 --- a/src/gridcoin/gridcoin.cpp +++ b/src/gridcoin/gridcoin.cpp @@ -398,6 +398,11 @@ bool GRC::Initialize(ThreadHandlerPtr threads, CBlockIndex* pindexBest) return true; } +void GRC::CloseResearcherRegistryFile() +{ + Tally::CloseRegistryFile(); +} + void GRC::ScheduleBackgroundJobs(CScheduler& scheduler) { scheduler.schedule(CheckBlockIndexJob); diff --git a/src/gridcoin/gridcoin.h b/src/gridcoin/gridcoin.h index 3f18141926..8bf914d7eb 100644 --- a/src/gridcoin/gridcoin.h +++ b/src/gridcoin/gridcoin.h @@ -18,6 +18,12 @@ namespace GRC { //! bool Initialize(ThreadHandlerPtr threads, CBlockIndex* pindexBest); +//! +//! \brief This closes the underlying research file to support the snapshot update +//! process, which must remove the accrual directory as part of the blockchain cleanup. +//! +void CloseResearcherRegistryFile(); + //! //! \brief Set up Gridcoin-specific background jobs. //! diff --git a/src/gridcoin/tally.cpp b/src/gridcoin/tally.cpp index 219fd42f8b..be7cbc7321 100644 --- a/src/gridcoin/tally.cpp +++ b/src/gridcoin/tally.cpp @@ -792,6 +792,11 @@ class ResearcherTally return Initialize(GetStartHeight(), SuperblockPtr::Empty()); } + + bool CloseRegistryFile() + { + return m_snapshots.CloseRegistryFile(); + } }; // ResearcherTally ResearcherTally g_researcher_tally; //!< Tracks lifetime research rewards. @@ -1261,3 +1266,8 @@ const CBlockIndex* Tally::GetBaseline() { return g_researcher_tally.GetBaseline(); } + +void Tally::CloseRegistryFile() +{ + g_researcher_tally.CloseRegistryFile(); +} diff --git a/src/gridcoin/tally.h b/src/gridcoin/tally.h index f0fb4a743f..f8100c51fd 100644 --- a/src/gridcoin/tally.h +++ b/src/gridcoin/tally.h @@ -261,5 +261,13 @@ class Tally //! const static CBlockIndex* GetBaseline(); + //! + //! \brief This closes the underlying register file of the researcher repository. It + //! is ONLY used in Shutdown() to release the lock on the registry.dat file + //! so that a snapshot download process cleanup will succeed, since the accrual directory + //! needs to be removed. + //! + static void CloseRegistryFile(); + }; } diff --git a/src/gridcoin/upgrade.cpp b/src/gridcoin/upgrade.cpp index 133a194ec7..ab1aae467e 100644 --- a/src/gridcoin/upgrade.cpp +++ b/src/gridcoin/upgrade.cpp @@ -376,6 +376,7 @@ bool Upgrade::CleanupBlockchainData() if (!fs::remove_all(*Iter)) return false; } } + continue; } @@ -391,6 +392,7 @@ bool Upgrade::CleanupBlockchainData() if (!fs::remove(*Iter)) return false; } + continue; } } diff --git a/src/init.cpp b/src/init.cpp index f02924fd1a..8cbc9d8346 100755 --- a/src/init.cpp +++ b/src/init.cpp @@ -104,6 +104,11 @@ void Shutdown(void* parg) StopNode(); bitdb.Flush(true); StopRPCThreads(); + + // This is necessary here to prevent a snapshot download from failing at the cleanup + // step because of a write lock on accrual/registry.dat. + GRC::CloseResearcherRegistryFile(); + fs::remove(GetPidFile()); UnregisterWallet(pwalletMain); delete pwalletMain; diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index ffb4c06ec7..30ffb84997 100755 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -23,6 +23,7 @@ #include "util.h" #include "winshutdownmonitor.h" #include "gridcoin/upgrade.h" +#include "gridcoin/gridcoin.h" #include "upgradeqt.h" #include @@ -404,7 +405,7 @@ int main(int argc, char *argv[]) // CTxDB().Close(); - if (Snapshot.SnapshotMain()) + if (Snapshot.SnapshotMain(app)) LogPrintf("Snapshot: Success!"); else @@ -560,6 +561,7 @@ int StartGridcoinQt(int argc, char *argv[], QApplication& app, OptionsModel& opt threads->removeAll(); threads.reset(); + return EXIT_SUCCESS; } diff --git a/src/qt/upgradeqt.cpp b/src/qt/upgradeqt.cpp index 851481391c..ffee89620e 100644 --- a/src/qt/upgradeqt.cpp +++ b/src/qt/upgradeqt.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -23,16 +22,8 @@ QString UpgradeQt::ToQString(const std::string& string) return QString::fromStdString(string); } -bool UpgradeQt::SnapshotMain() +bool UpgradeQt::SnapshotMain(QApplication& SnapshotApp) { - // Keep this separate from the main application - int xargc = 1; - char *xargv[] = {(char*)"gridcoinresearch"}; - - QApplication SnapshotApp(xargc, xargv); - - SnapshotApp.setOrganizationName("Gridcoin"); - SnapshotApp.setApplicationName("Gridcoin-Qt"); SnapshotApp.processEvents(); SnapshotApp.setWindowIcon(QPixmap(":/images/gridcoin")); diff --git a/src/qt/upgradeqt.h b/src/qt/upgradeqt.h index 1561c5de39..24220a689e 100644 --- a/src/qt/upgradeqt.h +++ b/src/qt/upgradeqt.h @@ -7,6 +7,7 @@ #include #include +#include class UpgradeQt { @@ -20,7 +21,7 @@ class UpgradeQt //! //! \return Returns success of snapshot task. //! - bool SnapshotMain(); + bool SnapshotMain(QApplication& SnapshotApp); //! //! \brief Function called via thread to download snapshot and provide realtime updates of progress. //! From 3faebef3f100644e4cbd3d54479e092a4fce3b2c Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sat, 6 Mar 2021 22:54:27 -0500 Subject: [PATCH 07/13] Change field names to be consistent with other rpc functions Co-authored-by: Cy Rossignol --- src/rpc/rawtransaction.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 433db85296..1e638fe8bb 100755 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -797,10 +797,10 @@ UniValue consolidateunspent(const UniValue& params, bool fHelp) " here."); result.pushKV("result", true); - result.pushKV("UTXOs_consolidated", (uint64_t) iInputCount); - result.pushKV("output_UTXO_value", FormatMoney(nAmount - nFeeRequired)); - result.pushKV("fees_paid", FormatMoney(nFeeRequired)); - result.pushKV("transaction_hash", wtxNew.GetHash().GetHex()); + result.pushKV("utxos_consolidated", (uint64_t) iInputCount); + result.pushKV("output_utxo_value", FormatMoney(nAmount - nFeeRequired)); + result.pushKV("fee", FormatMoney(nFeeRequired)); + result.pushKV("txid", wtxNew.GetHash().GetHex()); return result; } From d7ef15a1c49cd405f5dd60a2255379b591d3098f Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sat, 6 Mar 2021 23:24:59 -0500 Subject: [PATCH 08/13] Increment version to 5.2.0.2. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 67e2ad8d1e..731868c8d5 100755 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 5) define(_CLIENT_VERSION_MINOR, 2) define(_CLIENT_VERSION_REVISION, 0) -define(_CLIENT_VERSION_BUILD, 1) +define(_CLIENT_VERSION_BUILD, 2) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2021) define(_COPYRIGHT_HOLDERS,[The %s developers]) From 7e0eed41bb89606daa74f1ce590c418ce7f33b99 Mon Sep 17 00:00:00 2001 From: "James C. Owens" Date: Sun, 7 Mar 2021 15:10:56 -0500 Subject: [PATCH 09/13] Make some minor adjustments for VotingDialog flow This commit allows going to the voting dialog page without automatically kicking off calculating the poll results to avoid the long term lock every time the voting page is selected. It also implements a one hour timer once the data is refreshed, and will hide the polling data asking the user to refresh it once the timer is expired. --- src/qt/bitcoingui.cpp | 2 +- src/qt/votingdialog.cpp | 48 +++++++++++++++++++++++++++++++++++++++++ src/qt/votingdialog.h | 6 ++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index a0179b2455..f852cbb30e 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -1136,7 +1136,7 @@ void BitcoinGUI::gotoSendCoinsPage() void BitcoinGUI::gotoVotingPage() { votingAction->setChecked(true); - votingPage->resetData(); + //votingPage->loadPolls(false); centralWidget->setCurrentWidget(votingPage); exportAction->setEnabled(false); diff --git a/src/qt/votingdialog.cpp b/src/qt/votingdialog.cpp index 025b6d0493..ef1507c1ac 100644 --- a/src/qt/votingdialog.cpp +++ b/src/qt/votingdialog.cpp @@ -278,6 +278,9 @@ VotingItem* BuildPollItem(const PollRegistry::Sequence::Iterator& iter) void VotingTableModel::resetData(bool history) { + std::string function = __func__; + function += ": "; + // data: erase if (data_.size()) { beginRemoveRows(QModelIndex(), 0, data_.size() - 1); @@ -288,6 +291,8 @@ void VotingTableModel::resetData(bool history) endRemoveRows(); } + g_timer.GetTimes(function + "erase data", "votedialog"); + // retrieve data std::vector items; @@ -298,8 +303,11 @@ void VotingTableModel::resetData(bool history) if (VotingItem* item = BuildPollItem(iter)) { item->rowNumber_ = items.size() + 1; items.push_back(item); + } } + + g_timer.GetTimes(function + "populate poll results (cs_main lock)", "votedialog"); } // data: populate @@ -308,6 +316,8 @@ void VotingTableModel::resetData(bool history) for(size_t i=0; i < items.size(); i++) data_.append(items[i]); endInsertRows(); + + g_timer.GetTimes(function + "insert data in display table", "votedialog"); } } @@ -434,6 +444,12 @@ VotingDialog::VotingDialog(QWidget *parent) chartDialog_ = new VotingChartDialog(this); voteDialog_ = new VotingVoteDialog(this); pollDialog_ = new NewPollDialog(this); + + loadingIndicator->setText(tr("Press reload to load polls... This can take several minutes, and the wallet may not respond until finished.")); + tableView_->hide(); + loadingIndicator->show(); + + QObject::connect(vote_update_age_timer, SIGNAL(timeout()), this, SLOT(setStale())); } void VotingDialog::setModel(WalletModel *wallet_model) @@ -448,13 +464,23 @@ void VotingDialog::setModel(WalletModel *wallet_model) void VotingDialog::loadPolls(bool history) { + std::string function = __func__; + function += ": "; + bool isRunning = watcher.property("running").toBool(); if (tableModel_&& !isRunning) { loadingIndicator->setText(tr("Recalculating voting weights... This can take several minutes, and the wallet may not respond until finished.")); tableView_->hide(); loadingIndicator->show(); + + g_timer.InitTimer("votedialog", LogInstance().WillLogCategory(BCLog::LogFlags::MISC)); + vote_update_age_timer->start(STALE); + QFuture future = QtConcurrent::run(tableModel_, &VotingTableModel::resetData, history); + + g_timer.GetTimes(function + "Post future assignment", "votedialog"); + watcher.setProperty("running", true); watcher.setFuture(future); } @@ -470,6 +496,26 @@ void VotingDialog::loadHistory(void) loadPolls(true); } +void VotingDialog::setStale(void) +{ + LogPrint(BCLog::LogFlags::MISC, "INFO: %s called.", __func__); + + // If the stale flag is not set, but this function is called, it is from the timeout + // trigger of the vote_update_age_timer. Therefore set the loading indicator to stale + // and set the stale flag to true. The stale flag will be reset and the timer restarted + // when the loadPolls is called to refresh. + if (!stale) + { + loadingIndicator->setText(tr("Poll data is more than one hour old. Press reload to update... " + "This can take several minutes, and the wallet may not respond " + "until finished.")); + tableView_->hide(); + loadingIndicator->show(); + + stale = true; + } +} + void VotingDialog::onLoadingFinished(void) { watcher.setProperty("running", false); @@ -481,6 +527,8 @@ void VotingDialog::onLoadingFinished(void) } else { loadingIndicator->setText(tr("No polls !")); } + + stale = false; } void VotingDialog::tableColResize(void) diff --git a/src/qt/votingdialog.h b/src/qt/votingdialog.h index f4e369a015..ee75743477 100644 --- a/src/qt/votingdialog.h +++ b/src/qt/votingdialog.h @@ -164,6 +164,9 @@ class VotingDialog void setModel(WalletModel *wallet_model); private: + // The number of milliseconds of age at which the poll data is stale. Currently one hour equivalent. + static constexpr int64_t STALE = 60 * 60 * 1000; + QLineEdit *filterTQAU; QPushButton *resetButton; QPushButton *histButton; @@ -176,6 +179,8 @@ class VotingDialog NewPollDialog *pollDialog_; QLabel *loadingIndicator; QFutureWatcher watcher; + QTimer* vote_update_age_timer = new QTimer(this); + bool stale = false; private: virtual void showEvent(QShowEvent *); @@ -185,6 +190,7 @@ class VotingDialog private slots: void onLoadingFinished(void); + void setStale(void); public slots: void filterTQAUChanged(const QString &); From a6d30ac15590c160ed62876adc016b787d30ab81 Mon Sep 17 00:00:00 2001 From: jamescowens Date: Sun, 7 Mar 2021 19:47:42 -0500 Subject: [PATCH 10/13] Update copyright year to 2021 in aboutdialog.cpp --- src/qt/aboutdialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/aboutdialog.cpp b/src/qt/aboutdialog.cpp index 9388e02d81..e27fbd56bf 100755 --- a/src/qt/aboutdialog.cpp +++ b/src/qt/aboutdialog.cpp @@ -7,7 +7,7 @@ AboutDialog::AboutDialog(QWidget *parent) : ui(new Ui::AboutDialog) { ui->setupUi(this); - ui->copyrightLabel->setText("Copyright 2009-2020 The Bitcoin/Peercoin/Black-Coin/Gridcoin developers"); + ui->copyrightLabel->setText("Copyright 2009-2021 The Bitcoin/Peercoin/Black-Coin/Gridcoin developers"); } void AboutDialog::setModel(ClientModel *model) From de23c8fd13ed7ae57bf56c94bba639237ff08cb1 Mon Sep 17 00:00:00 2001 From: jamescowens Date: Sun, 7 Mar 2021 19:48:15 -0500 Subject: [PATCH 11/13] Update CHANGELOG.md for 5.2.1.0 release. --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b778f58fa..11a66abb53 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,17 @@ 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.2.1.0] 2021-03-07, leisure +### Added + - voting: Add wait warning to voting tab loading message #2039 (@cyrossignol) + - rpc: Adds transaction hash and fees paid to consolidateunspent (@jamescowens) + +### Changed +- gui, voting: Make some minor adjustments for VotingDialog flow (@jamescowens) + +### Fixed + - beacon, util, gui: Fix small error in beacon db for renewals and fix snapshot download functionality #2036 (@jamescowens) + ## [5.2.0.0] 2021-03-01, mandatory, "Hilda" ### Added - gui: Add RAC column to wizard summary page projects table #1951 (@cyrossignol) From 0b4af87702312a358c8ca5216cbaddbd2f6cc498 Mon Sep 17 00:00:00 2001 From: jamescowens Date: Sun, 7 Mar 2021 19:48:40 -0500 Subject: [PATCH 12/13] Increment version to 5.2.1.0 for release. --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 731868c8d5..70bfb932d8 100755 --- a/configure.ac +++ b/configure.ac @@ -2,9 +2,9 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 5) define(_CLIENT_VERSION_MINOR, 2) -define(_CLIENT_VERSION_REVISION, 0) -define(_CLIENT_VERSION_BUILD, 2) -define(_CLIENT_VERSION_IS_RELEASE, false) +define(_CLIENT_VERSION_REVISION, 1) +define(_CLIENT_VERSION_BUILD, 0) +define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2021) define(_COPYRIGHT_HOLDERS,[The %s developers]) define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[Gridcoin]]) From f436052327d9b7640e2a7276ab599f06080558a7 Mon Sep 17 00:00:00 2001 From: jamescowens Date: Sun, 7 Mar 2021 20:00:10 -0500 Subject: [PATCH 13/13] Make small correction to changelog. --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11a66abb53..7806832290 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [5.2.1.0] 2021-03-07, leisure ### Added - voting: Add wait warning to voting tab loading message #2039 (@cyrossignol) - - rpc: Adds transaction hash and fees paid to consolidateunspent (@jamescowens) + - rpc: Adds transaction hash and fees paid to consolidateunspent #2040 (@jamescowens) ### Changed -- gui, voting: Make some minor adjustments for VotingDialog flow (@jamescowens) +- gui, voting: Make some minor adjustments for VotingDialog flow #2041 (@jamescowens) ### Fixed - beacon, util, gui: Fix small error in beacon db for renewals and fix snapshot download functionality #2036 (@jamescowens)