// Copyright (c) 2017-2019 The PIVX developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "privacydialog.h" #include "ui_privacydialog.h" #include "addressbookpage.h" #include "addresstablemodel.h" #include "bitcoinunits.h" #include "coincontroldialog.h" #include "libzerocoin/Denominations.h" #include "optionsmodel.h" #include "sendcoinsentry.h" #include "walletmodel.h" #include "coincontrol.h" #include "zagrcontroldialog.h" #include "spork.h" #include "askpassphrasedialog.h" #include #include #include #include #include #include PrivacyDialog::PrivacyDialog(QWidget* parent) : QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowCloseButtonHint), ui(new Ui::PrivacyDialog), walletModel(0), currentBalance(-1), fDenomsMinimized(true) { nDisplayUnit = 0; // just make sure it's not unitialized ui->setupUi(this); // "Spending 999999 zAGR ought to be enough for anybody." - Bill Gates, 2017 ui->zAGRpayAmount->setValidator( new QDoubleValidator(0.0, 21000000.0, 20, this) ); //ui->labelMintAmountValue->setValidator( new QIntValidator(0, 999999, this) ); // disable MINT // Default texts for (mini-) coincontrol //ui->labelCoinControlQuantity->setText (tr("Coins automatically selected")); // disable MINT //ui->labelCoinControlAmount->setText (tr("Coins automatically selected")); // disable MINT ui->labelzAGRSyncStatus->setText("(" + tr("out of sync") + ")"); // Sunken frame for minting messages ui->TEMintStatus->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); ui->TEMintStatus->setLineWidth (2); ui->TEMintStatus->setMidLineWidth (2); ui->TEMintStatus->setPlainText(tr("Mint Status: Okay")); // Coin Control signals /* [disable MINT and coinControl] connect(ui->pushButtonCoinControl, SIGNAL(clicked()), this, SLOT(coinControlButtonClicked())); // Coin Control: clipboard actions QAction* clipboardQuantityAction = new QAction(tr("Copy quantity"), this); QAction* clipboardAmountAction = new QAction(tr("Copy amount"), this); connect(clipboardQuantityAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardQuantity())); connect(clipboardAmountAction, SIGNAL(triggered()), this, SLOT(coinControlClipboardAmount())); ui->labelCoinControlQuantity->addAction(clipboardQuantityAction); ui->labelCoinControlAmount->addAction(clipboardAmountAction); */ // Denomination labels ui->labelzDenom1Text->setText(tr("Denom. with value 1:")); ui->labelzDenom2Text->setText(tr("Denom. with value 5:")); ui->labelzDenom3Text->setText(tr("Denom. with value 10:")); ui->labelzDenom4Text->setText(tr("Denom. with value 50:")); ui->labelzDenom5Text->setText(tr("Denom. with value 100:")); ui->labelzDenom6Text->setText(tr("Denom. with value 500:")); ui->labelzDenom7Text->setText(tr("Denom. with value 1000:")); ui->labelzDenom8Text->setText(tr("Denom. with value 5000:")); // AutoMint status ui->label_AutoMintStatus->setText(tr("AutoMint Status:")); // Global Supply labels ui->labelZsupplyText1->setText(tr("Denom. 1:")); ui->labelZsupplyText5->setText(tr("Denom. 5:")); ui->labelZsupplyText10->setText(tr("Denom. 10:")); ui->labelZsupplyText50->setText(tr("Denom. 50:")); ui->labelZsupplyText100->setText(tr("Denom. 100:")); ui->labelZsupplyText500->setText(tr("Denom. 500:")); ui->labelZsupplyText1000->setText(tr("Denom. 1000:")); ui->labelZsupplyText5000->setText(tr("Denom. 5000:")); // Agrarian settings QSettings settings; if (!settings.contains("fMinimizeChange")){ fMinimizeChange = false; settings.setValue("fMinimizeChange", fMinimizeChange); } else{ fMinimizeChange = settings.value("fMinimizeChange").toBool(); } ui->checkBoxMinimizeChange->setChecked(fMinimizeChange); // Start with displaying the "out of sync" warnings showOutOfSyncWarning(true); // Hide those placeholder elements needed for CoinControl interaction ui->WarningLabel->hide(); // Explanatory text visible in QT-Creator ui->dummyHideWidget->hide(); // Dummy widget with elements to hide // Set labels/buttons depending on SPORK_16 status updateSPORK16Status(); // init Denoms section if(!settings.contains("fDenomsSectionMinimized")) settings.setValue("fDenomsSectionMinimized", true); minimizeDenomsSection(settings.value("fDenomsSectionMinimized").toBool()); ui->checkBoxMintChange->setVisible(false); } PrivacyDialog::~PrivacyDialog() { QSettings settings; settings.setValue("fDenomsSectionMinimized", fDenomsMinimized); delete ui; } void PrivacyDialog::setModel(WalletModel* walletModel) { this->walletModel = walletModel; if (walletModel && walletModel->getOptionsModel()) { // Keep up to date with wallet setBalance(walletModel->getBalance(), walletModel->getUnconfirmedBalance(), walletModel->getImmatureBalance(), walletModel->getZerocoinBalance(), walletModel->getUnconfirmedZerocoinBalance(), walletModel->getImmatureZerocoinBalance(), walletModel->getWatchBalance(), walletModel->getWatchUnconfirmedBalance(), walletModel->getWatchImmatureBalance()); connect(walletModel, SIGNAL(balanceChanged(CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount)), this, SLOT(setBalance(CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount))); connect(walletModel->getOptionsModel(), SIGNAL(zeromintEnableChanged(bool)), this, SLOT(updateAutomintStatus())); connect(walletModel->getOptionsModel(), SIGNAL(zeromintPercentageChanged(int)), this, SLOT(updateAutomintStatus())); } } void PrivacyDialog::on_pasteButton_clicked() { // Paste text from clipboard into recipient field ui->payTo->setText(QApplication::clipboard()->text()); } void PrivacyDialog::on_addressBookButton_clicked() { if (!walletModel || !walletModel->getOptionsModel()) return; AddressBookPage dlg(AddressBookPage::ForSelection, AddressBookPage::SendingTab, this); dlg.setModel(walletModel->getAddressTableModel()); if (dlg.exec()) { ui->payTo->setText(dlg.getReturnValue()); ui->zAGRpayAmount->setFocus(); } } /* disable MINT * void PrivacyDialog::on_pushButtonMintzAGR_clicked() { if (!walletModel || !walletModel->getOptionsModel()) return; if(GetAdjustedTime() > GetSporkValue(SPORK_16_ZEROCOIN_MAINTENANCE_MODE)) { QMessageBox::information(this, tr("Mint Zerocoin"), tr("zAGR is currently undergoing maintenance."), QMessageBox::Ok, QMessageBox::Ok); return; } // Reset message text ui->TEMintStatus->setPlainText(tr("Mint Status: Okay")); // Request unlock if wallet was locked or unlocked for mixing: WalletModel::EncryptionStatus encStatus = walletModel->getEncryptionStatus(); if (encStatus == walletModel->Locked) { WalletModel::UnlockContext ctx(walletModel->requestUnlock(AskPassphraseDialog::Context::Mint_zAGR, true)); if (!ctx.isValid()) { // Unlock wallet was cancelled ui->TEMintStatus->setPlainText(tr("Error: Your wallet is locked. Please enter the wallet passphrase first.")); return; } } QString sAmount = ui->labelMintAmountValue->text(); CAmount nAmount = sAmount.toInt() * COIN; // Minting amount must be > 0 if(nAmount <= 0){ ui->TEMintStatus->setPlainText(tr("Message: Enter an amount > 0.")); return; } ui->TEMintStatus->setPlainText(tr("Minting ") + ui->labelMintAmountValue->text() + " zAGR..."); ui->TEMintStatus->repaint (); int64_t nTime = GetTimeMillis(); CWalletTx wtx; vector vMints; string strError = pwalletMain->MintZerocoin(nAmount, wtx, vMints, CoinControlDialog::coinControl); // Return if something went wrong during minting if (strError != ""){ ui->TEMintStatus->setPlainText(QString::fromStdString(strError)); return; } double fDuration = (double)(GetTimeMillis() - nTime)/1000.0; // Minting successfully finished. Show some stats for entertainment. QString strStatsHeader = tr("Successfully minted ") + ui->labelMintAmountValue->text() + tr(" zAGR in ") + QString::number(fDuration) + tr(" sec. Used denominations:\n"); // Clear amount to avoid double spending when accidentally clicking twice ui->labelMintAmountValue->setText ("0"); QString strStats = ""; ui->TEMintStatus->setPlainText(strStatsHeader); for (CDeterministicMint dMint : vMints) { boost::this_thread::sleep(boost::posix_time::milliseconds(100)); strStats = strStats + QString::number(dMint.GetDenomination()) + " "; ui->TEMintStatus->setPlainText(strStatsHeader + strStats); ui->TEMintStatus->repaint (); } ui->TEMintStatus->verticalScrollBar()->setValue(ui->TEMintStatus->verticalScrollBar()->maximum()); // Automatically scroll to end of text // Available balance isn't always updated, so force it. setBalance(walletModel->getBalance(), walletModel->getUnconfirmedBalance(), walletModel->getImmatureBalance(), walletModel->getZerocoinBalance(), walletModel->getUnconfirmedZerocoinBalance(), walletModel->getImmatureZerocoinBalance(), walletModel->getWatchBalance(), walletModel->getWatchUnconfirmedBalance(), walletModel->getWatchImmatureBalance()); coinControlUpdateLabels(); return; } */ void PrivacyDialog::on_pushButtonMintReset_clicked() { ui->TEMintStatus->setPlainText(tr("Starting ResetMintZerocoin: rescanning complete blockchain, this will need up to 30 minutes depending on your hardware.\nPlease be patient...")); ui->TEMintStatus->repaint (); int64_t nTime = GetTimeMillis(); string strResetMintResult = pwalletMain->ResetMintZerocoin(); double fDuration = (double)(GetTimeMillis() - nTime)/1000.0; ui->TEMintStatus->setPlainText(QString::fromStdString(strResetMintResult) + tr("Duration: ") + QString::number(fDuration) + tr(" sec.\n")); ui->TEMintStatus->repaint (); ui->TEMintStatus->verticalScrollBar()->setValue(ui->TEMintStatus->verticalScrollBar()->maximum()); // Automatically scroll to end of text return; } void PrivacyDialog::on_pushButtonSpentReset_clicked() { ui->TEMintStatus->setPlainText(tr("Starting ResetSpentZerocoin: ")); ui->TEMintStatus->repaint (); int64_t nTime = GetTimeMillis(); string strResetSpentResult = pwalletMain->ResetSpentZerocoin(); double fDuration = (double)(GetTimeMillis() - nTime)/1000.0; ui->TEMintStatus->setPlainText(QString::fromStdString(strResetSpentResult) + tr("Duration: ") + QString::number(fDuration) + tr(" sec.\n")); ui->TEMintStatus->repaint (); ui->TEMintStatus->verticalScrollBar()->setValue(ui->TEMintStatus->verticalScrollBar()->maximum()); // Automatically scroll to end of text return; } void PrivacyDialog::on_pushButtonSpendzAGR_clicked() { if (!walletModel || !walletModel->getOptionsModel() || !pwalletMain) return; if(GetAdjustedTime() > GetSporkValue(SPORK_16_ZEROCOIN_MAINTENANCE_MODE)) { QMessageBox::information(this, tr("Mint Zerocoin"), tr("zAGR is currently undergoing maintenance."), QMessageBox::Ok, QMessageBox::Ok); return; } // Request unlock if wallet was locked or unlocked for mixing: WalletModel::EncryptionStatus encStatus = walletModel->getEncryptionStatus(); if (encStatus == walletModel->Locked || encStatus == walletModel->UnlockedForAnonymizationOnly) { WalletModel::UnlockContext ctx(walletModel->requestUnlock(AskPassphraseDialog::Context::Send_zAGR, true)); if (!ctx.isValid()) { // Unlock wallet was cancelled return; } // Wallet is unlocked now, sedn zAGR sendzAGR(); return; } // Wallet already unlocked or not encrypted at all, send zAGR sendzAGR(); } void PrivacyDialog::on_pushButtonZPivControl_clicked() { if (!walletModel || !walletModel->getOptionsModel()) return; ZPivControlDialog* zPivControl = new ZPivControlDialog(this); zPivControl->setModel(walletModel); zPivControl->exec(); } void PrivacyDialog::setZPivControlLabels(int64_t nAmount, int nQuantity) { ui->labelzPivSelected_int->setText(QString::number(nAmount)); ui->labelQuantitySelected_int->setText(QString::number(nQuantity)); } static inline int64_t roundint64(double d) { return (int64_t)(d > 0 ? d + 0.5 : d - 0.5); } void PrivacyDialog::sendzAGR() { QSettings settings; // Handle 'Pay To' address options CBitcoinAddress address(ui->payTo->text().toStdString()); if(ui->payTo->text().isEmpty()){ QMessageBox::information(this, tr("Spend Zerocoin"), tr("No 'Pay To' address provided, creating local payment"), QMessageBox::Ok, QMessageBox::Ok); } else{ if (!address.IsValid()) { QMessageBox::warning(this, tr("Spend Zerocoin"), tr("Invalid Agrarian Address"), QMessageBox::Ok, QMessageBox::Ok); ui->payTo->setFocus(); return; } } // Double is allowed now double dAmount = ui->zAGRpayAmount->text().toDouble(); CAmount nAmount = roundint64(dAmount* COIN); // Check amount validity if (!MoneyRange(nAmount) || nAmount <= 0.0) { QMessageBox::warning(this, tr("Spend Zerocoin"), tr("Invalid Send Amount"), QMessageBox::Ok, QMessageBox::Ok); ui->zAGRpayAmount->setFocus(); return; } // Convert change to zAGR bool fMintChange = false;// ui->checkBoxMintChange->isChecked(); // Persist minimize change setting fMinimizeChange = ui->checkBoxMinimizeChange->isChecked(); settings.setValue("fMinimizeChange", fMinimizeChange); // Warn for additional fees if amount is not an integer and change as zAGR is requested bool fWholeNumber = floor(dAmount) == dAmount; double dzFee = 0.0; if(!fWholeNumber) dzFee = 1.0 - (dAmount - floor(dAmount)); if(!fWholeNumber && fMintChange){ QString strFeeWarning = "You've entered an amount with fractional digits and want the change to be converted to Zerocoin.

"; strFeeWarning += QString::number(dzFee, 'f', 8) + " AGR will be added to the standard transaction fees!
"; QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm additional Fees"), strFeeWarning, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel); if (retval != QMessageBox::Yes) { // Sending canceled ui->zAGRpayAmount->setFocus(); return; } } // Spend confirmation message box // Add address info if available QString strAddressLabel = ""; if(!ui->payTo->text().isEmpty() && !ui->addAsLabel->text().isEmpty()){ strAddressLabel = "
(" + ui->addAsLabel->text() + ") "; } // General info QString strQuestionString = tr("Are you sure you want to send?

"); QString strAmount = "" + QString::number(dAmount, 'f', 8) + " zAGR"; QString strAddress = tr(" to address ") + QString::fromStdString(address.ToString()) + strAddressLabel + "
"; if(ui->payTo->text().isEmpty()){ // No address provided => send to local address strAddress = tr(" to a newly generated (unused and therefore anonymous) local address
"); } strQuestionString += strAmount + strAddress; // Display message box QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm send coins"), strQuestionString, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel); if (retval != QMessageBox::Yes) { // Sending canceled return; } int64_t nTime = GetTimeMillis(); ui->TEMintStatus->setPlainText(tr("Spending Zerocoin.\nComputationally expensive, might need several minutes depending on your hardware.\nPlease be patient...")); ui->TEMintStatus->repaint(); // use mints from zAGR selector if applicable vector vMintsToFetch; vector vMintsSelected; if (!ZPivControlDialog::setSelectedMints.empty()) { vMintsToFetch = ZPivControlDialog::GetSelectedMints(); for (auto& meta : vMintsToFetch) { CZerocoinMint mint; if (!pwalletMain->GetMint(meta.hashSerial, mint)) { ui->TEMintStatus->setPlainText(tr("Failed to fetch mint associated with serial hash")); ui->TEMintStatus->repaint(); return; } vMintsSelected.emplace_back(mint); } } // Spend zAGR CWalletTx wtxNew; CZerocoinSpendReceipt receipt; bool fSuccess = false; if(ui->payTo->text().isEmpty()){ // Spend to newly generated local address fSuccess = pwalletMain->SpendZerocoin(nAmount, wtxNew, receipt, vMintsSelected, fMintChange, fMinimizeChange); } else { // Spend to supplied destination address fSuccess = pwalletMain->SpendZerocoin(nAmount, wtxNew, receipt, vMintsSelected, fMintChange, fMinimizeChange, &address); } // Display errors during spend if (!fSuccess) { /* int nNeededSpends = receipt.GetNeededSpends(); // Number of spends we would need for this transaction const int nMaxSpends = Params().Zerocoin_MaxSpendsPerTransaction(); // Maximum possible spends for one zAGR transaction if (nNeededSpends > nMaxSpends) { QString strStatusMessage = tr("Too much inputs (") + QString::number(nNeededSpends, 10) + tr(") needed.\nMaximum allowed: ") + QString::number(nMaxSpends, 10); strStatusMessage += tr("\nEither mint higher denominations (so fewer inputs are needed) or reduce the amount to spend."); QMessageBox::warning(this, tr("Spend Zerocoin"), strStatusMessage.toStdString().c_str(), QMessageBox::Ok, QMessageBox::Ok); ui->TEMintStatus->setPlainText(tr("Spend Zerocoin failed with status = ") +QString::number(receipt.GetStatus(), 10) + "\n" + "Message: " + QString::fromStdString(strStatusMessage.toStdString())); } else { */ QMessageBox::warning(this, tr("Spend Zerocoin"), receipt.GetStatusMessage().c_str(), QMessageBox::Ok, QMessageBox::Ok); ui->TEMintStatus->setPlainText(tr("Spend Zerocoin failed with status = ") +QString::number(receipt.GetStatus(), 10) + "\n" + "Message: " + QString::fromStdString(receipt.GetStatusMessage())); //} ui->zAGRpayAmount->setFocus(); ui->TEMintStatus->repaint(); ui->TEMintStatus->verticalScrollBar()->setValue(ui->TEMintStatus->verticalScrollBar()->maximum()); // Automatically scroll to end of text return; } if (walletModel && walletModel->getAddressTableModel()) { // If zAGR was spent successfully update the addressbook with the label std::string labelText = ui->addAsLabel->text().toStdString(); if (!labelText.empty()) walletModel->updateAddressBookLabels(address.Get(), labelText, "send"); else walletModel->updateAddressBookLabels(address.Get(), "(no label)", "send"); } // Clear zagr selector in case it was used ZPivControlDialog::setSelectedMints.clear(); ui->labelzPivSelected_int->setText(QString("0")); ui->labelQuantitySelected_int->setText(QString("0")); // Some statistics for entertainment QString strStats = ""; CAmount nValueIn = 0; int nCount = 0; for (CZerocoinSpend spend : receipt.GetSpends()) { strStats += tr("zAGR Spend #: ") + QString::number(nCount) + ", "; strStats += tr("denomination: ") + QString::number(spend.GetDenomination()) + ", "; strStats += tr("serial: ") + spend.GetSerial().ToString().c_str() + "\n"; strStats += tr("Spend is 1 of : ") + QString::number(spend.GetMintCount()) + " mints in the accumulator\n"; nValueIn += libzerocoin::ZerocoinDenominationToAmount(spend.GetDenomination()); ++nCount; } CAmount nValueOut = 0; for (const CTxOut& txout: wtxNew.vout) { strStats += tr("value out: ") + FormatMoney(txout.nValue).c_str() + " Piv, "; nValueOut += txout.nValue; strStats += tr("address: "); CTxDestination dest; if(txout.IsZerocoinMint()) strStats += tr("zAGR Mint"); else if(ExtractDestination(txout.scriptPubKey, dest)) strStats += tr(CBitcoinAddress(dest).ToString().c_str()); strStats += "\n"; } double fDuration = (double)(GetTimeMillis() - nTime)/1000.0; strStats += tr("Duration: ") + QString::number(fDuration) + tr(" sec.\n"); strStats += tr("Sending successful, return code: ") + QString::number(receipt.GetStatus()) + "\n"; QString strReturn; strReturn += tr("txid: ") + wtxNew.GetHash().ToString().c_str() + "\n"; strReturn += tr("fee: ") + QString::fromStdString(FormatMoney(nValueIn-nValueOut)) + "\n"; strReturn += strStats; // Clear amount to avoid double spending when accidentally clicking twice ui->zAGRpayAmount->setText ("0"); ui->TEMintStatus->setPlainText(strReturn); ui->TEMintStatus->repaint(); ui->TEMintStatus->verticalScrollBar()->setValue(ui->TEMintStatus->verticalScrollBar()->maximum()); // Automatically scroll to end of text } void PrivacyDialog::on_payTo_textChanged(const QString& address) { updateLabel(address); } /* DISABLE MINTs: no need for coinCointrol // Coin Control: copy label "Quantity" to clipboard void PrivacyDialog::coinControlClipboardQuantity() { GUIUtil::setClipboard(ui->labelCoinControlQuantity->text()); } // Coin Control: copy label "Amount" to clipboard void PrivacyDialog::coinControlClipboardAmount() { GUIUtil::setClipboard(ui->labelCoinControlAmount->text().left(ui->labelCoinControlAmount->text().indexOf(" "))); } // Coin Control: button inputs -> show actual coin control dialog void PrivacyDialog::coinControlButtonClicked() { if (!walletModel || !walletModel->getOptionsModel()) return; CoinControlDialog dlg; dlg.setModel(walletModel); dlg.exec(); coinControlUpdateLabels(); } // Coin Control: update labels void PrivacyDialog::coinControlUpdateLabels() { if (!walletModel || !walletModel->getOptionsModel() || !walletModel->getOptionsModel()->getCoinControlFeatures()) return; // set pay amounts CoinControlDialog::payAmounts.clear(); if (CoinControlDialog::coinControl->HasSelected()) { // Actual coin control calculation CoinControlDialog::updateLabels(walletModel, this); } else { ui->labelCoinControlQuantity->setText (tr("Coins automatically selected")); ui->labelCoinControlAmount->setText (tr("Coins automatically selected")); } } */ void PrivacyDialog::on_pushButtonShowDenoms_clicked() { minimizeDenomsSection(false); } void PrivacyDialog::on_pushButtonHideDenoms_clicked() { minimizeDenomsSection(true); } void PrivacyDialog::minimizeDenomsSection(bool fMinimize) { if (fMinimize) { ui->balanceSupplyFrame->show(); ui->verticalFrameRight->hide(); } else { ui->balanceSupplyFrame->hide(); ui->verticalFrameRight->show(); } fDenomsMinimized = fMinimize; } bool PrivacyDialog::updateLabel(const QString& address) { if (!walletModel) return false; // Fill in label from address book, if address has an associated label QString associatedLabel = walletModel->getAddressTableModel()->labelForAddress(address); if (!associatedLabel.isEmpty()) { ui->addAsLabel->setText(associatedLabel); return true; } return false; } void PrivacyDialog::setBalance(const CAmount& balance, const CAmount& unconfirmedBalance, const CAmount& immatureBalance, const CAmount& zerocoinBalance, const CAmount& unconfirmedZerocoinBalance, const CAmount& immatureZerocoinBalance, const CAmount& watchOnlyBalance, const CAmount& watchUnconfBalance, const CAmount& watchImmatureBalance) { currentBalance = balance; currentUnconfirmedBalance = unconfirmedBalance; currentImmatureBalance = immatureBalance; currentZerocoinBalance = zerocoinBalance; currentUnconfirmedZerocoinBalance = unconfirmedZerocoinBalance; currentImmatureZerocoinBalance = immatureZerocoinBalance; currentWatchOnlyBalance = watchOnlyBalance; currentWatchUnconfBalance = watchUnconfBalance; currentWatchImmatureBalance = watchImmatureBalance; std::map mapDenomBalances; std::map mapUnconfirmed; std::map mapImmature; for (const auto& denom : libzerocoin::zerocoinDenomList){ mapDenomBalances.insert(make_pair(denom, 0)); mapUnconfirmed.insert(make_pair(denom, 0)); mapImmature.insert(make_pair(denom, 0)); } std::vector vMints = pwalletMain->zagrTracker->GetMints(false); map mapMaturityHeights = GetMintMaturityHeight(); for (auto& meta : vMints){ // All denominations mapDenomBalances.at(meta.denom)++; if (!meta.nHeight || chainActive.Height() - meta.nHeight <= Params().Zerocoin_MintRequiredConfirmations()) { // All unconfirmed denominations mapUnconfirmed.at(meta.denom)++; } else { if (meta.denom == libzerocoin::CoinDenomination::ZQ_ERROR) { mapImmature.at(meta.denom)++; } else if (meta.nHeight >= mapMaturityHeights.at(meta.denom)) { mapImmature.at(meta.denom)++; } } } int64_t nCoins = 0; int64_t nSumPerCoin = 0; int64_t nUnconfirmed = 0; int64_t nImmature = 0; QString strDenomStats, strUnconfirmed = ""; for (const auto& denom : libzerocoin::zerocoinDenomList) { nCoins = libzerocoin::ZerocoinDenominationToInt(denom); nSumPerCoin = nCoins * mapDenomBalances.at(denom); nUnconfirmed = mapUnconfirmed.at(denom); nImmature = mapImmature.at(denom); strUnconfirmed = ""; if (nUnconfirmed) { strUnconfirmed += QString::number(nUnconfirmed) + QString(" unconf. "); } if(nImmature) { strUnconfirmed += QString::number(nImmature) + QString(" immature "); } if(nImmature || nUnconfirmed) { strUnconfirmed = QString("( ") + strUnconfirmed + QString(") "); } strDenomStats = strUnconfirmed + QString::number(mapDenomBalances.at(denom)) + " x " + QString::number(nCoins) + " = " + QString::number(nSumPerCoin) + " zAGR "; switch (nCoins) { case libzerocoin::CoinDenomination::ZQ_ONE: ui->labelzDenom1Amount->setText(strDenomStats); break; case libzerocoin::CoinDenomination::ZQ_FIVE: ui->labelzDenom2Amount->setText(strDenomStats); break; case libzerocoin::CoinDenomination::ZQ_TEN: ui->labelzDenom3Amount->setText(strDenomStats); break; case libzerocoin::CoinDenomination::ZQ_FIFTY: ui->labelzDenom4Amount->setText(strDenomStats); break; case libzerocoin::CoinDenomination::ZQ_ONE_HUNDRED: ui->labelzDenom5Amount->setText(strDenomStats); break; case libzerocoin::CoinDenomination::ZQ_FIVE_HUNDRED: ui->labelzDenom6Amount->setText(strDenomStats); break; case libzerocoin::CoinDenomination::ZQ_ONE_THOUSAND: ui->labelzDenom7Amount->setText(strDenomStats); break; case libzerocoin::CoinDenomination::ZQ_FIVE_THOUSAND: ui->labelzDenom8Amount->setText(strDenomStats); break; default: // Error Case: don't update display break; } } CAmount matureZerocoinBalance = zerocoinBalance - unconfirmedZerocoinBalance - immatureZerocoinBalance; CAmount nLockedBalance = 0; if (walletModel) { nLockedBalance = walletModel->getLockedBalance(); } ui->labelzAvailableAmount->setText(QString::number(zerocoinBalance/COIN) + QString(" zAGR ")); ui->labelzAvailableAmount_2->setText(QString::number(matureZerocoinBalance/COIN) + QString(" zAGR ")); ui->labelzAvailableAmount_4->setText(QString::number(zerocoinBalance/COIN) + QString(" zAGR ")); // Display AutoMint status updateAutomintStatus(); // Update/enable labels and buttons depending on the current SPORK_16 status updateSPORK16Status(); // Display global supply ui->labelZsupplyAmount->setText(QString::number(chainActive.Tip()->GetZerocoinSupply()/COIN) + QString(" zAGR ")); ui->labelZsupplyAmount_2->setText(QString::number(chainActive.Tip()->GetZerocoinSupply()/COIN) + QString(" zAGR ")); for (auto denom : libzerocoin::zerocoinDenomList) { int64_t nSupply = chainActive.Tip()->mapZerocoinSupply.at(denom); QString strSupply = QString::number(nSupply) + " x " + QString::number(denom) + " = " + QString::number(nSupply*denom) + " zAGR "; switch (denom) { case libzerocoin::CoinDenomination::ZQ_ONE: ui->labelZsupplyAmount1->setText(strSupply); break; case libzerocoin::CoinDenomination::ZQ_FIVE: ui->labelZsupplyAmount5->setText(strSupply); break; case libzerocoin::CoinDenomination::ZQ_TEN: ui->labelZsupplyAmount10->setText(strSupply); break; case libzerocoin::CoinDenomination::ZQ_FIFTY: ui->labelZsupplyAmount50->setText(strSupply); break; case libzerocoin::CoinDenomination::ZQ_ONE_HUNDRED: ui->labelZsupplyAmount100->setText(strSupply); break; case libzerocoin::CoinDenomination::ZQ_FIVE_HUNDRED: ui->labelZsupplyAmount500->setText(strSupply); break; case libzerocoin::CoinDenomination::ZQ_ONE_THOUSAND: ui->labelZsupplyAmount1000->setText(strSupply); break; case libzerocoin::CoinDenomination::ZQ_FIVE_THOUSAND: ui->labelZsupplyAmount5000->setText(strSupply); break; default: // Error Case: don't update display break; } } } void PrivacyDialog::updateDisplayUnit() { if (walletModel && walletModel->getOptionsModel()) { nDisplayUnit = walletModel->getOptionsModel()->getDisplayUnit(); if (currentBalance != -1) setBalance(currentBalance, currentUnconfirmedBalance, currentImmatureBalance, currentZerocoinBalance, currentUnconfirmedZerocoinBalance, currentImmatureZerocoinBalance, currentWatchOnlyBalance, currentWatchUnconfBalance, currentWatchImmatureBalance); } } void PrivacyDialog::showOutOfSyncWarning(bool fShow) { ui->labelzAGRSyncStatus->setVisible(fShow); } void PrivacyDialog::keyPressEvent(QKeyEvent* event) { if (event->key() != Qt::Key_Escape) // press esc -> ignore { this->QDialog::keyPressEvent(event); } else { event->ignore(); } } void PrivacyDialog::updateAutomintStatus() { QString strAutomintStatus = tr("AutoMint Status:"); if (pwalletMain->isZeromintEnabled ()) { strAutomintStatus += tr(" enabled."); } else { strAutomintStatus += tr(" disabled."); } strAutomintStatus += tr(" Configured target percentage: ") + QString::number(pwalletMain->getZeromintPercentage()) + "%"; ui->label_AutoMintStatus->setText(strAutomintStatus); } void PrivacyDialog::updateSPORK16Status() { // Update/enable labels, buttons and tooltips depending on the current SPORK_16 status //bool fButtonsEnabled = ui->pushButtonMintzAGR->isEnabled(); bool fButtonsEnabled = false; bool fMaintenanceMode = GetAdjustedTime() > GetSporkValue(SPORK_16_ZEROCOIN_MAINTENANCE_MODE); if (fMaintenanceMode && fButtonsEnabled) { // Mint zAGR //ui->pushButtonMintzAGR->setEnabled(false); //ui->pushButtonMintzAGR->setToolTip(tr("zAGR is currently disabled due to maintenance.")); // Spend zAGR ui->pushButtonSpendzAGR->setEnabled(false); ui->pushButtonSpendzAGR->setToolTip(tr("zAGR is currently disabled due to maintenance.")); } else if (!fMaintenanceMode && !fButtonsEnabled) { // Mint zAGR //ui->pushButtonMintzAGR->setEnabled(true); //ui->pushButtonMintzAGR->setToolTip(tr("PrivacyDialog", "Enter an amount of AGR to convert to zAGR", 0)); // Spend zAGR ui->pushButtonSpendzAGR->setEnabled(true); ui->pushButtonSpendzAGR->setToolTip(tr("Spend Zerocoin. Without 'Pay To:' address creates payments to yourself.")); } }