From b0368da0e15b5506548da3462e14b038ca21ae69 Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Sat, 19 Jul 2014 18:35:29 +0400 Subject: [PATCH] Handle unspendable inputs correctly. * Add unspendable coins amount to overview page and getinfo RPC output; * Replace current balance with amount of spendable coins on send coins page. --- src/qt/forms/overviewpage.ui | 45 ++++++++++++++++++++++----- src/qt/locale/bitcoin_en.ts | 10 ++++++ src/qt/locale/bitcoin_ru.ts | 10 ++++++ src/qt/overviewpage.cpp | 27 +++++++++++----- src/qt/overviewpage.h | 5 ++- src/qt/sendcoinsdialog.cpp | 14 +++++--- src/qt/sendcoinsdialog.h | 2 +- src/qt/transactiondesc.cpp | 8 ++-- src/qt/transactionrecord.cpp | 4 +- src/qt/walletmodel.cpp | 15 ++++++-- src/qt/walletmodel.h | 3 +- src/rpcwallet.cpp | 13 ++++++-- src/wallet.cpp | 29 +++++++++++++---- src/wallet.h | 71 ++++++++++++++++++++++++++++++++---------- 14 files changed, 194 insertions(+), 62 deletions(-) diff --git a/src/qt/forms/overviewpage.ui b/src/qt/forms/overviewpage.ui index 4a59ade..a038818 100644 --- a/src/qt/forms/overviewpage.ui +++ b/src/qt/forms/overviewpage.ui @@ -91,7 +91,7 @@ - + 75 @@ -113,13 +113,42 @@ + + + Unspendable: + + + + + + + + 75 + true + + + + IBeamCursor + + + Your unspendable balance + + + 0 NVC + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + Stake: - + @@ -141,14 +170,14 @@ - + Unconfirmed: - + @@ -170,14 +199,14 @@ - + Immature: - + @@ -196,14 +225,14 @@ - + Number of transactions: - + Total number of transactions in wallet diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts index ea0e60a..cf48a2f 100644 --- a/src/qt/locale/bitcoin_en.ts +++ b/src/qt/locale/bitcoin_en.ts @@ -1458,6 +1458,11 @@ This label turns red, if the priority is smaller than "medium". Unconfirmed: + + Unspendable: + Unspendable: + + Wallet Wallet @@ -1483,6 +1488,11 @@ This label turns red, if the priority is smaller than "medium". Your current balance + + Your unspendable balance + Your unspendable balance + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance Total of transactions that have yet to be confirmed, and do not yet count toward the current balance diff --git a/src/qt/locale/bitcoin_ru.ts b/src/qt/locale/bitcoin_ru.ts index e7eee39..41d3856 100644 --- a/src/qt/locale/bitcoin_ru.ts +++ b/src/qt/locale/bitcoin_ru.ts @@ -1491,6 +1491,11 @@ This label turns red, if the priority is smaller than "medium". Незрелые: + + Unspendable: + Недоступно: + + Mined balance that has not yet matured Баланс добытых монет, который ещё не созрел @@ -1506,6 +1511,11 @@ This label turns red, if the priority is smaller than "medium". Ваш текущий баланс + + Your unspendable balance + Недоступный баланс + + Total of transactions that have yet to be confirmed, and do not yet count toward the current balance Общая сумма всех транзакций, которые до сих пор не подтверждены, и до сих пор не учитываются в текущем балансе diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index f176151..d2cd9ce 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -92,7 +92,8 @@ public: OverviewPage::OverviewPage(QWidget *parent) : QWidget(parent), ui(new Ui::OverviewPage), - currentBalance(-1), + currentBalanceTotal(-1), + currentBalanceWatchOnly(0), currentStake(0), currentUnconfirmedBalance(-1), currentImmatureBalance(-1), @@ -128,14 +129,16 @@ OverviewPage::~OverviewPage() delete ui; } -void OverviewPage::setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance) +void OverviewPage::setBalance(qint64 total, qint64 watchOnly, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance) { int unit = model->getOptionsModel()->getDisplayUnit(); - currentBalance = balance; + currentBalanceTotal = total; + currentBalanceWatchOnly = watchOnly; currentStake = stake; currentUnconfirmedBalance = unconfirmedBalance; currentImmatureBalance = immatureBalance; - ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance)); + ui->labelBalanceTotal->setText(BitcoinUnits::formatWithUnit(unit, total)); + ui->labelBalanceWatchOnly->setText(BitcoinUnits::formatWithUnit(unit, watchOnly)); ui->labelStake->setText(BitcoinUnits::formatWithUnit(unit, stake)); ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, unconfirmedBalance)); ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, immatureBalance)); @@ -145,6 +148,12 @@ void OverviewPage::setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBa bool showImmature = immatureBalance != 0; ui->labelImmature->setVisible(showImmature); ui->labelImmatureText->setVisible(showImmature); + + // only show watch-only balance if it's non-zero, so as not to complicate things + // for users + bool showWatchOnly = watchOnly != 0; + ui->labelBalanceWatchOnly->setVisible(showWatchOnly); + ui->labelBalanceWatchOnlyText->setVisible(showWatchOnly); } void OverviewPage::setNumTransactions(int count) @@ -170,8 +179,10 @@ void OverviewPage::setModel(WalletModel *model) ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress); // Keep up to date with wallet - setBalance(model->getBalance(), model->getStake(), model->getUnconfirmedBalance(), model->getImmatureBalance()); - connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64))); + qint64 nTotal=0, nWatchOnly=0; + model->getBalance(nTotal, nWatchOnly); + setBalance(nTotal, nWatchOnly, model->getStake(), model->getUnconfirmedBalance(), model->getImmatureBalance()); + connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64, qint64))); setNumTransactions(model->getNumTransactions()); connect(model, SIGNAL(numTransactionsChanged(int)), this, SLOT(setNumTransactions(int))); @@ -187,8 +198,8 @@ void OverviewPage::updateDisplayUnit() { if(model && model->getOptionsModel()) { - if(currentBalance != -1) - setBalance(currentBalance, model->getStake(), currentUnconfirmedBalance, currentImmatureBalance); + if(currentBalanceTotal != -1) + setBalance(currentBalanceTotal, currentBalanceWatchOnly, model->getStake(), currentUnconfirmedBalance, currentImmatureBalance); // Update txdelegate->unit with the current unit txdelegate->unit = model->getOptionsModel()->getDisplayUnit(); diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index 59fbb1d..10fa79a 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -27,7 +27,7 @@ public: void showOutOfSyncWarning(bool fShow); public slots: - void setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance); + void setBalance(qint64 total, qint64 watchOnly, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance); void setNumTransactions(int count); signals: @@ -36,7 +36,8 @@ signals: private: Ui::OverviewPage *ui; WalletModel *model; - qint64 currentBalance; + qint64 currentBalanceTotal; + qint64 currentBalanceWatchOnly; qint64 currentStake; qint64 currentUnconfirmedBalance; qint64 currentImmatureBalance; diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index d21a315..34ad759 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -93,8 +93,10 @@ void SendCoinsDialog::setModel(WalletModel *model) } if(model && model->getOptionsModel()) { - setBalance(model->getBalance(), model->getStake(), model->getUnconfirmedBalance(), model->getImmatureBalance()); - connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64))); + qint64 nTotal=0, nWatchOnly=0; + model->getBalance(nTotal, nWatchOnly); + setBalance(nTotal, nWatchOnly, model->getStake(), model->getUnconfirmedBalance(), model->getImmatureBalance()); + connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64, qint64))); connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); // Coin Control @@ -358,7 +360,7 @@ bool SendCoinsDialog::handleURI(const QString &uri) return false; } -void SendCoinsDialog::setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance) +void SendCoinsDialog::setBalance(qint64 total, qint64 watchOnly, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance) { Q_UNUSED(stake); Q_UNUSED(unconfirmedBalance); @@ -367,7 +369,7 @@ void SendCoinsDialog::setBalance(qint64 balance, qint64 stake, qint64 unconfirme return; int unit = model->getOptionsModel()->getDisplayUnit(); - ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance)); + ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, total - watchOnly)); } void SendCoinsDialog::updateDisplayUnit() @@ -375,7 +377,9 @@ void SendCoinsDialog::updateDisplayUnit() if(model && model->getOptionsModel()) { // Update labelBalance with the current balance and the current unit - ui->labelBalance->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->getBalance())); + qint64 total=0, watchOnly=0; + model->getBalance(total, watchOnly); + ui->labelBalance->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), total - watchOnly)); } } diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index f32e7f3..6810ff4 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -39,7 +39,7 @@ public slots: void accept(); SendCoinsEntry *addEntry(); void updateRemoveEnabled(); - void setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance); + void setBalance(qint64 total, qint64 watchOnly, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance); void on_addressBookButton_clicked(); void on_pasteButton_clicked(); diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 6ca00f6..4598e6e 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -40,7 +40,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) strHTML += ""; int64 nTime = wtx.GetTxTime(); - int64 nCredit = wtx.GetCredit(); + int64 nCredit = wtx.GetCredit(false); int64 nDebit = wtx.GetDebit(); int64 nNet = nCredit - nDebit; @@ -124,7 +124,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) // int64 nUnmatured = 0; BOOST_FOREACH(const CTxOut& txout, wtx.vout) - nUnmatured += wallet->GetCredit(txout); + nUnmatured += wallet->GetCredit(txout, false); strHTML += "" + tr("Credit") + ": "; if (wtx.IsInMainChain()) strHTML += BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")"; @@ -199,7 +199,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if (wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout)) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout, false)) + "
"; } } @@ -229,7 +229,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if(wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout)) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout, false)) + "
"; strHTML += "
" + tr("Transaction") + ":
"; strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true); diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 8962d18..20c263e 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -25,7 +25,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * { QList parts; int64 nTime = wtx.GetTxTime(); - int64 nCredit = wtx.GetCredit(true); + int64 nCredit = wtx.GetCredit(false,true); int64 nDebit = wtx.GetDebit(); int64 nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(), hashPrev = 0; @@ -205,7 +205,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) // For generated transactions, determine maturity if(type == TransactionRecord::Generated) { - int64 nCredit = wtx.GetCredit(true); + int64 nCredit = wtx.GetCredit(false,true); if (nCredit == 0) { status.maturity = TransactionStatus::Immature; diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index cafe9fc..b14388a 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -41,6 +41,11 @@ qint64 WalletModel::getBalance() const return wallet->GetBalance(); } +void WalletModel::getBalance(qint64 &nTotal, qint64 &nWatchOnly) const +{ + wallet->GetBalance(nTotal, nWatchOnly); +} + qint64 WalletModel::getUnconfirmedBalance() const { return wallet->GetUnconfirmedBalance(); @@ -86,18 +91,20 @@ void WalletModel::pollBalanceChanged() void WalletModel::checkBalanceChanged() { - qint64 newBalance = getBalance(); + qint64 newBalanceTotal=0, newBalanceWatchOnly=0; + getBalance(newBalanceTotal, newBalanceWatchOnly); + qint64 newStake = getStake(); qint64 newUnconfirmedBalance = getUnconfirmedBalance(); qint64 newImmatureBalance = getImmatureBalance(); - if(cachedBalance != newBalance || cachedStake != newStake || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance) + if(cachedBalance != newBalanceTotal || cachedStake != newStake || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance) { - cachedBalance = newBalance; + cachedBalance = newBalanceTotal; cachedStake = newStake; cachedUnconfirmedBalance = newUnconfirmedBalance; cachedImmatureBalance = newImmatureBalance; - emit balanceChanged(newBalance, newStake, newUnconfirmedBalance, newImmatureBalance); + emit balanceChanged(newBalanceTotal, newBalanceWatchOnly, newStake, newUnconfirmedBalance, newImmatureBalance); } } diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 4c8597c..84be464 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -64,6 +64,7 @@ public: TransactionTableModel *getTransactionTableModel(); qint64 getBalance() const; + void getBalance(qint64 &nTotal, qint64 &nWatchOnly) const; qint64 getStake() const; qint64 getUnconfirmedBalance() const; qint64 getImmatureBalance() const; @@ -170,7 +171,7 @@ public slots: signals: // Signal that balance in wallet changed - void balanceChanged(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance); + void balanceChanged(qint64 total, qint64 watchOnly, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance); // Number of transactions in wallet changed void numTransactionsChanged(int count); diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index d64a4f8..5699c4f 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -69,11 +69,15 @@ Value getinfo(const Array& params, bool fHelp) proxyType proxy; GetProxy(NET_IPV4, proxy); + int64 nTotal = 0, nWatchOnly = 0; + pwalletMain->GetBalance(nTotal, nWatchOnly); + Object obj, diff; obj.push_back(Pair("version", FormatFullVersion())); obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); - obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); + obj.push_back(Pair("balance", ValueFromAmount(nTotal))); + obj.push_back(Pair("unspendable", ValueFromAmount(nWatchOnly))); obj.push_back(Pair("newmint", ValueFromAmount(pwalletMain->GetNewMint()))); obj.push_back(Pair("stake", ValueFromAmount(pwalletMain->GetStake()))); obj.push_back(Pair("blocks", (int)nBestHeight)); @@ -722,7 +726,10 @@ Value sendmany(const Array& params, bool fHelp) bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired); if (!fCreated) { - if (totalAmount + nFeeRequired > pwalletMain->GetBalance()) + int64 nTotal = 0, nWatchOnly = 0; + pwalletMain->GetBalance(nTotal, nWatchOnly); + + if (totalAmount + nFeeRequired > nTotal - nWatchOnly) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds"); throw JSONRPCError(RPC_WALLET_ERROR, "Transaction creation failed"); } @@ -1258,7 +1265,7 @@ Value gettransaction(const Array& params, bool fHelp) TxToJSON(wtx, 0, entry); - int64 nCredit = wtx.GetCredit(); + int64 nCredit = wtx.GetCredit(false); int64 nDebit = wtx.GetDebit(); int64 nNet = nCredit - nDebit; int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0); diff --git a/src/wallet.cpp b/src/wallet.cpp index f53f344..fb12cb0 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -386,7 +386,7 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx, bool fBlock) printf("WalletUpdateSpent: bad wtx %s\n", wtx.GetHash().ToString().c_str()); else if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n])) { - printf("WalletUpdateSpent found spent coin %snvc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str()); + printf("WalletUpdateSpent found spent coin %snvc %s\n", FormatMoney(wtx.GetCredit(false)).c_str(), wtx.GetHash().ToString().c_str()); wtx.MarkSpent(txin.prevout.n); wtx.WriteToDisk(); NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED); @@ -697,7 +697,7 @@ void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, l if (GetBlocksToMaturity() > 0) nGeneratedImmature = pwallet->GetCredit(*this); else - nGeneratedMature = GetCredit(); + nGeneratedMature = GetCredit(false); return; } @@ -921,7 +921,7 @@ void CWallet::ReacceptWalletTransactions() } if (fUpdated) { - printf("ReacceptWalletTransactions found spent coin %snvc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str()); + printf("ReacceptWalletTransactions found spent coin %snvc %s\n", FormatMoney(wtx.GetCredit(false)).c_str(), wtx.GetHash().ToString().c_str()); wtx.MarkDirty(); wtx.WriteToDisk(); } @@ -1034,13 +1034,28 @@ int64 CWallet::GetBalance() const { const CWalletTx* pcoin = &(*it).second; if (pcoin->IsTrusted()) - nTotal += pcoin->GetAvailableCredit(); + nTotal += pcoin->GetAvailableCredit(false); } } return nTotal; } +void CWallet::GetBalance(int64 &nTotal, int64 &nWatchOnly) const +{ + { + LOCK(cs_wallet); + for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx* pcoin = &(*it).second; + if (pcoin->IsTrusted()) { + nWatchOnly += pcoin->GetAvailableCredit(true); + nTotal += pcoin->GetAvailableCredit(false); + } + } + } +} + int64 CWallet::GetUnconfirmedBalance() const { int64 nTotal = 0; @@ -1050,7 +1065,7 @@ int64 CWallet::GetUnconfirmedBalance() const { const CWalletTx* pcoin = &(*it).second; if (!pcoin->IsFinal() || !pcoin->IsTrusted()) - nTotal += pcoin->GetAvailableCredit(); + nTotal += pcoin->GetAvailableCredit(false); } } return nTotal; @@ -2036,12 +2051,12 @@ void CWallet::PrintWallet(const CBlock& block) if (block.IsProofOfWork() && mapWallet.count(block.vtx[0].GetHash())) { CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()]; - printf(" mine: %d %d %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit()); + printf(" mine: %d %d %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit(false)); } if (block.IsProofOfStake() && mapWallet.count(block.vtx[1].GetHash())) { CWalletTx& wtx = mapWallet[block.vtx[1].GetHash()]; - printf(" stake: %d %d %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit()); + printf(" stake: %d %d %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit(false)); } } diff --git a/src/wallet.h b/src/wallet.h index 964067f..cb07d39 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -185,6 +185,7 @@ public: void ReacceptWalletTransactions(); void ResendWalletTransactions(); int64 GetBalance() const; + void GetBalance(int64 &nTotal, int64 &nWatchOnly) const; int64 GetUnconfirmedBalance() const; int64 GetImmatureBalance() const; int64 GetStake() const; @@ -219,11 +220,14 @@ public: { return ::IsMine(*this, txout.scriptPubKey); } - int64 GetCredit(const CTxOut& txout) const + int64 GetCredit(const CTxOut& txout, bool fWatchOnly=false) const { if (!MoneyRange(txout.nValue)) throw std::runtime_error("CWallet::GetCredit() : value out of range"); - return (IsMine(txout) ? txout.nValue : 0); + isminetype ismine = IsMine(txout); + if (fWatchOnly && ismine != MINE_WATCH_ONLY) + return 0; + return (ismine != MINE_NO ? txout.nValue : 0); } bool IsChange(const CTxOut& txout) const; int64 GetChange(const CTxOut& txout) const @@ -254,12 +258,14 @@ public: } return nDebit; } - int64 GetCredit(const CTransaction& tx) const + int64 GetCredit(const CTransaction& tx, bool fWatchOnly=true) const { int64 nCredit = 0; BOOST_FOREACH(const CTxOut& txout, tx.vout) { - nCredit += GetCredit(txout); + if (!fWatchOnly || (fWatchOnly && IsMine(txout) == MINE_WATCH_ONLY)) + nCredit += GetCredit(txout); + if (!MoneyRange(nCredit)) throw std::runtime_error("CWallet::GetCredit() : value out of range"); } @@ -401,11 +407,15 @@ public: // memory only mutable bool fDebitCached; mutable bool fCreditCached; + mutable bool fWatchOnlyCreditCached; mutable bool fAvailableCreditCached; + mutable bool fAvailableWatchOnlyCreditCached; mutable bool fChangeCached; mutable int64 nDebitCached; mutable int64 nCreditCached; + mutable int64 nWatchOnlyCreditCached; mutable int64 nAvailableCreditCached; + mutable int64 nAvailableWatchOnlyCreditCached; mutable int64 nChangeCached; CWalletTx() @@ -442,11 +452,15 @@ public: vfSpent.clear(); fDebitCached = false; fCreditCached = false; + fWatchOnlyCreditCached = false; fAvailableCreditCached = false; + fAvailableWatchOnlyCreditCached = false; fChangeCached = false; nDebitCached = 0; nCreditCached = 0; + nWatchOnlyCreditCached = 0; nAvailableCreditCached = 0; + nAvailableWatchOnlyCreditCached = 0; nChangeCached = 0; nOrderPos = -1; } @@ -522,7 +536,7 @@ public: { vfSpent[i] = true; fReturn = true; - fAvailableCreditCached = false; + fAvailableCreditCached = fAvailableWatchOnlyCreditCached = false; } } return fReturn; @@ -532,7 +546,7 @@ public: void MarkDirty() { fCreditCached = false; - fAvailableCreditCached = false; + fAvailableCreditCached = fAvailableWatchOnlyCreditCached = false; fDebitCached = false; fChangeCached = false; } @@ -551,7 +565,7 @@ public: if (!vfSpent[nOut]) { vfSpent[nOut] = true; - fAvailableCreditCached = false; + fAvailableCreditCached = fAvailableWatchOnlyCreditCached = false; } } @@ -563,7 +577,7 @@ public: if (vfSpent[nOut]) { vfSpent[nOut] = false; - fAvailableCreditCached = false; + fAvailableCreditCached = fAvailableWatchOnlyCreditCached = false; } } @@ -587,28 +601,46 @@ public: return nDebitCached; } - int64 GetCredit(bool fUseCache=true) const + int64 GetCredit(bool fWatchOnly, bool fUseCache=true) const { // Must wait until coinbase is safely deep enough in the chain before valuing it if ((IsCoinBase() || IsCoinStake()) && GetBlocksToMaturity() > 0) return 0; // GetBalance can assume transactions in mapWallet won't change - if (fUseCache && fCreditCached) - return nCreditCached; + if (fUseCache) { + if (fWatchOnly && fCreditCached) + return nWatchOnlyCreditCached; + if (fCreditCached) + return nCreditCached; + } + + if (fWatchOnly) { + nWatchOnlyCreditCached = pwallet->GetCredit(*this, true); + fWatchOnlyCreditCached = true; + + return nWatchOnlyCreditCached; + } + nCreditCached = pwallet->GetCredit(*this); fCreditCached = true; + return nCreditCached; } - int64 GetAvailableCredit(bool fUseCache=true) const + int64 GetAvailableCredit(bool fWatchOnly, bool fUseCache=true) const { // Must wait until coinbase is safely deep enough in the chain before valuing it if ((IsCoinBase() || IsCoinStake()) && GetBlocksToMaturity() > 0) return 0; - if (fUseCache && fAvailableCreditCached) - return nAvailableCreditCached; + if (fUseCache) { + if (fWatchOnly && fAvailableWatchOnlyCreditCached) + return nAvailableWatchOnlyCreditCached; + + if (fAvailableCreditCached) + return nAvailableCreditCached; + } int64 nCredit = 0; for (unsigned int i = 0; i < vout.size(); i++) @@ -616,14 +648,19 @@ public: if (!IsSpent(i)) { const CTxOut &txout = vout[i]; - nCredit += pwallet->GetCredit(txout); + nCredit += pwallet->GetCredit(txout, fWatchOnly); if (!MoneyRange(nCredit)) throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range"); } } - nAvailableCreditCached = nCredit; - fAvailableCreditCached = true; + if (fWatchOnly) { + nAvailableWatchOnlyCreditCached = nCredit; + fAvailableWatchOnlyCreditCached = true; + } else { + nAvailableCreditCached = nCredit; + fAvailableCreditCached = true; + } return nCredit; } -- 1.7.1