Implement tab for DIP3 MN list (#2454)

* Implement tab for DIP3 MN list

* Update src/qt/masternodelist.cpp

Co-Authored-By: codablock <ablock84@gmail.com>

* Change "x.xx% to UNSPECIFIED" to "x.xx% but not claimed" for opeartor reward
This commit is contained in:
Alexander Block 2018-11-16 18:19:49 +01:00 committed by GitHub
parent e74810a80e
commit cf2b547b7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 298 additions and 8 deletions

View File

@ -217,7 +217,55 @@
<string>All Masternodes</string>
</attribute>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<item row="1" column="0" rowspan="2" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_filter">
<property name="text">
<string>Filter List:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="filterLineEdit">
<property name="toolTip">
<string>Filter masternode list</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_count">
<property name="text">
<string>Node Count:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="countLabel">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QTableWidget" name="tableWidgetMasternodes">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
@ -270,26 +318,46 @@
</widget>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<widget class="QLabel" name="legacyListNote">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Note: This list represents the legacy and non-deterministic masternode list. It is only active as long as DIP3 has not been fully activated. After SPORK15 activation, this list will be empty.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabDIP3Masternodes">
<attribute name="title">
<string>DIP3 Masternodes</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_filter">
<widget class="QLabel" name="label_filter_2">
<property name="text">
<string>Filter List:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="filterLineEdit">
<widget class="QLineEdit" name="filterLineEditDIP3">
<property name="toolTip">
<string>Filter masternode list</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -302,14 +370,14 @@
</spacer>
</item>
<item>
<widget class="QLabel" name="label_count">
<widget class="QLabel" name="label_count_2">
<property name="text">
<string>Node Count:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="countLabel">
<widget class="QLabel" name="countLabelDIP3">
<property name="text">
<string>0</string>
</property>
@ -317,6 +385,81 @@
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QTableWidget" name="tableWidgetMasternodesDIP3">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<column>
<property name="text">
<string>Address</string>
</property>
</column>
<column>
<property name="text">
<string>Status</string>
</property>
</column>
<column>
<property name="text">
<string>PoSe Score</string>
</property>
</column>
<column>
<property name="text">
<string>Registered</string>
</property>
</column>
<column>
<property name="text">
<string>Last Paid</string>
</property>
</column>
<column>
<property name="text">
<string>Next Payment</string>
</property>
</column>
<column>
<property name="text">
<string>Payee</string>
</property>
</column>
<column>
<property name="text">
<string>Operator Reward</string>
</property>
</column>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="dip3NoteLabel">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Note: This list is not active yet and only for informational purposes. The network is still running in compatibility mode, which means that the non-deterministic masternode list is still active. Only after SPORK15 activation, this list will become the active one. Also, the values in the payment related fields are not used at the moment, but still updated for every block. Please ignore this until SPORK15 activation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>

View File

@ -45,6 +45,13 @@ MasternodeList::MasternodeList(const PlatformStyle* platformStyle, QWidget* pare
int columnActiveWidth = 130;
int columnLastSeenWidth = 130;
int columnPoSeScoreWidth = 80;
int columnRegisteredWidth = 80;
int columnLastPaidWidth = 80;
int columnNextPaymentWidth = 100;
int columnPayeeWidth = 130;
int columnOperatorRewardWidth = 130;
ui->tableWidgetMyMasternodes->setColumnWidth(0, columnAliasWidth);
ui->tableWidgetMyMasternodes->setColumnWidth(1, columnAddressWidth);
ui->tableWidgetMyMasternodes->setColumnWidth(2, columnProtocolWidth);
@ -58,6 +65,15 @@ MasternodeList::MasternodeList(const PlatformStyle* platformStyle, QWidget* pare
ui->tableWidgetMasternodes->setColumnWidth(3, columnActiveWidth);
ui->tableWidgetMasternodes->setColumnWidth(4, columnLastSeenWidth);
ui->tableWidgetMasternodesDIP3->setColumnWidth(0, columnAddressWidth);
ui->tableWidgetMasternodesDIP3->setColumnWidth(1, columnStatusWidth);
ui->tableWidgetMasternodesDIP3->setColumnWidth(2, columnPoSeScoreWidth);
ui->tableWidgetMasternodesDIP3->setColumnWidth(3, columnRegisteredWidth);
ui->tableWidgetMasternodesDIP3->setColumnWidth(4, columnLastPaidWidth);
ui->tableWidgetMasternodesDIP3->setColumnWidth(5, columnNextPaymentWidth);
ui->tableWidgetMasternodesDIP3->setColumnWidth(6, columnPayeeWidth);
ui->tableWidgetMasternodesDIP3->setColumnWidth(7, columnOperatorRewardWidth);
ui->tableWidgetMyMasternodes->setContextMenuPolicy(Qt::CustomContextMenu);
QAction* startAliasAction = new QAction(tr("Start alias"), this);
@ -70,11 +86,15 @@ MasternodeList::MasternodeList(const PlatformStyle* platformStyle, QWidget* pare
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateNodeList()));
connect(timer, SIGNAL(timeout()), this, SLOT(updateMyNodeList()));
connect(timer, SIGNAL(timeout()), this, SLOT(updateDIP3List()));
timer->start(1000);
fFilterUpdated = false;
fFilterUpdatedDIP3 = false;
nTimeFilterUpdated = GetTime();
nTimeFilterUpdatedDIP3 = GetTime();
updateNodeList();
updateDIP3List();
}
MasternodeList::~MasternodeList()
@ -288,9 +308,16 @@ void MasternodeList::updateNodeList()
ui->tableWidgetMasternodes->setSortingEnabled(false);
ui->tableWidgetMasternodes->clearContents();
ui->tableWidgetMasternodes->setRowCount(0);
std::map<COutPoint, CMasternode> mapMasternodes = mnodeman.GetFullMasternodeMap();
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
ui->countLabel->setText(QString::number(0));
return;
}
int offsetFromUtc = GetOffsetFromUtc();
std::map<COutPoint, CMasternode> mapMasternodes = mnodeman.GetFullMasternodeMap();
for (const auto& mnpair : mapMasternodes) {
CMasternode mn = mnpair.second;
// populate list
@ -325,6 +352,110 @@ void MasternodeList::updateNodeList()
ui->tableWidgetMasternodes->setSortingEnabled(true);
}
void MasternodeList::updateDIP3List()
{
TRY_LOCK(cs_dip3list, fLockAcquired);
if (!fLockAcquired) return;
static int64_t nTimeListUpdated = GetTime();
// to prevent high cpu usage update only once in MASTERNODELIST_UPDATE_SECONDS seconds
// or MASTERNODELIST_FILTER_COOLDOWN_SECONDS seconds after filter was last changed
int64_t nSecondsToWait = fFilterUpdatedDIP3
? nTimeFilterUpdatedDIP3 - GetTime() + MASTERNODELIST_FILTER_COOLDOWN_SECONDS
: nTimeListUpdated - GetTime() + MASTERNODELIST_UPDATE_SECONDS;
if (fFilterUpdatedDIP3) {
ui->countLabel->setText(QString::fromStdString(strprintf("Please wait... %d", nSecondsToWait)));
}
if (nSecondsToWait > 0) return;
nTimeListUpdated = GetTime();
fFilterUpdatedDIP3 = false;
QString strToFilter;
ui->countLabelDIP3->setText("Updating...");
ui->tableWidgetMasternodesDIP3->setSortingEnabled(false);
ui->tableWidgetMasternodesDIP3->clearContents();
ui->tableWidgetMasternodesDIP3->setRowCount(0);
if (deterministicMNManager->IsDeterministicMNsSporkActive()) {
ui->dip3NoteLabel->setVisible(false);
}
auto mnList = deterministicMNManager->GetListAtChainTip();
auto projectedPayees = mnList.GetProjectedMNPayees(mnList.GetValidMNsCount());
std::map<uint256, int> nextPayments;
for (size_t i = 0; i < projectedPayees.size(); i++) {
const auto& dmn = projectedPayees[i];
nextPayments.emplace(dmn->proTxHash, mnList.GetHeight() + (int)i + 1);
}
mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
// populate list
// Address, Protocol, Status, Active Seconds, Last Seen, Pub Key
QTableWidgetItem* addressItem = new QTableWidgetItem(QString::fromStdString(dmn->pdmnState->addr.ToString()));
QTableWidgetItem* statusItem = new QTableWidgetItem(mnList.IsMNValid(dmn) ? tr("ENABLED") : (mnList.IsMNPoSeBanned(dmn) ? tr("POSE_BANNED") : tr("UNKNOWN")));
QTableWidgetItem* PoSeScoreItem = new QTableWidgetItem(QString::number(dmn->pdmnState->nPoSePenalty));
QTableWidgetItem* registeredItem = new QTableWidgetItem(QString::number(dmn->pdmnState->nRegisteredHeight));
QTableWidgetItem* lastPaidItem = new QTableWidgetItem(QString::number(dmn->pdmnState->nLastPaidHeight));
QTableWidgetItem* nextPaymentItem = new QTableWidgetItem(nextPayments.count(dmn->proTxHash) ? QString::number(nextPayments[dmn->proTxHash]) : tr("UNKNOWN"));
CTxDestination payeeDest;
QString payeeStr;
if (ExtractDestination(dmn->pdmnState->scriptPayout, payeeDest)) {
payeeStr = QString::fromStdString(CBitcoinAddress(payeeDest).ToString());
} else {
payeeStr = tr("UNKNOWN");
}
QTableWidgetItem* payeeItem = new QTableWidgetItem(payeeStr);
QString operatorRewardStr;
if (dmn->nOperatorReward) {
operatorRewardStr += QString::number(dmn->nOperatorReward / 100.0, 'f', 2) + "%";
if (dmn->pdmnState->scriptOperatorPayout != CScript()) {
CTxDestination dest;
if (ExtractDestination(dmn->pdmnState->scriptOperatorPayout, dest)) {
operatorRewardStr += tr(" to %1").arg(QString::fromStdString(CBitcoinAddress(payeeDest).ToString()));
} else {
operatorRewardStr += tr(" to UNKNOWN");
}
} else {
operatorRewardStr += tr(" but not claimed");
}
} else {
operatorRewardStr = tr("NONE");
}
QTableWidgetItem* operatorRewardItem = new QTableWidgetItem(operatorRewardStr);
if (strCurrentFilterDIP3 != "") {
strToFilter = addressItem->text() + " " +
statusItem->text() + " " +
PoSeScoreItem->text() + " " +
registeredItem->text() + " " +
lastPaidItem->text() + " " +
nextPaymentItem->text() + " " +
payeeItem->text() + " " +
operatorRewardItem->text();
if (!strToFilter.contains(strCurrentFilterDIP3)) return;
}
ui->tableWidgetMasternodesDIP3->insertRow(0);
ui->tableWidgetMasternodesDIP3->setItem(0, 0, addressItem);
ui->tableWidgetMasternodesDIP3->setItem(0, 1, statusItem);
ui->tableWidgetMasternodesDIP3->setItem(0, 2, PoSeScoreItem);
ui->tableWidgetMasternodesDIP3->setItem(0, 3, registeredItem);
ui->tableWidgetMasternodesDIP3->setItem(0, 4, lastPaidItem);
ui->tableWidgetMasternodesDIP3->setItem(0, 5, nextPaymentItem);
ui->tableWidgetMasternodesDIP3->setItem(0, 6, payeeItem);
ui->tableWidgetMasternodesDIP3->setItem(0, 7, operatorRewardItem);
});
ui->countLabelDIP3->setText(QString::number(ui->tableWidgetMasternodesDIP3->rowCount()));
ui->tableWidgetMasternodesDIP3->setSortingEnabled(true);
}
void MasternodeList::on_filterLineEdit_textChanged(const QString& strFilterIn)
{
strCurrentFilter = strFilterIn;
@ -333,6 +464,14 @@ void MasternodeList::on_filterLineEdit_textChanged(const QString& strFilterIn)
ui->countLabel->setText(QString::fromStdString(strprintf("Please wait... %d", MASTERNODELIST_FILTER_COOLDOWN_SECONDS)));
}
void MasternodeList::on_filterLineEditDIP3_textChanged(const QString& strFilterIn)
{
strCurrentFilterDIP3 = strFilterIn;
nTimeFilterUpdatedDIP3 = GetTime();
fFilterUpdatedDIP3 = true;
ui->countLabelDIP3->setText(QString::fromStdString(strprintf("Please wait... %d", MASTERNODELIST_FILTER_COOLDOWN_SECONDS)));
}
void MasternodeList::on_startButton_clicked()
{
std::string strAlias;

View File

@ -44,12 +44,15 @@ public:
private:
QMenu* contextMenu;
int64_t nTimeFilterUpdated;
int64_t nTimeFilterUpdatedDIP3;
bool fFilterUpdated;
bool fFilterUpdatedDIP3;
public Q_SLOTS:
void updateMyMasternodeInfo(QString strAlias, QString strAddr, const COutPoint& outpoint);
void updateMyNodeList(bool fForce = false);
void updateNodeList();
void updateDIP3List();
Q_SIGNALS:
void doubleClicked(const QModelIndex&);
@ -66,11 +69,16 @@ private:
// Protects tableWidgetMyMasternodes
CCriticalSection cs_mymnlist;
// Protects tableWidgetMasternodesDIP3
CCriticalSection cs_dip3list;
QString strCurrentFilter;
QString strCurrentFilterDIP3;
private Q_SLOTS:
void showContextMenu(const QPoint&);
void on_filterLineEdit_textChanged(const QString& strFilterIn);
void on_filterLineEditDIP3_textChanged(const QString& strFilterIn);
void on_QRButton_clicked();
void on_startButton_clicked();
void on_startAllButton_clicked();