]> Git Repo - VerusCoin.git/blame - src/qt/walletmodel.cpp
Use a typedef for monetary values
[VerusCoin.git] / src / qt / walletmodel.cpp
CommitLineData
57702541 1// Copyright (c) 2011-2014 The Bitcoin developers
e592d43f
WL
2// Distributed under the MIT/X11 software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
ef079e18 5#include "walletmodel.h"
51ed9ec9 6
ef079e18 7#include "addresstablemodel.h"
51ed9ec9 8#include "guiconstants.h"
666893b1 9#include "recentrequeststablemodel.h"
6c1bf199 10#include "transactiontablemodel.h"
ef079e18 11
51ed9ec9
BD
12#include "base58.h"
13#include "db.h"
14#include "keystore.h"
15#include "main.h"
16#include "sync.h"
6b6aaa16 17#include "ui_interface.h"
51ed9ec9 18#include "wallet.h"
9eace6b1 19#include "walletdb.h" // for BackupWallet
ef079e18 20
51ed9ec9
BD
21#include <stdint.h>
22
23#include <QDebug>
a5e6d723 24#include <QSet>
6c83a841 25#include <QTimer>
ef079e18 26
09eb201b
WL
27using namespace std;
28
ee014e5b
WL
29WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) :
30 QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0),
5df0b03c 31 transactionTableModel(0),
666893b1 32 recentRequestsTableModel(0),
8fdb7e10 33 cachedBalance(0), cachedUnconfirmedBalance(0), cachedImmatureBalance(0),
6c83a841
SE
34 cachedEncryptionStatus(Unencrypted),
35 cachedNumBlocks(0)
ef079e18 36{
acd432b5 37 fProcessingQueuedTransactions = false;
939ed973 38 fHaveWatchOnly = wallet->HaveWatchOnly();
80daee0f 39 fForceCheckBalanceChanged = false;
acd432b5 40
ef079e18
WL
41 addressTableModel = new AddressTableModel(wallet, this);
42 transactionTableModel = new TransactionTableModel(wallet, this);
666893b1 43 recentRequestsTableModel = new RecentRequestsTableModel(wallet, this);
ab1b288f 44
2e00b8fb 45 // This timer will be fired repeatedly to update the balance
6c83a841 46 pollTimer = new QTimer(this);
6c83a841 47 connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollBalanceChanged()));
2e00b8fb 48 pollTimer->start(MODEL_UPDATE_DELAY);
6c83a841 49
ab1b288f
WL
50 subscribeToCoreSignals();
51}
52
53WalletModel::~WalletModel()
54{
55 unsubscribeFromCoreSignals();
ef079e18
WL
56}
57
a372168e 58CAmount WalletModel::getBalance(const CCoinControl *coinControl) const
ef079e18 59{
6a86c24d
CL
60 if (coinControl)
61 {
a372168e 62 CAmount nBalance = 0;
6a86c24d
CL
63 std::vector<COutput> vCoins;
64 wallet->AvailableCoins(vCoins, true, coinControl);
65 BOOST_FOREACH(const COutput& out, vCoins)
2935b211
WL
66 if(out.fSpendable)
67 nBalance += out.tx->vout[out.i].nValue;
6a86c24d
CL
68
69 return nBalance;
70 }
71
ef079e18
WL
72 return wallet->GetBalance();
73}
74
a372168e 75CAmount WalletModel::getUnconfirmedBalance() const
df5ccbd2
WL
76{
77 return wallet->GetUnconfirmedBalance();
78}
79
a372168e 80CAmount WalletModel::getImmatureBalance() const
8fdb7e10 81{
82 return wallet->GetImmatureBalance();
83}
84
939ed973
CL
85bool WalletModel::haveWatchOnly() const
86{
87 return fHaveWatchOnly;
88}
89
a372168e 90CAmount WalletModel::getWatchBalance() const
ffd40da3
J
91{
92 return wallet->GetWatchOnlyBalance();
93}
94
a372168e 95CAmount WalletModel::getWatchUnconfirmedBalance() const
ffd40da3
J
96{
97 return wallet->GetUnconfirmedWatchOnlyBalance();
98}
99
a372168e 100CAmount WalletModel::getWatchImmatureBalance() const
ffd40da3
J
101{
102 return wallet->GetImmatureWatchOnlyBalance();
103}
104
fe4a6550 105void WalletModel::updateStatus()
ef079e18 106{
fe4a6550
WL
107 EncryptionStatus newEncryptionStatus = getEncryptionStatus();
108
109 if(cachedEncryptionStatus != newEncryptionStatus)
110 emit encryptionStatusChanged(newEncryptionStatus);
111}
112
6c83a841 113void WalletModel::pollBalanceChanged()
fe4a6550 114{
41106a50
WL
115 // Get required locks upfront. This avoids the GUI from getting stuck on
116 // periodical polls if the core is holding the locks for a longer time -
117 // for example, during a wallet rescan.
118 TRY_LOCK(cs_main, lockMain);
119 if(!lockMain)
120 return;
121 TRY_LOCK(wallet->cs_wallet, lockWallet);
122 if(!lockWallet)
123 return;
124
80daee0f 125 if(fForceCheckBalanceChanged || chainActive.Height() != cachedNumBlocks)
2e00b8fb 126 {
80daee0f
CL
127 fForceCheckBalanceChanged = false;
128
41106a50
WL
129 // Balance and number of transactions might have changed
130 cachedNumBlocks = chainActive.Height();
131
6c83a841 132 checkBalanceChanged();
55a1db4f
WL
133 if(transactionTableModel)
134 transactionTableModel->updateConfirmations();
6c83a841 135 }
6c83a841
SE
136}
137
138void WalletModel::checkBalanceChanged()
139{
a372168e
MF
140 CAmount newBalance = getBalance();
141 CAmount newUnconfirmedBalance = getUnconfirmedBalance();
142 CAmount newImmatureBalance = getImmatureBalance();
143 CAmount newWatchOnlyBalance = 0;
144 CAmount newWatchUnconfBalance = 0;
145 CAmount newWatchImmatureBalance = 0;
939ed973
CL
146 if (haveWatchOnly())
147 {
148 newWatchOnlyBalance = getWatchBalance();
149 newWatchUnconfBalance = getWatchUnconfirmedBalance();
150 newWatchImmatureBalance = getWatchImmatureBalance();
151 }
5df0b03c 152
ffd40da3
J
153 if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance ||
154 cachedWatchOnlyBalance != newWatchOnlyBalance || cachedWatchUnconfBalance != newWatchUnconfBalance || cachedWatchImmatureBalance != newWatchImmatureBalance)
2e00b8fb 155 {
6c83a841
SE
156 cachedBalance = newBalance;
157 cachedUnconfirmedBalance = newUnconfirmedBalance;
158 cachedImmatureBalance = newImmatureBalance;
ffd40da3
J
159 cachedWatchOnlyBalance = newWatchOnlyBalance;
160 cachedWatchUnconfBalance = newWatchUnconfBalance;
161 cachedWatchImmatureBalance = newWatchImmatureBalance;
162 emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance,
163 newWatchOnlyBalance, newWatchUnconfBalance, newWatchImmatureBalance);
6c83a841
SE
164 }
165}
8fdb7e10 166
6c83a841
SE
167void WalletModel::updateTransaction(const QString &hash, int status)
168{
169 if(transactionTableModel)
170 transactionTableModel->updateTransaction(hash, status);
5df0b03c 171
6c83a841 172 // Balance and number of transactions might have changed
80daee0f 173 fForceCheckBalanceChanged = true;
ef079e18
WL
174}
175
42018eff 176void WalletModel::updateAddressBook(const QString &address, const QString &label,
dcd0b077 177 bool isMine, const QString &purpose, int status)
98e61758 178{
fe4a6550 179 if(addressTableModel)
dcd0b077 180 addressTableModel->updateEntry(address, label, isMine, purpose, status);
98e61758
WL
181}
182
939ed973
CL
183void WalletModel::updateWatchOnlyFlag(bool fHaveWatchonly)
184{
185 fHaveWatchOnly = fHaveWatchonly;
186 emit notifyWatchonlyChanged(fHaveWatchonly);
187}
188
a5e6d723 189bool WalletModel::validateAddress(const QString &address)
ef079e18 190{
491ad6db
WL
191 CBitcoinAddress addressParsed(address.toStdString());
192 return addressParsed.IsValid();
a5e6d723
WL
193}
194
6a86c24d 195WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl)
a5e6d723 196{
a372168e 197 CAmount total = 0;
9e8904f6 198 QList<SendCoinsRecipient> recipients = transaction.getRecipients();
a372168e 199 std::vector<std::pair<CScript, CAmount> > vecSend;
a5e6d723
WL
200
201 if(recipients.empty())
ef079e18 202 {
a5e6d723 203 return OK;
ef079e18
WL
204 }
205
a41d5fe0
GA
206 QSet<QString> setAddress; // Used to detect duplicates
207 int nAddresses = 0;
208
a5e6d723
WL
209 // Pre-check input data for validity
210 foreach(const SendCoinsRecipient &rcp, recipients)
ef079e18 211 {
a41d5fe0 212 if (rcp.paymentRequest.IsInitialized())
d5f0ef54 213 { // PaymentRequest...
a372168e 214 CAmount subtotal = 0;
a41d5fe0
GA
215 const payments::PaymentDetails& details = rcp.paymentRequest.getDetails();
216 for (int i = 0; i < details.outputs_size(); i++)
217 {
218 const payments::Output& out = details.outputs(i);
219 if (out.amount() <= 0) continue;
220 subtotal += out.amount();
221 const unsigned char* scriptStr = (const unsigned char*)out.script().data();
222 CScript scriptPubKey(scriptStr, scriptStr+out.script().size());
a372168e 223 vecSend.push_back(std::pair<CScript, CAmount>(scriptPubKey, out.amount()));
a41d5fe0
GA
224 }
225 if (subtotal <= 0)
226 {
227 return InvalidAmount;
228 }
229 total += subtotal;
a5e6d723 230 }
a41d5fe0
GA
231 else
232 { // User-entered bitcoin address / amount:
233 if(!validateAddress(rcp.address))
234 {
235 return InvalidAddress;
236 }
237 if(rcp.amount <= 0)
238 {
239 return InvalidAmount;
240 }
241 setAddress.insert(rcp.address);
242 ++nAddresses;
a5e6d723 243
0be990ba 244 CScript scriptPubKey = GetScriptForDestination(CBitcoinAddress(rcp.address.toStdString()).Get());
a372168e 245 vecSend.push_back(std::pair<CScript, CAmount>(scriptPubKey, rcp.amount));
a41d5fe0
GA
246
247 total += rcp.amount;
a5e6d723 248 }
ef079e18 249 }
a41d5fe0 250 if(setAddress.size() != nAddresses)
a5e6d723
WL
251 {
252 return DuplicateAddress;
253 }
254
a372168e 255 CAmount nBalance = getBalance(coinControl);
6a86c24d
CL
256
257 if(total > nBalance)
ef079e18
WL
258 {
259 return AmountExceedsBalance;
260 }
261
ef079e18 262 {
f8dcd5ca
PW
263 LOCK2(cs_main, wallet->cs_wallet);
264
9e8904f6 265 transaction.newPossibleKeyChange(wallet);
a372168e 266 CAmount nFeeRequired = 0;
1f00f4e9 267 std::string strFailReason;
9e8904f6
JS
268
269 CWalletTx *newTx = transaction.getTransaction();
270 CReserveKey *keyChange = transaction.getPossibleKeyChange();
6a86c24d 271 bool fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, strFailReason, coinControl);
9e8904f6 272 transaction.setTransactionFee(nFeeRequired);
ef079e18 273
a5e6d723 274 if(!fCreated)
ef079e18 275 {
6a86c24d 276 if((total + nFeeRequired) > nBalance)
a5e6d723 277 {
9e8904f6 278 return SendCoinsReturn(AmountWithFeeExceedsBalance);
a5e6d723 279 }
1f00f4e9
GA
280 emit message(tr("Send Coins"), QString::fromStdString(strFailReason),
281 CClientUIInterface::MSG_ERROR);
a5e6d723 282 return TransactionCreationFailed;
ef079e18 283 }
9e8904f6
JS
284 }
285
286 return SendCoinsReturn(OK);
287}
288
289WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &transaction)
290{
291 QByteArray transaction_array; /* store serialized transaction */
292
293 {
294 LOCK2(cs_main, wallet->cs_wallet);
295 CWalletTx *newTx = transaction.getTransaction();
296
a41d5fe0 297 // Store PaymentRequests in wtx.vOrderForm in wallet.
9e8904f6 298 foreach(const SendCoinsRecipient &rcp, transaction.getRecipients())
a41d5fe0
GA
299 {
300 if (rcp.paymentRequest.IsInitialized())
301 {
302 std::string key("PaymentRequest");
303 std::string value;
304 rcp.paymentRequest.SerializeToString(&value);
9e8904f6 305 newTx->vOrderForm.push_back(make_pair(key, value));
a41d5fe0 306 }
22a51207
CL
307 else if (!rcp.message.isEmpty()) // Message from normal bitcoin:URI (bitcoin:123...?message=example)
308 newTx->vOrderForm.push_back(make_pair("Message", rcp.message.toStdString()));
ef079e18 309 }
9e8904f6
JS
310
311 CReserveKey *keyChange = transaction.getPossibleKeyChange();
312 if(!wallet->CommitTransaction(*newTx, *keyChange))
a5e6d723 313 return TransactionCommitFailed;
a41d5fe0 314
9e8904f6 315 CTransaction* t = (CTransaction*)newTx;
a41d5fe0
GA
316 CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
317 ssTx << *t;
9e8904f6 318 transaction_array.append(&(ssTx[0]), ssTx.size());
ef079e18
WL
319 }
320
a41d5fe0 321 // Add addresses / update labels that we've sent to to the address book,
9e8904f6
JS
322 // and emit coinsSent signal for each recipient
323 foreach(const SendCoinsRecipient &rcp, transaction.getRecipients())
ef079e18 324 {
c6c97e0f
PK
325 // Don't touch the address book when we have a payment request
326 if (!rcp.paymentRequest.IsInitialized())
a5e6d723 327 {
48c01148
PK
328 std::string strAddress = rcp.address.toStdString();
329 CTxDestination dest = CBitcoinAddress(strAddress).Get();
330 std::string strLabel = rcp.label.toStdString();
dab7acdf 331 {
48c01148
PK
332 LOCK(wallet->cs_wallet);
333
334 std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(dest);
335
336 // Check if we have a new address or an updated label
337 if (mi == wallet->mapAddressBook.end())
338 {
339 wallet->SetAddressBook(dest, strLabel, "send");
340 }
341 else if (mi->second.name != strLabel)
342 {
343 wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose
344 }
dab7acdf 345 }
a5e6d723 346 }
9e8904f6 347 emit coinsSent(wallet, rcp, transaction_array);
ef079e18 348 }
80daee0f 349 checkBalanceChanged(); // update balance immediately, otherwise there could be a short noticeable delay until pollBalanceChanged hits
a5e13258 350
9e8904f6 351 return SendCoinsReturn(OK);
ef079e18
WL
352}
353
354OptionsModel *WalletModel::getOptionsModel()
355{
356 return optionsModel;
357}
358
359AddressTableModel *WalletModel::getAddressTableModel()
360{
361 return addressTableModel;
362}
363
364TransactionTableModel *WalletModel::getTransactionTableModel()
365{
366 return transactionTableModel;
367}
ebff5c40 368
666893b1
WL
369RecentRequestsTableModel *WalletModel::getRecentRequestsTableModel()
370{
371 return recentRequestsTableModel;
372}
373
ae8adeb9
WL
374WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const
375{
376 if(!wallet->IsCrypted())
377 {
378 return Unencrypted;
379 }
380 else if(wallet->IsLocked())
381 {
382 return Locked;
383 }
384 else
385 {
386 return Unlocked;
387 }
388}
b7bcaf94 389
94f778bd 390bool WalletModel::setWalletEncrypted(bool encrypted, const SecureString &passphrase)
b7bcaf94
WL
391{
392 if(encrypted)
393 {
394 // Encrypt
395 return wallet->EncryptWallet(passphrase);
396 }
397 else
398 {
399 // Decrypt -- TODO; not supported yet
400 return false;
401 }
402}
403
94f778bd 404bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase)
b7bcaf94
WL
405{
406 if(locked)
407 {
408 // Lock
409 return wallet->Lock();
410 }
411 else
412 {
413 // Unlock
414 return wallet->Unlock(passPhrase);
415 }
416}
417
94f778bd 418bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureString &newPass)
b7bcaf94
WL
419{
420 bool retval;
b7bcaf94 421 {
f8dcd5ca 422 LOCK(wallet->cs_wallet);
b7bcaf94
WL
423 wallet->Lock(); // Make sure wallet is locked before attempting pass change
424 retval = wallet->ChangeWalletPassphrase(oldPass, newPass);
425 }
426 return retval;
427}
428
4efbda3f 429bool WalletModel::backupWallet(const QString &filename)
430{
431 return BackupWallet(*wallet, filename.toLocal8Bit().data());
432}
433
ab1b288f
WL
434// Handlers for core signals
435static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel, CCryptoKeyStore *wallet)
436{
42018eff 437 qDebug() << "NotifyKeyStoreStatusChanged";
ab1b288f
WL
438 QMetaObject::invokeMethod(walletmodel, "updateStatus", Qt::QueuedConnection);
439}
440
dcd0b077
WL
441static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet,
442 const CTxDestination &address, const std::string &label, bool isMine,
443 const std::string &purpose, ChangeType status)
ab1b288f 444{
42018eff
PK
445 QString strAddress = QString::fromStdString(CBitcoinAddress(address).ToString());
446 QString strLabel = QString::fromStdString(label);
447 QString strPurpose = QString::fromStdString(purpose);
448
449 qDebug() << "NotifyAddressBookChanged : " + strAddress + " " + strLabel + " isMine=" + QString::number(isMine) + " purpose=" + strPurpose + " status=" + QString::number(status);
ab1b288f 450 QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection,
42018eff
PK
451 Q_ARG(QString, strAddress),
452 Q_ARG(QString, strLabel),
0832c0d1 453 Q_ARG(bool, isMine),
42018eff 454 Q_ARG(QString, strPurpose),
ab1b288f
WL
455 Q_ARG(int, status));
456}
457
39278369
CL
458// queue notifications to show a non freezing progress dialog e.g. for rescan
459static bool fQueueNotifications = false;
460static std::vector<std::pair<uint256, ChangeType> > vQueueNotifications;
ab1b288f
WL
461static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet, const uint256 &hash, ChangeType status)
462{
39278369
CL
463 if (fQueueNotifications)
464 {
465 vQueueNotifications.push_back(make_pair(hash, status));
466 return;
467 }
468
42018eff
PK
469 QString strHash = QString::fromStdString(hash.GetHex());
470
471 qDebug() << "NotifyTransactionChanged : " + strHash + " status= " + QString::number(status);
ab1b288f 472 QMetaObject::invokeMethod(walletmodel, "updateTransaction", Qt::QueuedConnection,
42018eff 473 Q_ARG(QString, strHash),
ab1b288f
WL
474 Q_ARG(int, status));
475}
476
39278369
CL
477static void ShowProgress(WalletModel *walletmodel, const std::string &title, int nProgress)
478{
39278369
CL
479 if (nProgress == 0)
480 fQueueNotifications = true;
481
482 if (nProgress == 100)
483 {
484 fQueueNotifications = false;
acd432b5
CL
485 if (vQueueNotifications.size() > 10) // prevent balloon spam, show maximum 10 balloons
486 QMetaObject::invokeMethod(walletmodel, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));
487 for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)
488 {
489 if (vQueueNotifications.size() - i <= 10)
490 QMetaObject::invokeMethod(walletmodel, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));
491
492 NotifyTransactionChanged(walletmodel, NULL, vQueueNotifications[i].first, vQueueNotifications[i].second);
493 }
39278369
CL
494 std::vector<std::pair<uint256, ChangeType> >().swap(vQueueNotifications); // clear
495 }
80daee0f
CL
496
497 // emits signal "showProgress"
498 QMetaObject::invokeMethod(walletmodel, "showProgress", Qt::QueuedConnection,
499 Q_ARG(QString, QString::fromStdString(title)),
500 Q_ARG(int, nProgress));
39278369
CL
501}
502
939ed973
CL
503static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly)
504{
505 QMetaObject::invokeMethod(walletmodel, "updateWatchOnlyFlag", Qt::QueuedConnection,
506 Q_ARG(bool, fHaveWatchonly));
507}
508
ab1b288f
WL
509void WalletModel::subscribeToCoreSignals()
510{
511 // Connect signals to wallet
512 wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
dcd0b077 513 wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
ab1b288f 514 wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
39278369 515 wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
939ed973 516 wallet->NotifyWatchonlyChanged.connect(boost::bind(NotifyWatchonlyChanged, this, _1));
ab1b288f
WL
517}
518
519void WalletModel::unsubscribeFromCoreSignals()
520{
521 // Disconnect signals from wallet
522 wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
dcd0b077 523 wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
ab1b288f 524 wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
39278369 525 wallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
939ed973 526 wallet->NotifyWatchonlyChanged.disconnect(boost::bind(NotifyWatchonlyChanged, this, _1));
ab1b288f
WL
527}
528
b7bcaf94
WL
529// WalletModel::UnlockContext implementation
530WalletModel::UnlockContext WalletModel::requestUnlock()
531{
532 bool was_locked = getEncryptionStatus() == Locked;
533 if(was_locked)
534 {
535 // Request UI to unlock wallet
536 emit requireUnlock();
537 }
538 // If wallet is still locked, unlock was failed or cancelled, mark context as invalid
539 bool valid = getEncryptionStatus() != Locked;
540
541 return UnlockContext(this, valid, was_locked);
542}
543
544WalletModel::UnlockContext::UnlockContext(WalletModel *wallet, bool valid, bool relock):
545 wallet(wallet),
546 valid(valid),
547 relock(relock)
548{
549}
550
551WalletModel::UnlockContext::~UnlockContext()
552{
553 if(valid && relock)
554 {
555 wallet->setWalletLocked(true);
556 }
557}
558
559void WalletModel::UnlockContext::CopyFrom(const UnlockContext& rhs)
560{
561 // Transfer context; old object no longer relocks wallet
562 *this = rhs;
563 rhs.relock = false;
564}
6a86c24d
CL
565
566bool WalletModel::getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
567{
568 return wallet->GetPubKey(address, vchPubKeyOut);
569}
570
571// returns a list of COutputs from COutPoints
572void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs)
573{
55a1db4f 574 LOCK2(cs_main, wallet->cs_wallet);
6a86c24d
CL
575 BOOST_FOREACH(const COutPoint& outpoint, vOutpoints)
576 {
577 if (!wallet->mapWallet.count(outpoint.hash)) continue;
2b72d46f
GA
578 int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain();
579 if (nDepth < 0) continue;
c8988460 580 COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true);
6a86c24d
CL
581 vOutputs.push_back(out);
582 }
583}
584
93a18a36
GA
585bool WalletModel::isSpent(const COutPoint& outpoint) const
586{
55a1db4f 587 LOCK2(cs_main, wallet->cs_wallet);
93a18a36
GA
588 return wallet->IsSpent(outpoint.hash, outpoint.n);
589}
590
6a86c24d
CL
591// AvailableCoins + LockedCoins grouped by wallet address (put change in one group with wallet address)
592void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins) const
593{
594 std::vector<COutput> vCoins;
595 wallet->AvailableCoins(vCoins);
596
55a1db4f 597 LOCK2(cs_main, wallet->cs_wallet); // ListLockedCoins, mapWallet
6a86c24d
CL
598 std::vector<COutPoint> vLockedCoins;
599 wallet->ListLockedCoins(vLockedCoins);
600
601 // add locked coins
602 BOOST_FOREACH(const COutPoint& outpoint, vLockedCoins)
603 {
604 if (!wallet->mapWallet.count(outpoint.hash)) continue;
2b72d46f
GA
605 int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain();
606 if (nDepth < 0) continue;
c8988460 607 COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true);
6a86c24d
CL
608 vCoins.push_back(out);
609 }
610
611 BOOST_FOREACH(const COutput& out, vCoins)
612 {
613 COutput cout = out;
614
615 while (wallet->IsChange(cout.tx->vout[cout.i]) && cout.tx->vin.size() > 0 && wallet->IsMine(cout.tx->vin[0]))
616 {
617 if (!wallet->mapWallet.count(cout.tx->vin[0].prevout.hash)) break;
c8988460 618 cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0, true);
6a86c24d
CL
619 }
620
621 CTxDestination address;
2935b211
WL
622 if(!out.fSpendable || !ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address))
623 continue;
2c2cc5da 624 mapCoins[QString::fromStdString(CBitcoinAddress(address).ToString())].push_back(out);
6a86c24d
CL
625 }
626}
627
628bool WalletModel::isLockedCoin(uint256 hash, unsigned int n) const
629{
55a1db4f 630 LOCK2(cs_main, wallet->cs_wallet);
6a86c24d
CL
631 return wallet->IsLockedCoin(hash, n);
632}
633
634void WalletModel::lockCoin(COutPoint& output)
635{
55a1db4f 636 LOCK2(cs_main, wallet->cs_wallet);
6a86c24d
CL
637 wallet->LockCoin(output);
638}
639
640void WalletModel::unlockCoin(COutPoint& output)
641{
55a1db4f 642 LOCK2(cs_main, wallet->cs_wallet);
6a86c24d
CL
643 wallet->UnlockCoin(output);
644}
645
646void WalletModel::listLockedCoins(std::vector<COutPoint>& vOutpts)
647{
55a1db4f 648 LOCK2(cs_main, wallet->cs_wallet);
6a86c24d
CL
649 wallet->ListLockedCoins(vOutpts);
650}
8476d5d4
CL
651
652void WalletModel::loadReceiveRequests(std::vector<std::string>& vReceiveRequests)
653{
654 LOCK(wallet->cs_wallet);
655 BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, wallet->mapAddressBook)
656 BOOST_FOREACH(const PAIRTYPE(std::string, std::string)& item2, item.second.destdata)
657 if (item2.first.size() > 2 && item2.first.substr(0,2) == "rr") // receive request
658 vReceiveRequests.push_back(item2.second);
659}
660
661bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest)
662{
663 CTxDestination dest = CBitcoinAddress(sAddress).Get();
664
665 std::stringstream ss;
666 ss << nId;
667 std::string key = "rr" + ss.str(); // "rr" prefix = "receive request" in destdata
668
669 LOCK(wallet->cs_wallet);
670 if (sRequest.empty())
671 return wallet->EraseDestData(dest, key);
672 else
673 return wallet->AddDestData(dest, key, sRequest);
674}
This page took 0.234461 seconds and 4 git commands to generate.