Skip to content

Commit 482a549

Browse files
authored
Add collateral, owner and voting addresses to masternode list table (#3207)
* Add collateral, owner and voting addresses to masternode list table * Adjust column names in masternode list table * Slightly refactor updateDIP3List() * Lock cs_main in updateDIP3List early to avoid GUI frezes * Update MN list in GUI 10 times less often while blockchain is still syncing * Move GetUTXO calls outside of main update loop * Fill coin cache for masternode UTXOs on start
1 parent 37f96f5 commit 482a549

File tree

3 files changed

+84
-15
lines changed

3 files changed

+84
-15
lines changed

src/init.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,20 @@ void ThreadImport(std::vector<fs::path> vImportFiles)
831831
// GetMainSignals().UpdatedBlockTip(chainActive.Tip());
832832
pdsNotificationInterface->InitializeCurrentBlockTip();
833833

834+
{
835+
// Get all UTXOs for each MN collateral in one go so that we can fill coin cache early
836+
// and reduce further locking overhead for cs_main in other parts of code inclluding GUI
837+
LogPrintf("Filling coin cache with masternode UTXOs...\n");
838+
LOCK(cs_main);
839+
int64_t nStart = GetTimeMillis();
840+
auto mnList = deterministicMNManager->GetListAtChainTip();
841+
mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
842+
Coin coin;
843+
GetUTXOCoin(dmn->collateralOutpoint, coin);
844+
});
845+
LogPrintf("Filling coin cache with masternode UTXOs: done in %dms\n", GetTimeMillis() - nStart);
846+
}
847+
834848
if (fMasternodeMode) {
835849
assert(activeMasternodeManager);
836850
activeMasternodeManager->Init();

src/qt/forms/masternodelist.ui

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@
126126
</attribute>
127127
<column>
128128
<property name="text">
129-
<string>Address</string>
129+
<string>Service</string>
130130
</property>
131131
</column>
132132
<column>
@@ -156,14 +156,29 @@
156156
</column>
157157
<column>
158158
<property name="text">
159-
<string>Payee</string>
159+
<string>Payout Address</string>
160160
</property>
161161
</column>
162162
<column>
163163
<property name="text">
164164
<string>Operator Reward</string>
165165
</property>
166166
</column>
167+
<column>
168+
<property name="text">
169+
<string>Collateral Address</string>
170+
</property>
171+
</column>
172+
<column>
173+
<property name="text">
174+
<string>Owner Address</string>
175+
</property>
176+
</column>
177+
<column>
178+
<property name="text">
179+
<string>Voting Address</string>
180+
</property>
181+
</column>
167182
</widget>
168183
</item>
169184
</layout>

src/qt/masternodelist.cpp

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
#include "masternode/activemasternode.h"
55
#include "clientmodel.h"
66
#include "clientversion.h"
7+
#include "coins.h"
78
#include "guiutil.h"
89
#include "init.h"
910
#include "masternode/masternode-sync.h"
1011
#include "netbase.h"
1112
#include "sync.h"
13+
#include "validation.h"
1214
#include "wallet/wallet.h"
1315
#include "walletmodel.h"
1416

@@ -49,6 +51,9 @@ MasternodeList::MasternodeList(const PlatformStyle* platformStyle, QWidget* pare
4951
int columnNextPaymentWidth = 100;
5052
int columnPayeeWidth = 130;
5153
int columnOperatorRewardWidth = 130;
54+
int columnCollateralWidth = 130;
55+
int columnOwnerWidth = 130;
56+
int columnVotingWidth = 130;
5257

5358
ui->tableWidgetMasternodesDIP3->setColumnWidth(0, columnAddressWidth);
5459
ui->tableWidgetMasternodesDIP3->setColumnWidth(1, columnStatusWidth);
@@ -58,11 +63,14 @@ MasternodeList::MasternodeList(const PlatformStyle* platformStyle, QWidget* pare
5863
ui->tableWidgetMasternodesDIP3->setColumnWidth(5, columnNextPaymentWidth);
5964
ui->tableWidgetMasternodesDIP3->setColumnWidth(6, columnPayeeWidth);
6065
ui->tableWidgetMasternodesDIP3->setColumnWidth(7, columnOperatorRewardWidth);
66+
ui->tableWidgetMasternodesDIP3->setColumnWidth(8, columnCollateralWidth);
67+
ui->tableWidgetMasternodesDIP3->setColumnWidth(9, columnOwnerWidth);
68+
ui->tableWidgetMasternodesDIP3->setColumnWidth(10, columnVotingWidth);
6169

6270
// dummy column for proTxHash
6371
// TODO use a proper table model for the MN list
64-
ui->tableWidgetMasternodesDIP3->insertColumn(8);
65-
ui->tableWidgetMasternodesDIP3->setColumnHidden(8, true);
72+
ui->tableWidgetMasternodesDIP3->insertColumn(11);
73+
ui->tableWidgetMasternodesDIP3->setColumnHidden(11, true);
6674

6775
ui->tableWidgetMasternodesDIP3->setContextMenuPolicy(Qt::CustomContextMenu);
6876

@@ -132,7 +140,8 @@ void MasternodeList::updateDIP3ListScheduled()
132140
fFilterUpdatedDIP3 = false;
133141
}
134142
} else if (mnListChanged) {
135-
int64_t nSecondsToWait = nTimeUpdatedDIP3 - GetTime() + MASTERNODELIST_UPDATE_SECONDS;
143+
int64_t nMnListUpdateSecods = masternodeSync.IsBlockchainSynced() ? MASTERNODELIST_UPDATE_SECONDS : MASTERNODELIST_UPDATE_SECONDS*10;
144+
int64_t nSecondsToWait = nTimeUpdatedDIP3 - GetTime() + nMnListUpdateSecods;
136145

137146
if (nSecondsToWait <= 0) {
138147
updateDIP3List();
@@ -147,6 +156,22 @@ void MasternodeList::updateDIP3List()
147156
return;
148157
}
149158

159+
auto mnList = clientModel->getMasternodeList();
160+
std::map<uint256, CTxDestination> mapCollateralDests;
161+
162+
{
163+
// Get all UTXOs for each MN collateral in one go so that we can reduce locking overhead for cs_main
164+
// We also do this outside of the below Qt list update loop to reduce cs_main locking time to a minimum
165+
LOCK(cs_main);
166+
mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
167+
CTxDestination collateralDest;
168+
Coin coin;
169+
if (GetUTXOCoin(dmn->collateralOutpoint, coin) && ExtractDestination(coin.out.scriptPubKey, collateralDest)) {
170+
mapCollateralDests.emplace(dmn->proTxHash, collateralDest);
171+
}
172+
});
173+
}
174+
150175
LOCK(cs_dip3list);
151176

152177
QString strToFilter;
@@ -155,7 +180,6 @@ void MasternodeList::updateDIP3List()
155180
ui->tableWidgetMasternodesDIP3->clearContents();
156181
ui->tableWidgetMasternodesDIP3->setRowCount(0);
157182

158-
auto mnList = clientModel->getMasternodeList();
159183
nTimeUpdatedDIP3 = GetTime();
160184

161185
auto projectedPayees = mnList.GetProjectedMNPayees(mnList.GetValidMNsCount());
@@ -193,17 +217,15 @@ void MasternodeList::updateDIP3List()
193217
QTableWidgetItem* nextPaymentItem = new QTableWidgetItem(nextPayments.count(dmn->proTxHash) ? QString::number(nextPayments[dmn->proTxHash]) : tr("UNKNOWN"));
194218

195219
CTxDestination payeeDest;
196-
QString payeeStr;
220+
QString payeeStr = tr("UNKNOWN");
197221
if (ExtractDestination(dmn->pdmnState->scriptPayout, payeeDest)) {
198222
payeeStr = QString::fromStdString(CBitcoinAddress(payeeDest).ToString());
199-
} else {
200-
payeeStr = tr("UNKNOWN");
201223
}
202224
QTableWidgetItem* payeeItem = new QTableWidgetItem(payeeStr);
203225

204-
QString operatorRewardStr;
226+
QString operatorRewardStr = tr("NONE");
205227
if (dmn->nOperatorReward) {
206-
operatorRewardStr += QString::number(dmn->nOperatorReward / 100.0, 'f', 2) + "% ";
228+
operatorRewardStr = QString::number(dmn->nOperatorReward / 100.0, 'f', 2) + "% ";
207229

208230
if (dmn->pdmnState->scriptOperatorPayout != CScript()) {
209231
CTxDestination operatorDest;
@@ -215,10 +237,22 @@ void MasternodeList::updateDIP3List()
215237
} else {
216238
operatorRewardStr += tr("but not claimed");
217239
}
218-
} else {
219-
operatorRewardStr = tr("NONE");
220240
}
221241
QTableWidgetItem* operatorRewardItem = new QTableWidgetItem(operatorRewardStr);
242+
243+
QString collateralStr = tr("UNKNOWN");
244+
auto collateralDestIt = mapCollateralDests.find(dmn->proTxHash);
245+
if (collateralDestIt != mapCollateralDests.end()) {
246+
collateralStr = QString::fromStdString(CBitcoinAddress(collateralDestIt->second).ToString());
247+
}
248+
QTableWidgetItem* collateralItem = new QTableWidgetItem(collateralStr);
249+
250+
QString ownerStr = QString::fromStdString(CBitcoinAddress(dmn->pdmnState->keyIDOwner).ToString());
251+
QTableWidgetItem* ownerItem = new QTableWidgetItem(ownerStr);
252+
253+
QString votingStr = QString::fromStdString(CBitcoinAddress(dmn->pdmnState->keyIDVoting).ToString());
254+
QTableWidgetItem* votingItem = new QTableWidgetItem(votingStr);
255+
222256
QTableWidgetItem* proTxHashItem = new QTableWidgetItem(QString::fromStdString(dmn->proTxHash.ToString()));
223257

224258
if (strCurrentFilterDIP3 != "") {
@@ -230,6 +264,9 @@ void MasternodeList::updateDIP3List()
230264
nextPaymentItem->text() + " " +
231265
payeeItem->text() + " " +
232266
operatorRewardItem->text() + " " +
267+
collateralItem->text() + " " +
268+
ownerItem->text() + " " +
269+
votingItem->text() + " " +
233270
proTxHashItem->text();
234271
if (!strToFilter.contains(strCurrentFilterDIP3)) return;
235272
}
@@ -243,7 +280,10 @@ void MasternodeList::updateDIP3List()
243280
ui->tableWidgetMasternodesDIP3->setItem(0, 5, nextPaymentItem);
244281
ui->tableWidgetMasternodesDIP3->setItem(0, 6, payeeItem);
245282
ui->tableWidgetMasternodesDIP3->setItem(0, 7, operatorRewardItem);
246-
ui->tableWidgetMasternodesDIP3->setItem(0, 8, proTxHashItem);
283+
ui->tableWidgetMasternodesDIP3->setItem(0, 8, collateralItem);
284+
ui->tableWidgetMasternodesDIP3->setItem(0, 9, ownerItem);
285+
ui->tableWidgetMasternodesDIP3->setItem(0, 10, votingItem);
286+
ui->tableWidgetMasternodesDIP3->setItem(0, 11, proTxHashItem);
247287
});
248288

249289
ui->countLabelDIP3->setText(QString::number(ui->tableWidgetMasternodesDIP3->rowCount()));
@@ -282,7 +322,7 @@ CDeterministicMNCPtr MasternodeList::GetSelectedDIP3MN()
282322

283323
QModelIndex index = selected.at(0);
284324
int nSelectedRow = index.row();
285-
strProTxHash = ui->tableWidgetMasternodesDIP3->item(nSelectedRow, 8)->text().toStdString();
325+
strProTxHash = ui->tableWidgetMasternodesDIP3->item(nSelectedRow, 11)->text().toStdString();
286326
}
287327

288328
uint256 proTxHash;

0 commit comments

Comments
 (0)