Browse Source

Watchonly balances are shown separately in gui.

0.10
JaSK 11 years ago
parent
commit
ffd40da361
  1. 171
      src/qt/forms/overviewpage.ui
  2. 34
      src/qt/overviewpage.cpp
  3. 6
      src/qt/overviewpage.h
  4. 13
      src/qt/sendcoinsdialog.cpp
  5. 3
      src/qt/sendcoinsdialog.h
  6. 46
      src/qt/transactiondesc.cpp
  7. 17
      src/qt/transactionrecord.cpp
  8. 27
      src/qt/walletmodel.cpp
  9. 9
      src/qt/walletmodel.h
  10. 4
      src/rpcdump.cpp
  11. 2
      src/rpcmisc.cpp
  12. 2
      src/script.h
  13. 53
      src/wallet.cpp
  14. 71
      src/wallet.h

171
src/qt/forms/overviewpage.ui

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>573</width> <width>596</width>
<height>342</height> <height>342</height>
</rect> </rect>
</property> </property>
@ -45,6 +45,8 @@
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_4"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item> <item>
<widget class="QLabel" name="label_5"> <widget class="QLabel" name="label_5">
<property name="font"> <property name="font">
@ -74,11 +76,34 @@
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="labelWatchonly">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Watchonly:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer_2"> <spacer name="horizontalSpacer_2">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>40</width> <width>40</width>
@ -89,6 +114,8 @@
</item> </item>
</layout> </layout>
</item> </item>
</layout>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<item> <item>
@ -181,6 +208,9 @@
<bold>true</bold> <bold>true</bold>
</font> </font>
</property> </property>
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="toolTip"> <property name="toolTip">
<string>Mined balance that has not yet matured</string> <string>Mined balance that has not yet matured</string>
</property> </property>
@ -195,6 +225,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0" colspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="4" column="0"> <item row="4" column="0">
<widget class="QLabel" name="labelTotalText"> <widget class="QLabel" name="labelTotalText">
<property name="text"> <property name="text">
@ -227,13 +264,138 @@
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="horizontalSpacing">
<number>12</number>
</property>
<property name="verticalSpacing">
<number>12</number>
</property>
<item row="0" column="1">
<widget class="QLabel" name="labelWatchAvailable">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="toolTip">
<string>Your current balance in watchonly addresses</string>
</property>
<property name="text">
<string>0 BTC</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="labelWatchPending">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="toolTip">
<string>Unconfirmed transactions to watchonly addresses</string>
</property>
<property name="text">
<string>0 BTC</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="labelWatchImmature">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="toolTip">
<string>Mined balance in watchonly addresses that has not yet matured</string>
</property>
<property name="text">
<string>0 BTC</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2"> <item row="3" column="0" colspan="2">
<widget class="Line" name="line"> <widget class="Line" name="lineWatchBalance">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>140</width>
<height>0</height>
</size>
</property>
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1">
<widget class="QLabel" name="labelWatchTotal">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="toolTip">
<string>Current total balance in watchonly addresses</string>
</property>
<property name="text">
<string>0 BTC</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@ -241,9 +403,12 @@
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>40</width> <width>20</width>
<height>20</height> <height>20</height>
</size> </size>
</property> </property>

34
src/qt/overviewpage.cpp

@ -103,6 +103,9 @@ OverviewPage::OverviewPage(QWidget *parent) :
currentBalance(-1), currentBalance(-1),
currentUnconfirmedBalance(-1), currentUnconfirmedBalance(-1),
currentImmatureBalance(-1), currentImmatureBalance(-1),
currentWatchOnlyBalance(-1),
currentWatchUnconfBalance(-1),
currentWatchImmatureBalance(-1),
txdelegate(new TxViewDelegate()), txdelegate(new TxViewDelegate()),
filter(0) filter(0)
{ {
@ -135,22 +138,39 @@ OverviewPage::~OverviewPage()
delete ui; delete ui;
} }
void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance) void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance)
{ {
int unit = walletModel->getOptionsModel()->getDisplayUnit(); int unit = walletModel->getOptionsModel()->getDisplayUnit();
currentBalance = balance; currentBalance = balance;
currentUnconfirmedBalance = unconfirmedBalance; currentUnconfirmedBalance = unconfirmedBalance;
currentImmatureBalance = immatureBalance; currentImmatureBalance = immatureBalance;
currentWatchOnlyBalance = watchOnlyBalance;
currentWatchUnconfBalance = watchUnconfBalance;
currentWatchImmatureBalance = watchImmatureBalance;
ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance)); ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance));
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, unconfirmedBalance)); ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, unconfirmedBalance));
ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, immatureBalance)); ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, immatureBalance));
ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balance + unconfirmedBalance + immatureBalance)); ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balance + unconfirmedBalance + immatureBalance));
ui->labelWatchAvailable->setText(BitcoinUnits::formatWithUnit(unit, watchOnlyBalance));
ui->labelWatchPending->setText(BitcoinUnits::formatWithUnit(unit, watchUnconfBalance));
ui->labelWatchImmature->setText(BitcoinUnits::formatWithUnit(unit, watchImmatureBalance));
ui->labelWatchTotal->setText(BitcoinUnits::formatWithUnit(unit, watchOnlyBalance + watchUnconfBalance + watchImmatureBalance));
// only show immature (newly mined) balance if it's non-zero, so as not to complicate things // only show immature (newly mined) balance if it's non-zero, so as not to complicate things
// for the non-mining users // for the non-mining users
bool showImmature = immatureBalance != 0; bool showImmature = immatureBalance != 0;
ui->labelImmature->setVisible(showImmature); bool showWatchOnlyImmature = watchImmatureBalance != 0;
ui->labelImmatureText->setVisible(showImmature); bool showWatchOnly = (watchOnlyBalance != 0 || watchUnconfBalance != 0 || showWatchOnlyImmature);
// for symmetry reasons also show immature label when the watchonly one is shown
ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature);
ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature);
ui->labelWatchonly->setVisible(showWatchOnly); // show Watchonly label
ui->lineWatchBalance->setVisible(showWatchOnly); // show watchonly balance separator line
ui->labelWatchAvailable->setVisible(showWatchOnly); // show watchonly available balance
ui->labelWatchImmature->setVisible(showWatchOnlyImmature); // show watchonly immature balance
ui->labelWatchPending->setVisible(showWatchOnly); // show watchonly pending balance
ui->labelWatchTotal->setVisible(showWatchOnly); // show watchonly total balance
} }
void OverviewPage::setClientModel(ClientModel *model) void OverviewPage::setClientModel(ClientModel *model)
@ -182,8 +202,9 @@ void OverviewPage::setWalletModel(WalletModel *model)
ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress); ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
// Keep up to date with wallet // Keep up to date with wallet
setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance()); setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(),
connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64))); model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance());
connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64, qint64, qint64)));
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
} }
@ -197,7 +218,8 @@ void OverviewPage::updateDisplayUnit()
if(walletModel && walletModel->getOptionsModel()) if(walletModel && walletModel->getOptionsModel())
{ {
if(currentBalance != -1) if(currentBalance != -1)
setBalance(currentBalance, currentUnconfirmedBalance, currentImmatureBalance); setBalance(currentBalance, currentUnconfirmedBalance, currentImmatureBalance,
currentWatchOnlyBalance, currentWatchUnconfBalance, currentWatchImmatureBalance);
// Update txdelegate->unit with the current unit // Update txdelegate->unit with the current unit
txdelegate->unit = walletModel->getOptionsModel()->getDisplayUnit(); txdelegate->unit = walletModel->getOptionsModel()->getDisplayUnit();

6
src/qt/overviewpage.h

@ -34,7 +34,8 @@ public:
void showOutOfSyncWarning(bool fShow); void showOutOfSyncWarning(bool fShow);
public slots: public slots:
void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance); void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance,
qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance);
signals: signals:
void transactionClicked(const QModelIndex &index); void transactionClicked(const QModelIndex &index);
@ -46,6 +47,9 @@ private:
qint64 currentBalance; qint64 currentBalance;
qint64 currentUnconfirmedBalance; qint64 currentUnconfirmedBalance;
qint64 currentImmatureBalance; qint64 currentImmatureBalance;
qint64 currentWatchOnlyBalance;
qint64 currentWatchUnconfBalance;
qint64 currentWatchImmatureBalance;
TxViewDelegate *txdelegate; TxViewDelegate *txdelegate;
TransactionFilterProxy *filter; TransactionFilterProxy *filter;

13
src/qt/sendcoinsdialog.cpp

@ -90,8 +90,9 @@ void SendCoinsDialog::setModel(WalletModel *model)
} }
} }
setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance()); setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(),
connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64))); model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance());
connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64, qint64, qint64)));
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
// Coin Control // Coin Control
@ -383,10 +384,14 @@ bool SendCoinsDialog::handlePaymentRequest(const SendCoinsRecipient &rv)
return true; return true;
} }
void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance) void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance,
qint64 watchBalance, qint64 watchUnconfirmedBalance, qint64 watchImmatureBalance)
{ {
Q_UNUSED(unconfirmedBalance); Q_UNUSED(unconfirmedBalance);
Q_UNUSED(immatureBalance); Q_UNUSED(immatureBalance);
Q_UNUSED(watchBalance);
Q_UNUSED(watchUnconfirmedBalance);
Q_UNUSED(watchImmatureBalance);
if(model && model->getOptionsModel()) if(model && model->getOptionsModel())
{ {
@ -396,7 +401,7 @@ void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance, qint
void SendCoinsDialog::updateDisplayUnit() void SendCoinsDialog::updateDisplayUnit()
{ {
setBalance(model->getBalance(), 0, 0); setBalance(model->getBalance(), 0, 0, 0, 0, 0);
} }
void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg) void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg)

3
src/qt/sendcoinsdialog.h

@ -47,7 +47,8 @@ public slots:
void accept(); void accept();
SendCoinsEntry *addEntry(); SendCoinsEntry *addEntry();
void updateTabsAndLabels(); void updateTabsAndLabels();
void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance); void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance,
qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance);
private: private:
Ui::SendCoinsDialog *ui; Ui::SendCoinsDialog *ui;

46
src/qt/transactiondesc.cpp

@ -89,6 +89,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
if (nNet > 0) if (nNet > 0)
{ {
// Credit // Credit
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{
if (wallet->IsMine(txout))
{
if (CBitcoinAddress(rec->address).IsValid()) if (CBitcoinAddress(rec->address).IsValid())
{ {
CTxDestination address = CBitcoinAddress(rec->address).Get(); CTxDestination address = CBitcoinAddress(rec->address).Get();
@ -97,13 +101,17 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>"; strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>";
strHTML += "<b>" + tr("To") + ":</b> "; strHTML += "<b>" + tr("To") + ":</b> ";
strHTML += GUIUtil::HtmlEscape(rec->address); strHTML += GUIUtil::HtmlEscape(rec->address);
std::string addressOwned = wallet->IsMine(txout) == MINE_SPENDABLE ? "own address" : "watch-only";
if (!wallet->mapAddressBook[address].name.empty()) if (!wallet->mapAddressBook[address].name.empty())
strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; strHTML += " (" + tr(addressOwned.c_str()) + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")";
else else
strHTML += " (" + tr("own address") + ")"; strHTML += " (" + tr(addressOwned.c_str()) + ")";
strHTML += "<br>"; strHTML += "<br>";
} }
} }
break;
}
}
} }
} }
@ -148,22 +156,33 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
} }
else else
{ {
bool fAllFromMe = true; isminetype fAllFromMe = MINE_SPENDABLE;
BOOST_FOREACH(const CTxIn& txin, wtx.vin) BOOST_FOREACH(const CTxIn& txin, wtx.vin)
fAllFromMe = fAllFromMe && wallet->IsMine(txin); {
isminetype mine = wallet->IsMine(txin);
if(fAllFromMe > mine) fAllFromMe = mine;
}
bool fAllToMe = true; isminetype fAllToMe = MINE_SPENDABLE;
BOOST_FOREACH(const CTxOut& txout, wtx.vout) BOOST_FOREACH(const CTxOut& txout, wtx.vout)
fAllToMe = fAllToMe && wallet->IsMine(txout); {
isminetype mine = wallet->IsMine(txout);
if(fAllToMe > mine) fAllToMe = mine;
}
if (fAllFromMe) if (fAllFromMe)
{ {
if(fAllFromMe == MINE_WATCH_ONLY)
strHTML += "<b>" + tr("From") + ":</b> " + tr("watch-only") + "<br>";
// //
// Debit // Debit
// //
BOOST_FOREACH(const CTxOut& txout, wtx.vout) BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{ {
if (wallet->IsMine(txout)) // Ignore change
isminetype toSelf = wallet->IsMine(txout);
if ((toSelf == MINE_SPENDABLE) && (fAllFromMe == MINE_SPENDABLE))
continue; continue;
if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty()) if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty())
@ -176,11 +195,17 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty()) if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty())
strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " "; strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " ";
strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString()); strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString());
if(toSelf == MINE_SPENDABLE)
strHTML += " (own address)";
else if(toSelf == MINE_WATCH_ONLY)
strHTML += " (watch-only)";
strHTML += "<br>"; strHTML += "<br>";
} }
} }
strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -txout.nValue) + "<br>"; strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -txout.nValue) + "<br>";
if(toSelf)
strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, txout.nValue) + "<br>";
} }
if (fAllToMe) if (fAllToMe)
@ -188,8 +213,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
// Payment to self // Payment to self
int64_t nChange = wtx.GetChange(); int64_t nChange = wtx.GetChange();
int64_t nValue = nCredit - nChange; int64_t nValue = nCredit - nChange;
strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -nValue) + "<br>"; strHTML += "<b>" + tr("Total debit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, -nValue) + "<br>";
strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, nValue) + "<br>"; strHTML += "<b>" + tr("Total credit") + ":</b> " + BitcoinUnits::formatWithUnit(unit, nValue) + "<br>";
} }
int64_t nTxFee = nDebit - wtx.GetValueOut(); int64_t nTxFee = nDebit - wtx.GetValueOut();
@ -286,7 +311,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
strHTML += QString::fromStdString(CBitcoinAddress(address).ToString()); strHTML += QString::fromStdString(CBitcoinAddress(address).ToString());
} }
strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(unit, vout.nValue); strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(unit, vout.nValue);
strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? tr("true") : tr("false")) + "</li>"; strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & MINE_SPENDABLE ? tr("true") : tr("false")) + "</li>";
strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(vout) & MINE_WATCH_ONLY ? tr("true") : tr("false")) + "</li>";
} }
} }
} }

17
src/qt/transactionrecord.cpp

@ -45,7 +45,8 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
// //
BOOST_FOREACH(const CTxOut& txout, wtx.vout) BOOST_FOREACH(const CTxOut& txout, wtx.vout)
{ {
if(wallet->IsMine(txout)) isminetype mine = wallet->IsMine(txout);
if(mine)
{ {
TransactionRecord sub(hash, nTime); TransactionRecord sub(hash, nTime);
CTxDestination address; CTxDestination address;
@ -75,13 +76,19 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
} }
else else
{ {
bool fAllFromMe = true; isminetype fAllFromMe = MINE_SPENDABLE;
BOOST_FOREACH(const CTxIn& txin, wtx.vin) BOOST_FOREACH(const CTxIn& txin, wtx.vin)
fAllFromMe = fAllFromMe && wallet->IsMine(txin); {
isminetype mine = wallet->IsMine(txin);
if(fAllFromMe > mine) fAllFromMe = mine;
}
bool fAllToMe = true; isminetype fAllToMe = MINE_SPENDABLE;
BOOST_FOREACH(const CTxOut& txout, wtx.vout) BOOST_FOREACH(const CTxOut& txout, wtx.vout)
fAllToMe = fAllToMe && wallet->IsMine(txout); {
isminetype mine = wallet->IsMine(txout);
if(fAllToMe > mine) fAllToMe = mine;
}
if (fAllFromMe && fAllToMe) if (fAllFromMe && fAllToMe)
{ {

27
src/qt/walletmodel.cpp

@ -79,6 +79,21 @@ qint64 WalletModel::getImmatureBalance() const
return wallet->GetImmatureBalance(); return wallet->GetImmatureBalance();
} }
qint64 WalletModel::getWatchBalance() const
{
return wallet->GetWatchOnlyBalance();
}
qint64 WalletModel::getWatchUnconfirmedBalance() const
{
return wallet->GetUnconfirmedWatchOnlyBalance();
}
qint64 WalletModel::getWatchImmatureBalance() const
{
return wallet->GetImmatureWatchOnlyBalance();
}
int WalletModel::getNumTransactions() const int WalletModel::getNumTransactions() const
{ {
int numTransactions = 0; int numTransactions = 0;
@ -127,13 +142,21 @@ void WalletModel::checkBalanceChanged()
qint64 newBalance = getBalance(); qint64 newBalance = getBalance();
qint64 newUnconfirmedBalance = getUnconfirmedBalance(); qint64 newUnconfirmedBalance = getUnconfirmedBalance();
qint64 newImmatureBalance = getImmatureBalance(); qint64 newImmatureBalance = getImmatureBalance();
qint64 newWatchOnlyBalance = getWatchBalance();
qint64 newWatchUnconfBalance = getWatchUnconfirmedBalance();
qint64 newWatchImmatureBalance = getWatchImmatureBalance();
if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance) if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance ||
cachedWatchOnlyBalance != newWatchOnlyBalance || cachedWatchUnconfBalance != newWatchUnconfBalance || cachedWatchImmatureBalance != newWatchImmatureBalance)
{ {
cachedBalance = newBalance; cachedBalance = newBalance;
cachedUnconfirmedBalance = newUnconfirmedBalance; cachedUnconfirmedBalance = newUnconfirmedBalance;
cachedImmatureBalance = newImmatureBalance; cachedImmatureBalance = newImmatureBalance;
emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance); cachedWatchOnlyBalance = newWatchOnlyBalance;
cachedWatchUnconfBalance = newWatchUnconfBalance;
cachedWatchImmatureBalance = newWatchImmatureBalance;
emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance,
newWatchOnlyBalance, newWatchUnconfBalance, newWatchImmatureBalance);
} }
} }

9
src/qt/walletmodel.h

@ -128,6 +128,9 @@ public:
qint64 getBalance(const CCoinControl *coinControl = NULL) const; qint64 getBalance(const CCoinControl *coinControl = NULL) const;
qint64 getUnconfirmedBalance() const; qint64 getUnconfirmedBalance() const;
qint64 getImmatureBalance() const; qint64 getImmatureBalance() const;
qint64 getWatchBalance() const;
qint64 getWatchUnconfirmedBalance() const;
qint64 getWatchImmatureBalance() const;
int getNumTransactions() const; int getNumTransactions() const;
EncryptionStatus getEncryptionStatus() const; EncryptionStatus getEncryptionStatus() const;
@ -206,6 +209,9 @@ private:
qint64 cachedBalance; qint64 cachedBalance;
qint64 cachedUnconfirmedBalance; qint64 cachedUnconfirmedBalance;
qint64 cachedImmatureBalance; qint64 cachedImmatureBalance;
qint64 cachedWatchOnlyBalance;
qint64 cachedWatchUnconfBalance;
qint64 cachedWatchImmatureBalance;
qint64 cachedNumTransactions; qint64 cachedNumTransactions;
EncryptionStatus cachedEncryptionStatus; EncryptionStatus cachedEncryptionStatus;
int cachedNumBlocks; int cachedNumBlocks;
@ -218,7 +224,8 @@ private:
signals: signals:
// Signal that balance in wallet changed // Signal that balance in wallet changed
void balanceChanged(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance); void balanceChanged(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance,
qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance);
// Number of transactions in wallet changed // Number of transactions in wallet changed
void numTransactionsChanged(int count); void numTransactionsChanged(int count);

4
src/rpcdump.cpp

@ -158,12 +158,14 @@ Value importaddress(const Array& params, bool fHelp)
{ {
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
// add to address book or update label
pwalletMain->SetAddressBook(dest, strLabel, "receive");
// Don't throw error in case an address is already there // Don't throw error in case an address is already there
if (pwalletMain->HaveWatchOnly(dest)) if (pwalletMain->HaveWatchOnly(dest))
return Value::null; return Value::null;
pwalletMain->MarkDirty(); pwalletMain->MarkDirty();
pwalletMain->SetAddressBook(dest, strLabel, "receive");
if (!pwalletMain->AddWatchOnly(dest)) if (!pwalletMain->AddWatchOnly(dest))
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");

2
src/rpcmisc.cpp

@ -171,7 +171,7 @@ Value validateaddress(const Array& params, bool fHelp)
ret.push_back(Pair("address", currentAddress)); ret.push_back(Pair("address", currentAddress));
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : MINE_NO; isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : MINE_NO;
ret.push_back(Pair("ismine", mine != MINE_NO)); ret.push_back(Pair("ismine", mine == MINE_SPENDABLE));
if (mine != MINE_NO) { if (mine != MINE_NO) {
ret.push_back(Pair("watchonly", mine == MINE_WATCH_ONLY)); ret.push_back(Pair("watchonly", mine == MINE_WATCH_ONLY));
Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest); Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest);

2
src/script.h

@ -201,6 +201,8 @@ enum isminetype
MINE_WATCH_ONLY = 1, MINE_WATCH_ONLY = 1,
MINE_SPENDABLE = 2, MINE_SPENDABLE = 2,
}; };
/** used for bitflags of isminetype */
typedef uint8_t isminefilter;
// Mandatory script verification flags that all new blocks must comply with for // Mandatory script verification flags that all new blocks must comply with for
// them to be valid. (but old blocks may not comply with) Currently just P2SH, // them to be valid. (but old blocks may not comply with) Currently just P2SH,

53
src/wallet.cpp

@ -738,7 +738,7 @@ bool CWallet::IsChange(const CTxOut& txout) const
// a better way of identifying which outputs are 'the send' and which are // a better way of identifying which outputs are 'the send' and which are
// 'the change' will need to be implemented (maybe extend CWalletTx to remember // 'the change' will need to be implemented (maybe extend CWalletTx to remember
// which output, if any, was change). // which output, if any, was change).
if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address)) if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address) == MINE_SPENDABLE)
{ {
LOCK(cs_wallet); LOCK(cs_wallet);
if (!mapAddressBook.count(address)) if (!mapAddressBook.count(address))
@ -793,7 +793,7 @@ int CWalletTx::GetRequestCount() const
} }
void CWalletTx::GetAmounts(list<pair<CTxDestination, int64_t> >& listReceived, void CWalletTx::GetAmounts(list<pair<CTxDestination, int64_t> >& listReceived,
list<pair<CTxDestination, int64_t> >& listSent, int64_t& nFee, string& strSentAccount) const list<pair<CTxDestination, int64_t> >& listSent, int64_t& nFee, string& strSentAccount, const isminefilter& filter) const
{ {
nFee = 0; nFee = 0;
listReceived.clear(); listReceived.clear();
@ -820,9 +820,9 @@ void CWalletTx::GetAmounts(list<pair<CTxDestination, int64_t> >& listReceived,
// Don't report 'change' txouts // Don't report 'change' txouts
if (pwallet->IsChange(txout)) if (pwallet->IsChange(txout))
continue; continue;
fIsMine = pwallet->IsMine(txout); fIsMine = (pwallet->IsMine(txout) & filter);
} }
else if (!(fIsMine = pwallet->IsMine(txout))) else if (!(fIsMine = (pwallet->IsMine(txout) & filter)))
continue; continue;
// In either case, we need to get the destination address // In either case, we need to get the destination address
@ -1066,6 +1066,51 @@ int64_t CWallet::GetImmatureBalance() const
return nTotal; return nTotal;
} }
int64_t CWallet::GetWatchOnlyBalance() const
{
int64_t nTotal = 0;
{
LOCK(cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
if (pcoin->IsTrusted())
nTotal += pcoin->GetAvailableWatchOnlyCredit();
}
}
return nTotal;
}
int64_t CWallet::GetUnconfirmedWatchOnlyBalance() const
{
int64_t nTotal = 0;
{
LOCK(cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
if (!IsFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
nTotal += pcoin->GetAvailableWatchOnlyCredit();
}
}
return nTotal;
}
int64_t CWallet::GetImmatureWatchOnlyBalance() const
{
int64_t nTotal = 0;
{
LOCK(cs_wallet);
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
nTotal += pcoin->GetImmatureWatchOnlyCredit();
}
}
return nTotal;
}
// populate vCoins with vector of available COutputs. // populate vCoins with vector of available COutputs.
void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const
{ {

71
src/wallet.h

@ -262,6 +262,9 @@ public:
int64_t GetBalance() const; int64_t GetBalance() const;
int64_t GetUnconfirmedBalance() const; int64_t GetUnconfirmedBalance() const;
int64_t GetImmatureBalance() const; int64_t GetImmatureBalance() const;
int64_t GetWatchOnlyBalance() const;
int64_t GetUnconfirmedWatchOnlyBalance() const;
int64_t GetImmatureWatchOnlyBalance() const;
bool CreateTransaction(const std::vector<std::pair<CScript, int64_t> >& vecSend, bool CreateTransaction(const std::vector<std::pair<CScript, int64_t> >& vecSend,
CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL);
bool CreateTransaction(CScript scriptPubKey, int64_t nValue, bool CreateTransaction(CScript scriptPubKey, int64_t nValue,
@ -290,11 +293,11 @@ public:
{ {
return ::IsMine(*this, txout.scriptPubKey); return ::IsMine(*this, txout.scriptPubKey);
} }
int64_t GetCredit(const CTxOut& txout) const int64_t GetCredit(const CTxOut& txout, const isminefilter& filter = (MINE_WATCH_ONLY | MINE_SPENDABLE)) const
{ {
if (!MoneyRange(txout.nValue)) if (!MoneyRange(txout.nValue))
throw std::runtime_error("CWallet::GetCredit() : value out of range"); throw std::runtime_error("CWallet::GetCredit() : value out of range");
return (IsMine(txout) ? txout.nValue : 0); return ((IsMine(txout) & filter) ? txout.nValue : 0);
} }
bool IsChange(const CTxOut& txout) const; bool IsChange(const CTxOut& txout) const;
int64_t GetChange(const CTxOut& txout) const int64_t GetChange(const CTxOut& txout) const
@ -332,12 +335,12 @@ public:
} }
return nDebit; return nDebit;
} }
int64_t GetCredit(const CTransaction& tx) const int64_t GetCredit(const CTransaction& tx, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const
{ {
int64_t nCredit = 0; int64_t nCredit = 0;
BOOST_FOREACH(const CTxOut& txout, tx.vout) BOOST_FOREACH(const CTxOut& txout, tx.vout)
{ {
nCredit += GetCredit(txout); nCredit += GetCredit(txout, filter);
if (!MoneyRange(nCredit)) if (!MoneyRange(nCredit))
throw std::runtime_error("CWallet::GetCredit() : value out of range"); throw std::runtime_error("CWallet::GetCredit() : value out of range");
} }
@ -483,11 +486,15 @@ public:
mutable bool fCreditCached; mutable bool fCreditCached;
mutable bool fImmatureCreditCached; mutable bool fImmatureCreditCached;
mutable bool fAvailableCreditCached; mutable bool fAvailableCreditCached;
mutable bool fImmatureWatchCreditCached;
mutable bool fAvailableWatchCreditCached;
mutable bool fChangeCached; mutable bool fChangeCached;
mutable int64_t nDebitCached; mutable int64_t nDebitCached;
mutable int64_t nCreditCached; mutable int64_t nCreditCached;
mutable int64_t nImmatureCreditCached; mutable int64_t nImmatureCreditCached;
mutable int64_t nAvailableCreditCached; mutable int64_t nAvailableCreditCached;
mutable int64_t nImmatureWatchCreditCached;
mutable int64_t nAvailableWatchCreditCached;
mutable int64_t nChangeCached; mutable int64_t nChangeCached;
CWalletTx() CWalletTx()
@ -524,11 +531,15 @@ public:
fCreditCached = false; fCreditCached = false;
fImmatureCreditCached = false; fImmatureCreditCached = false;
fAvailableCreditCached = false; fAvailableCreditCached = false;
fImmatureWatchCreditCached = false;
fAvailableWatchCreditCached = false;
fChangeCached = false; fChangeCached = false;
nDebitCached = 0; nDebitCached = 0;
nCreditCached = 0; nCreditCached = 0;
nImmatureCreditCached = 0; nImmatureCreditCached = 0;
nAvailableCreditCached = 0; nAvailableCreditCached = 0;
nAvailableWatchCreditCached = 0;
nImmatureWatchCreditCached = 0;
nChangeCached = 0; nChangeCached = 0;
nOrderPos = -1; nOrderPos = -1;
} }
@ -581,6 +592,8 @@ public:
{ {
fCreditCached = false; fCreditCached = false;
fAvailableCreditCached = false; fAvailableCreditCached = false;
fAvailableWatchCreditCached = false;
fImmatureWatchCreditCached = false;
fDebitCached = false; fDebitCached = false;
fChangeCached = false; fChangeCached = false;
} }
@ -622,7 +635,7 @@ public:
{ {
if (fUseCache && fImmatureCreditCached) if (fUseCache && fImmatureCreditCached)
return nImmatureCreditCached; return nImmatureCreditCached;
nImmatureCreditCached = pwallet->GetCredit(*this); nImmatureCreditCached = pwallet->GetCredit(*this, MINE_SPENDABLE);
fImmatureCreditCached = true; fImmatureCreditCached = true;
return nImmatureCreditCached; return nImmatureCreditCached;
} }
@ -649,7 +662,7 @@ public:
if (!pwallet->IsSpent(hashTx, i)) if (!pwallet->IsSpent(hashTx, i))
{ {
const CTxOut &txout = vout[i]; const CTxOut &txout = vout[i];
nCredit += pwallet->GetCredit(txout); nCredit += pwallet->GetCredit(txout, MINE_SPENDABLE);
if (!MoneyRange(nCredit)) if (!MoneyRange(nCredit))
throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range"); throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
} }
@ -660,6 +673,48 @@ public:
return nCredit; return nCredit;
} }
int64_t GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const
{
if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
{
if (fUseCache && fImmatureWatchCreditCached)
return nImmatureWatchCreditCached;
nImmatureWatchCreditCached = pwallet->GetCredit(*this, MINE_WATCH_ONLY);
fImmatureWatchCreditCached = true;
return nImmatureWatchCreditCached;
}
return 0;
}
int64_t GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const
{
if (pwallet == 0)
return 0;
// Must wait until coinbase is safely deep enough in the chain before valuing it
if (IsCoinBase() && GetBlocksToMaturity() > 0)
return 0;
if (fUseCache && fAvailableWatchCreditCached)
return nAvailableWatchCreditCached;
int64_t nCredit = 0;
for (unsigned int i = 0; i < vout.size(); i++)
{
if (!pwallet->IsSpent(GetHash(), i))
{
const CTxOut &txout = vout[i];
nCredit += pwallet->GetCredit(txout, MINE_WATCH_ONLY);
if (!MoneyRange(nCredit))
throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
}
}
nAvailableWatchCreditCached = nCredit;
fAvailableWatchCreditCached = true;
return nCredit;
}
int64_t GetChange() const int64_t GetChange() const
{ {
@ -671,7 +726,7 @@ public:
} }
void GetAmounts(std::list<std::pair<CTxDestination, int64_t> >& listReceived, void GetAmounts(std::list<std::pair<CTxDestination, int64_t> >& listReceived,
std::list<std::pair<CTxDestination, int64_t> >& listSent, int64_t& nFee, std::string& strSentAccount) const; std::list<std::pair<CTxDestination, int64_t> >& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const;
void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived, void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived,
int64_t& nSent, int64_t& nFee) const; int64_t& nSent, int64_t& nFee) const;
@ -702,7 +757,7 @@ public:
if (parent == NULL) if (parent == NULL)
return false; return false;
const CTxOut& parentOut = parent->vout[txin.prevout.n]; const CTxOut& parentOut = parent->vout[txin.prevout.n];
if (!pwallet->IsMine(parentOut)) if (pwallet->IsMine(parentOut) != MINE_SPENDABLE)
return false; return false;
} }
return true; return true;

Loading…
Cancel
Save