Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/interfaces/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ class GOV
int nextsuperblock{0};
int fundingthreshold{0};
CAmount governancebudget{0};
int64_t targetSpacing{0};
int relayRequiredConfs{1};
int requiredConfs{6};
};
Expand Down
4 changes: 4 additions & 0 deletions src/interfaces/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <vector>

class CFeeRate;
class CGovernanceVote;
class CKey;
class CRPCCommand;
enum class FeeReason;
Expand Down Expand Up @@ -355,6 +356,9 @@ class Wallet
const std::string& data_hex, const COutPoint& outpoint,
std::string& out_fee_txid, std::string& error) = 0;

//! Sign a governance vote with the given voting key.
virtual bool signGovernanceVote(const CKeyID& keyID, CGovernanceVote& vote) = 0;

//! Return pointer to internal wallet class, useful for testing.
virtual wallet::CWallet* wallet() { return nullptr; }
};
Expand Down
1 change: 1 addition & 0 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4200,6 +4200,7 @@ void CConnman::StopNodes()
}
m_nodes_disconnected.clear();
vhListenSocket.clear();
WITH_LOCK(m_reconnections_mutex, m_reconnections.clear());
semOutbound.reset();
semAddnode.reset();
/**
Expand Down
4 changes: 2 additions & 2 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -1261,8 +1261,8 @@ friend class CNode;
EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex, !m_added_nodes_mutex, !m_addr_fetches_mutex, !mutexMsgProc);

void StopThreads();
void StopNodes() EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex, !cs_mapSocketToNode, !cs_sendable_receivable_nodes);
void Stop() EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex, !cs_mapSocketToNode, !cs_sendable_receivable_nodes)
void StopNodes() EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex, !cs_mapSocketToNode, !cs_sendable_receivable_nodes, !m_reconnections_mutex);
void Stop() EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex, !cs_mapSocketToNode, !cs_sendable_receivable_nodes, !m_reconnections_mutex)
{
StopThreads();
StopNodes();
Expand Down
3 changes: 2 additions & 1 deletion src/node/interfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ class GOVImpl : public GOV
info.proposalfee = GOVERNANCE_PROPOSAL_FEE_TX;
info.superblockcycle = consensusParams.nSuperblockCycle;
info.superblockmaturitywindow = consensusParams.nSuperblockMaturityWindow;
info.targetSpacing = consensusParams.nPowTargetSpacing;
info.relayRequiredConfs = GOVERNANCE_MIN_RELAY_FEE_CONFIRMATIONS;
info.requiredConfs = GOVERNANCE_FEE_CONFIRMATIONS;
if (ctx.dmnman) {
Expand Down Expand Up @@ -366,7 +367,7 @@ class LLMQImpl : public LLMQ
public:
size_t getInstantSentLockCount() override
{
if (context().llmq_ctx->isman != nullptr) {
if (context().llmq_ctx && context().llmq_ctx->isman != nullptr) {
return context().llmq_ctx->isman->GetInstantSendLockCount();
}
return 0;
Expand Down
20 changes: 17 additions & 3 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1476,7 +1476,14 @@ void BitcoinGUI::updateGovernanceVisibility()
// Show/hide the underlying QAction, hiding the QToolButton itself doesn't
// work for the GUI part but is still needed for shortcuts to work properly.
if (m_governance_action) m_governance_action->setVisible(fShow);
if (governanceButton) governanceButton->setVisible(fShow);
if (governanceButton) {
#ifdef ENABLE_WALLET
if (!fShow && governanceButton->isChecked()) {
gotoOverviewPage();
}
#endif // ENABLE_WALLET
governanceButton->setVisible(fShow);
}

GUIUtil::updateButtonGroupShortcuts(tabGroup);
updateWidth();
Expand All @@ -1490,7 +1497,14 @@ void BitcoinGUI::updateMasternodesVisibility()
// Show/hide the underlying QAction, hiding the QToolButton itself doesn't
// work for the GUI part but is still needed for shortcuts to work properly.
if (m_masternode_action) m_masternode_action->setVisible(fShow);
if (masternodeButton) masternodeButton->setVisible(fShow);
if (masternodeButton) {
#ifdef ENABLE_WALLET
if (!fShow && masternodeButton->isChecked()) {
gotoOverviewPage();
}
#endif // ENABLE_WALLET
masternodeButton->setVisible(fShow);
}

GUIUtil::updateButtonGroupShortcuts(tabGroup);
updateWidth();
Expand All @@ -1507,7 +1521,7 @@ void BitcoinGUI::updateWidth()
int nWidthWidestButton{0};
int nButtonsVisible{0};
for (QAbstractButton* button : tabGroup->buttons()) {
if (!button->isEnabled()) {
if (!button->isEnabled() || !button->isVisible()) {
continue;
}
QFontMetrics fm(button->font());
Expand Down
7 changes: 3 additions & 4 deletions src/qt/governancelist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include <interfaces/wallet.h>
#include <script/standard.h>
#include <util/strencodings.h>
#include <wallet/wallet.h>

#include <qt/clientmodel.h>
#include <qt/guiutil.h>
Expand Down Expand Up @@ -156,7 +155,7 @@ void GovernanceList::showCreateProposalDialog()
QMessageBox::warning(this, tr("Unavailable"), tr("A synced node and an unlocked wallet are required."));
return;
}
ProposalWizard* proposalWizard = new ProposalWizard(this->clientModel->node(), this->walletModel, this);
ProposalWizard* proposalWizard = new ProposalWizard(this->walletModel, this);
// Ensure closing the dialog actually destroys it so a fresh flow starts next time
proposalWizard->setAttribute(Qt::WA_DeleteOnClose, true);
// Modeless window that does not block the parent
Expand Down Expand Up @@ -304,8 +303,8 @@ void GovernanceList::voteForProposal(vote_outcome_enum_t outcome)
// Create vote
CGovernanceVote vote(dmn->getCollateralOutpoint(), proposalHash, VOTE_SIGNAL_FUNDING, outcome);

// Sign vote using CWallet member function
if (!walletModel->wallet().wallet()->SignGovernanceVote(votingKeyID, vote)) {
// Sign vote via wallet interface
if (!walletModel->wallet().signGovernanceVote(votingKeyID, vote)) {
nFailed++;
failedMessages.append(
tr("Failed to sign vote for masternode %1").arg(QString::fromStdString(proTxHash.ToString())));
Expand Down
20 changes: 12 additions & 8 deletions src/qt/masternodelist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include <QClipboard>
#include <QHeaderView>

#include <set>

namespace {
constexpr int MASTERNODELIST_UPDATE_SECONDS{3};
} // anonymous namespace
Expand Down Expand Up @@ -60,7 +62,7 @@ bool MasternodeListSortFilterProxyModel::filterAcceptsRow(int source_row, const
if (m_show_owned_only) {
QModelIndex idx = sourceModel()->index(source_row, MasternodeModel::PROTX_HASH, source_parent);
QString proTxHash = sourceModel()->data(idx, Qt::DisplayRole).toString();
if (m_my_mn_hashes.find(proTxHash) == m_my_mn_hashes.end()) {
if (!m_my_mn_hashes.contains(proTxHash)) {
return false;
}
}
Expand Down Expand Up @@ -186,26 +188,27 @@ void MasternodeList::updateDIP3ListScheduled()
int64_t nSecondsToWait = nTimeUpdatedDIP3 - GetTime() + nMnListUpdateSecods;

if (nSecondsToWait <= 0) {
updateDIP3List();
m_mn_list_changed.store(false, std::memory_order_relaxed);
if (updateDIP3List()) {
m_mn_list_changed.store(false, std::memory_order_relaxed);
}
}
}
}

void MasternodeList::updateDIP3List()
bool MasternodeList::updateDIP3List()
{
if (!clientModel || clientModel->node().shutdownRequested()) {
return;
return false;
}

auto [mnList, pindex] = clientModel->getMasternodeList();
if (!pindex) return;
if (!pindex) return false;
auto projectedPayees = mnList->getProjectedMNPayees(pindex);

if (projectedPayees.empty() && mnList->getValidMNsCount() > 0) {
// GetProjectedMNPayees failed to provide results for a list with valid mns.
// Keep current list and let it try again later.
return;
return false;
}

std::map<uint256, CTxDestination> mapCollateralDests;
Expand Down Expand Up @@ -260,6 +263,7 @@ void MasternodeList::updateDIP3List()
}

updateFilteredCount();
return true;
}

void MasternodeList::updateMyMasternodeHashes(const interfaces::MnListPtr& mnList)
Expand All @@ -273,7 +277,7 @@ void MasternodeList::updateMyMasternodeHashes(const interfaces::MnListPtr& mnLis
setOutpts.emplace(outpt);
}

std::set<QString> myHashes;
QSet<QString> myHashes;
mnList->forEachMN(/*only_valid=*/false, [&](const auto& dmn) {
bool fMyMasternode = setOutpts.count(dmn.getCollateralOutpoint()) ||
walletModel->wallet().isSpendable(PKHash(dmn.getKeyIdOwner())) ||
Expand Down
8 changes: 4 additions & 4 deletions src/qt/masternodelist.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
#include <util/system.h>

#include <QMenu>
#include <QSet>
#include <QSortFilterProxyModel>
#include <QString>
#include <QTimer>
#include <QWidget>

#include <atomic>
#include <memory>
#include <set>

namespace interfaces {
class MnList;
Expand Down Expand Up @@ -51,7 +51,7 @@ class MasternodeListSortFilterProxyModel : public QSortFilterProxyModel

void forceInvalidateFilter() { invalidateFilter(); }
void setHideBanned(bool hide) { m_hide_banned = hide; }
void setMyMasternodeHashes(std::set<QString> hashes) { m_my_mn_hashes = std::move(hashes); }
void setMyMasternodeHashes(QSet<QString> hashes) { m_my_mn_hashes = std::move(hashes); }
void setShowOwnedOnly(bool show) { m_show_owned_only = show; }
void setTypeFilter(TypeFilter type) { m_type_filter = type; }

Expand All @@ -61,7 +61,7 @@ class MasternodeListSortFilterProxyModel : public QSortFilterProxyModel
private:
bool m_hide_banned{true};
bool m_show_owned_only{false};
std::set<QString> m_my_mn_hashes;
QSet<QString> m_my_mn_hashes;
TypeFilter m_type_filter{TypeFilter::All};
};

Expand Down Expand Up @@ -96,7 +96,7 @@ class MasternodeList : public QWidget

const MasternodeEntry* GetSelectedEntry();

void updateDIP3List();
bool updateDIP3List();
void updateMyMasternodeHashes(const interfaces::MnListPtr& mnList);

Q_SIGNALS:
Expand Down
6 changes: 3 additions & 3 deletions src/qt/masternodemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
#include <qt/clientmodel.h>
#include <qt/guiutil.h>

#include <QHash>
#include <QObject>
#include <QStringList>

#include <univalue.h>

#include <map>
#include <set>

namespace {
Expand Down Expand Up @@ -354,7 +354,7 @@ void MasternodeModel::remove(int row)

void MasternodeModel::reconcile(MasternodeEntryList&& entries)
{
std::map<QString, int> existing;
QHash<QString, int> existing;
for (int i = 0; i < static_cast<int>(m_data.size()); ++i) {
existing[m_data[i]->proTxHash()] = i;
}
Expand All @@ -364,7 +364,7 @@ void MasternodeModel::reconcile(MasternodeEntryList&& entries)
std::vector<std::unique_ptr<MasternodeEntry>> add;
for (auto& entry : entries) {
if (auto it = existing.find(entry->proTxHash()); it != existing.end()) {
int idx = it->second;
int idx = it.value();
present.insert(idx);
if (m_data[idx]->toTie() != entry->toTie()) {
m_data[idx] = std::move(entry);
Expand Down
20 changes: 10 additions & 10 deletions src/qt/masternodemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,16 @@ class MasternodeEntry
QString m_service{};
QString m_type_description{};
QString m_voting_address{};
std::optional<int32_t> m_collateral_index{std::nullopt};
std::optional<int32_t> m_consecutive_payments{std::nullopt};
std::optional<int32_t> m_pose_ban_height{std::nullopt};
std::optional<int32_t> m_pose_revived_height{std::nullopt};
std::optional<QString> m_collateral_hash{std::nullopt};
std::optional<QString> m_network_addresses{std::nullopt};
std::optional<QString> m_platform_https_addresses{std::nullopt};
std::optional<QString> m_platform_node_id{std::nullopt};
std::optional<QString> m_platform_p2p_addresses{std::nullopt};
std::optional<QString> m_pub_key_operator{std::nullopt};
std::optional<int32_t> m_collateral_index{};
std::optional<int32_t> m_consecutive_payments{};
std::optional<int32_t> m_pose_ban_height{};
std::optional<int32_t> m_pose_revived_height{};
std::optional<QString> m_collateral_hash{};
std::optional<QString> m_network_addresses{};
std::optional<QString> m_platform_https_addresses{};
std::optional<QString> m_platform_node_id{};
std::optional<QString> m_platform_p2p_addresses{};
std::optional<QString> m_pub_key_operator{};
uint16_t m_operator_reward_pct{0};

public:
Expand Down
15 changes: 12 additions & 3 deletions src/qt/proposalmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <univalue.h>

#include <algorithm>
#include <cmath>

Proposal::Proposal(ClientModel* _clientModel, const CGovernanceObject& _govObj) :
clientModel{_clientModel},
Expand All @@ -40,7 +41,7 @@ Proposal::Proposal(ClientModel* _clientModel, const CGovernanceObject& _govObj)
}

if (const UniValue& amountValue = prop_data.find_value("payment_amount"); amountValue.isNum()) {
m_paymentAmount = amountValue.get_real();
m_paymentAmount = llround(amountValue.get_real() * COIN);
}

if (const UniValue& urlValue = prop_data.find_value("url"); urlValue.isStr()) {
Expand Down Expand Up @@ -121,7 +122,7 @@ QVariant ProposalModel::data(const QModelIndex& index, int role) const
case Column::END_DATE:
return proposal->endDate().date();
case Column::PAYMENT_AMOUNT: {
return BitcoinUnits::floorWithUnit(m_display_unit, proposal->paymentAmount() * COIN, false,
return BitcoinUnits::floorWithUnit(m_display_unit, proposal->paymentAmount(), false,
BitcoinUnits::SeparatorStyle::ALWAYS);
}
case Column::IS_ACTIVE:
Expand All @@ -146,7 +147,7 @@ QVariant ProposalModel::data(const QModelIndex& index, int role) const
case Column::END_DATE:
return proposal->endDate();
case Column::PAYMENT_AMOUNT:
return proposal->paymentAmount();
return qlonglong(proposal->paymentAmount());
case Column::IS_ACTIVE:
return proposal->isActive();
case Column::VOTING_STATUS:
Expand Down Expand Up @@ -257,6 +258,14 @@ void ProposalModel::reconcile(ProposalList&& proposals)
}
}

void ProposalModel::setDisplayUnit(const BitcoinUnit& display_unit)
{
m_display_unit = display_unit;
if (!m_data.empty()) {
Q_EMIT dataChanged(createIndex(0, Column::PAYMENT_AMOUNT), createIndex(rowCount() - 1, Column::PAYMENT_AMOUNT));
}
}

void ProposalModel::setVotingParams(int newAbsVoteReq)
{
if (this->nAbsVoteReq == newAbsVoteReq) {
Expand Down
6 changes: 3 additions & 3 deletions src/qt/proposalmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Proposal
ClientModel* clientModel;
const CGovernanceObject govObj;

double m_paymentAmount{0.0};
CAmount m_paymentAmount{0};
QDateTime m_endDate{};
QDateTime m_startDate{};
QString m_hash{};
Expand All @@ -34,7 +34,7 @@ class Proposal
explicit Proposal(ClientModel* _clientModel, const CGovernanceObject& _govObj);

bool isActive() const;
double paymentAmount() const { return m_paymentAmount; }
CAmount paymentAmount() const { return m_paymentAmount; }
int GetAbsoluteYesCount() const;
QDateTime endDate() const { return m_endDate; }
QDateTime startDate() const { return m_startDate; }
Expand Down Expand Up @@ -82,7 +82,7 @@ class ProposalModel : public QAbstractTableModel
void append(std::unique_ptr<Proposal>&& proposal);
void remove(int row);
void reconcile(ProposalList&& proposals);
void setDisplayUnit(const BitcoinUnit& display_unit) { m_display_unit = display_unit; }
void setDisplayUnit(const BitcoinUnit& display_unit);
void setVotingParams(int nAbsVoteReq);
const Proposal* getProposalAt(const QModelIndex& index) const;

Expand Down
Loading
Loading