aboutsummaryrefslogtreecommitdiff
path: root/src/qt/walletmodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qt/walletmodel.cpp')
-rw-r--r--src/qt/walletmodel.cpp159
1 files changed, 128 insertions, 31 deletions
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index bda39b675..2470af41a 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -1,16 +1,27 @@
+// Copyright (c) 2011-2013 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
#include "walletmodel.h"
-#include "guiconstants.h"
-#include "optionsmodel.h"
+
#include "addresstablemodel.h"
+#include "guiconstants.h"
#include "transactiontablemodel.h"
+#include "base58.h"
+#include "db.h"
+#include "keystore.h"
+#include "main.h"
+#include "sync.h"
#include "ui_interface.h"
+#include "wallet.h"
#include "walletdb.h" // for BackupWallet
-#include "base58.h"
+#include <stdint.h>
+
+#include <QDebug>
#include <QSet>
#include <QTimer>
-#include <QDebug>
WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) :
QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0),
@@ -36,8 +47,19 @@ WalletModel::~WalletModel()
unsubscribeFromCoreSignals();
}
-qint64 WalletModel::getBalance() const
+qint64 WalletModel::getBalance(const CCoinControl *coinControl) const
{
+ if (coinControl)
+ {
+ qint64 nBalance = 0;
+ std::vector<COutput> vCoins;
+ wallet->AvailableCoins(vCoins, true, coinControl);
+ BOOST_FOREACH(const COutput& out, vCoins)
+ nBalance += out.tx->vout[out.i].nValue;
+
+ return nBalance;
+ }
+
return wallet->GetBalance();
}
@@ -73,10 +95,10 @@ void WalletModel::updateStatus()
void WalletModel::pollBalanceChanged()
{
- if(nBestHeight != cachedNumBlocks)
+ if(chainActive.Height() != cachedNumBlocks)
{
// Balance and number of transactions might have changed
- cachedNumBlocks = nBestHeight;
+ cachedNumBlocks = chainActive.Height();
checkBalanceChanged();
}
}
@@ -125,11 +147,11 @@ bool WalletModel::validateAddress(const QString &address)
return addressParsed.IsValid();
}
-WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction)
+WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl)
{
qint64 total = 0;
QList<SendCoinsRecipient> recipients = transaction.getRecipients();
- std::vector<std::pair<CScript, int64> > vecSend;
+ std::vector<std::pair<CScript, int64_t> > vecSend;
if(recipients.empty())
{
@@ -144,7 +166,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
{
if (rcp.paymentRequest.IsInitialized())
{ // PaymentRequest...
- int64 subtotal = 0;
+ int64_t subtotal = 0;
const payments::PaymentDetails& details = rcp.paymentRequest.getDetails();
for (int i = 0; i < details.outputs_size(); i++)
{
@@ -153,7 +175,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
subtotal += out.amount();
const unsigned char* scriptStr = (const unsigned char*)out.script().data();
CScript scriptPubKey(scriptStr, scriptStr+out.script().size());
- vecSend.push_back(std::pair<CScript, int64>(scriptPubKey, out.amount()));
+ vecSend.push_back(std::pair<CScript, int64_t>(scriptPubKey, out.amount()));
}
if (subtotal <= 0)
{
@@ -176,7 +198,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
CScript scriptPubKey;
scriptPubKey.SetDestination(CBitcoinAddress(rcp.address.toStdString()).Get());
- vecSend.push_back(std::pair<CScript, int64>(scriptPubKey, rcp.amount));
+ vecSend.push_back(std::pair<CScript, int64_t>(scriptPubKey, rcp.amount));
total += rcp.amount;
}
@@ -186,12 +208,14 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
return DuplicateAddress;
}
- if(total > getBalance())
+ qint64 nBalance = getBalance(coinControl);
+
+ if(total > nBalance)
{
return AmountExceedsBalance;
}
- if((total + nTransactionFee) > getBalance())
+ if((total + nTransactionFee) > nBalance)
{
transaction.setTransactionFee(nTransactionFee);
return SendCoinsReturn(AmountWithFeeExceedsBalance);
@@ -201,17 +225,17 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
LOCK2(cs_main, wallet->cs_wallet);
transaction.newPossibleKeyChange(wallet);
- int64 nFeeRequired = 0;
+ int64_t nFeeRequired = 0;
std::string strFailReason;
CWalletTx *newTx = transaction.getTransaction();
CReserveKey *keyChange = transaction.getPossibleKeyChange();
- bool fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, strFailReason);
+ bool fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, strFailReason, coinControl);
transaction.setTransactionFee(nFeeRequired);
if(!fCreated)
{
- if((total + nFeeRequired) > wallet->GetBalance())
+ if((total + nFeeRequired) > nBalance)
{
return SendCoinsReturn(AmountWithFeeExceedsBalance);
}
@@ -258,22 +282,26 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
// and emit coinsSent signal for each recipient
foreach(const SendCoinsRecipient &rcp, transaction.getRecipients())
{
- std::string strAddress = rcp.address.toStdString();
- CTxDestination dest = CBitcoinAddress(strAddress).Get();
- std::string strLabel = rcp.label.toStdString();
+ // Don't touch the address book when we have a payment request
+ if (!rcp.paymentRequest.IsInitialized())
{
- LOCK(wallet->cs_wallet);
-
- std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(dest);
-
- // Check if we have a new address or an updated label
- if (mi == wallet->mapAddressBook.end())
+ std::string strAddress = rcp.address.toStdString();
+ CTxDestination dest = CBitcoinAddress(strAddress).Get();
+ std::string strLabel = rcp.label.toStdString();
{
- wallet->SetAddressBook(dest, strLabel, "send");
- }
- else if (mi->second.name != strLabel)
- {
- wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose
+ LOCK(wallet->cs_wallet);
+
+ std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(dest);
+
+ // Check if we have a new address or an updated label
+ if (mi == wallet->mapAddressBook.end())
+ {
+ wallet->SetAddressBook(dest, strLabel, "send");
+ }
+ else if (mi->second.name != strLabel)
+ {
+ wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose
+ }
}
}
emit coinsSent(wallet, rcp, transaction_array);
@@ -443,3 +471,72 @@ void WalletModel::UnlockContext::CopyFrom(const UnlockContext& rhs)
*this = rhs;
rhs.relock = false;
}
+
+bool WalletModel::getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
+{
+ return wallet->GetPubKey(address, vchPubKeyOut);
+}
+
+// returns a list of COutputs from COutPoints
+void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs)
+{
+ BOOST_FOREACH(const COutPoint& outpoint, vOutpoints)
+ {
+ if (!wallet->mapWallet.count(outpoint.hash)) continue;
+ COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, wallet->mapWallet[outpoint.hash].GetDepthInMainChain());
+ vOutputs.push_back(out);
+ }
+}
+
+// AvailableCoins + LockedCoins grouped by wallet address (put change in one group with wallet address)
+void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins) const
+{
+ std::vector<COutput> vCoins;
+ wallet->AvailableCoins(vCoins);
+
+ std::vector<COutPoint> vLockedCoins;
+ wallet->ListLockedCoins(vLockedCoins);
+
+ // add locked coins
+ BOOST_FOREACH(const COutPoint& outpoint, vLockedCoins)
+ {
+ if (!wallet->mapWallet.count(outpoint.hash)) continue;
+ COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, wallet->mapWallet[outpoint.hash].GetDepthInMainChain());
+ vCoins.push_back(out);
+ }
+
+ BOOST_FOREACH(const COutput& out, vCoins)
+ {
+ COutput cout = out;
+
+ while (wallet->IsChange(cout.tx->vout[cout.i]) && cout.tx->vin.size() > 0 && wallet->IsMine(cout.tx->vin[0]))
+ {
+ if (!wallet->mapWallet.count(cout.tx->vin[0].prevout.hash)) break;
+ cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0);
+ }
+
+ CTxDestination address;
+ if(!ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address)) continue;
+ mapCoins[CBitcoinAddress(address).ToString().c_str()].push_back(out);
+ }
+}
+
+bool WalletModel::isLockedCoin(uint256 hash, unsigned int n) const
+{
+ return wallet->IsLockedCoin(hash, n);
+}
+
+void WalletModel::lockCoin(COutPoint& output)
+{
+ wallet->LockCoin(output);
+}
+
+void WalletModel::unlockCoin(COutPoint& output)
+{
+ wallet->UnlockCoin(output);
+}
+
+void WalletModel::listLockedCoins(std::vector<COutPoint>& vOutpts)
+{
+ wallet->ListLockedCoins(vOutpts);
+}