Handle unspendable inputs correctly.
authorCryptoManiac <balthazar@yandex.ru>
Sat, 19 Jul 2014 14:35:29 +0000 (18:35 +0400)
committerCryptoManiac <balthazar@yandex.ru>
Sat, 19 Jul 2014 14:35:29 +0000 (18:35 +0400)
* Add unspendable coins amount to overview page and getinfo RPC output;
* Replace current balance with amount of spendable coins on send coins page.

14 files changed:
src/qt/forms/overviewpage.ui
src/qt/locale/bitcoin_en.ts
src/qt/locale/bitcoin_ru.ts
src/qt/overviewpage.cpp
src/qt/overviewpage.h
src/qt/sendcoinsdialog.cpp
src/qt/sendcoinsdialog.h
src/qt/transactiondesc.cpp
src/qt/transactionrecord.cpp
src/qt/walletmodel.cpp
src/qt/walletmodel.h
src/rpcwallet.cpp
src/wallet.cpp
src/wallet.h

index 4a59ade..a038818 100644 (file)
@@ -91,7 +91,7 @@
            </widget>
           </item>
           <item row="0" column="1">
-           <widget class="QLabel" name="labelBalance">
+           <widget class="QLabel" name="labelBalanceTotal">
             <property name="font">
              <font>
               <weight>75</weight>
            </widget>
           </item>
           <item row="1" column="0">
+           <widget class="QLabel" name="labelBalanceWatchOnlyText">
+            <property name="text">
+             <string>Unspendable:</string>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QLabel" name="labelBalanceWatchOnly">
+            <property name="font">
+             <font>
+              <weight>75</weight>
+              <bold>true</bold>
+             </font>
+            </property>
+            <property name="cursor">
+             <cursorShape>IBeamCursor</cursorShape>
+            </property>
+            <property name="toolTip">
+             <string>Your unspendable balance</string>
+            </property>
+            <property name="text">
+             <string notr="true">0 NVC</string>
+            </property>
+            <property name="textInteractionFlags">
+             <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0">
            <widget class="QLabel" name="label_6">
             <property name="text">
              <string>Stake:</string>
             </property>
            </widget>
           </item>
-          <item row="1" column="1">
+          <item row="2" column="1">
            <widget class="QLabel" name="labelStake">
             <property name="font">
              <font>
             </property>
            </widget>
           </item>
-          <item row="2" column="0">
+          <item row="3" column="0">
            <widget class="QLabel" name="label_3">
             <property name="text">
              <string>Unconfirmed:</string>
             </property>
            </widget>
           </item>
-          <item row="2" column="1">
+          <item row="3" column="1">
            <widget class="QLabel" name="labelUnconfirmed">
             <property name="font">
              <font>
             </property>
            </widget>
           </item>
-          <item row="3" column="0">
+          <item row="4" column="0">
            <widget class="QLabel" name="labelImmatureText">
             <property name="text">
              <string>Immature:</string>
             </property>
            </widget>
           </item>
-          <item row="3" column="1">
+          <item row="4" column="1">
            <widget class="QLabel" name="labelImmature">
             <property name="font">
              <font>
             </property>
            </widget>
           </item>
-          <item row="4" column="0">
+          <item row="5" column="0">
            <widget class="QLabel" name="label_2">
             <property name="text">
              <string>Number of transactions:</string>
             </property>
            </widget>
           </item>
-          <item row="4" column="1">
+          <item row="5" column="1">
            <widget class="QLabel" name="labelNumTransactions">
             <property name="toolTip">
              <string>Total number of transactions in wallet</string>
index ea0e60a..cf48a2f 100644 (file)
@@ -1458,6 +1458,11 @@ This label turns red, if the priority is smaller than &quot;medium&quot;.
         <translation>Unconfirmed:</translation>
     </message>
     <message>
+        <location line="-55"/>
+        <source>Unspendable:</source>
+        <translation>Unspendable:</translation>
+    </message>
+    <message>
         <location line="-107"/>
         <source>Wallet</source>
         <translation>Wallet</translation>
@@ -1483,6 +1488,11 @@ This label turns red, if the priority is smaller than &quot;medium&quot;.
         <translation>Your current balance</translation>
     </message>
     <message>
+        <location line="-147"/>
+        <source>Your unspendable balance</source>
+        <translation>Your unspendable balance</translation>
+    </message>
+    <message>
         <location line="+58"/>
         <source>Total of transactions that have yet to be confirmed, and do not yet count toward the current balance</source>
         <translation>Total of transactions that have yet to be confirmed, and do not yet count toward the current balance</translation>
index e7eee39..41d3856 100644 (file)
@@ -1491,6 +1491,11 @@ This label turns red, if the priority is smaller than &quot;medium&quot;.
         <translation>Незрелые:</translation>
     </message>
     <message>
+        <location line="+136"/>
+        <source>Unspendable:</source>
+        <translation>Недоступно:</translation>
+    </message>
+    <message>
         <location line="+13"/>
         <source>Mined balance that has not yet matured</source>
         <translation>Баланс добытых монет, который ещё не созрел</translation>
@@ -1506,6 +1511,11 @@ This label turns red, if the priority is smaller than &quot;medium&quot;.
         <translation>Ваш текущий баланс</translation>
     </message>
     <message>
+        <location line="-147"/>
+        <source>Your unspendable balance</source>
+        <translation>Недоступный баланс</translation>
+    </message>
+    <message>
         <location line="+58"/>
         <source>Total of transactions that have yet to be confirmed, and do not yet count toward the current balance</source>
         <translation>Общая сумма всех транзакций, которые до сих пор не подтверждены, и до сих пор не учитываются в текущем балансе</translation>
index f176151..d2cd9ce 100644 (file)
@@ -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();
index 59fbb1d..10fa79a 100644 (file)
@@ -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;
index d21a315..34ad759 100644 (file)
@@ -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));
     }
 }
 
index f32e7f3..6810ff4 100644 (file)
@@ -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();
index 6ca00f6..4598e6e 100644 (file)
@@ -40,7 +40,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
         strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>";
 
         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 += "<b>" + tr("Credit") + ":</b> ";
             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 += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin)) + "<br>";
                 BOOST_FOREACH(const CTxOut& txout, wtx.vout)
                     if (wallet->IsMine(txout))
-                        strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout)) + "<br>";
+                        strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout, false)) + "<br>";
             }
         }
 
@@ -229,7 +229,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
                     strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, -wallet->GetDebit(txin)) + "<br>";
             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
                 if(wallet->IsMine(txout))
-                    strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout)) + "<br>";
+                    strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, wallet->GetCredit(txout, false)) + "<br>";
 
             strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
             strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
index 8962d18..20c263e 100644 (file)
@@ -25,7 +25,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
 {
     QList<TransactionRecord> 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;
index cafe9fc..b14388a 100644 (file)
@@ -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);
     }
 }
 
index 4c8597c..84be464 100644 (file)
@@ -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);
index d64a4f8..5699c4f 100644 (file)
@@ -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);
index f53f344..fb12cb0 100644 (file)
@@ -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<uint256, CWalletTx>::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));
          }
 
     }
index 964067f..cb07d39 100644 (file)
@@ -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;
     }