Dash Core  0.12.2.1
P2P Digital Currency
walletmodel.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2015 The Bitcoin Core developers
2 // Copyright (c) 2014-2017 The Dash Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include "walletmodel.h"
7 
8 #include "addresstablemodel.h"
9 #include "guiconstants.h"
10 #include "guiutil.h"
11 #include "paymentserver.h"
13 #include "transactiontablemodel.h"
14 
15 #include "base58.h"
16 #include "keystore.h"
17 #include "validation.h"
18 #include "net.h" // for g_connman
19 #include "sync.h"
20 #include "ui_interface.h"
21 #include "util.h" // for GetBoolArg
22 #include "wallet/wallet.h"
23 #include "wallet/walletdb.h" // for BackupWallet
24 
25 #include "instantx.h"
26 #include "spork.h"
27 #include "privatesend-client.h"
28 
29 #include <stdint.h>
30 
31 #include <QDebug>
32 #include <QSet>
33 #include <QTimer>
34 
35 #include <boost/foreach.hpp>
36 
37 WalletModel::WalletModel(const PlatformStyle *platformStyle, CWallet *wallet, OptionsModel *optionsModel, QObject *parent) :
38  QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0),
39  transactionTableModel(0),
40  recentRequestsTableModel(0),
41  cachedBalance(0),
42  cachedUnconfirmedBalance(0),
43  cachedImmatureBalance(0),
44  cachedAnonymizedBalance(0),
45  cachedWatchOnlyBalance(0),
46  cachedWatchUnconfBalance(0),
47  cachedWatchImmatureBalance(0),
48  cachedEncryptionStatus(Unencrypted),
49  cachedNumBlocks(0),
50  cachedTxLocks(0),
51  cachedPrivateSendRounds(0)
52 {
53  fHaveWatchOnly = wallet->HaveWatchOnly();
55 
57  transactionTableModel = new TransactionTableModel(platformStyle, wallet, this);
59 
60  // This timer will be fired repeatedly to update the balance
61  pollTimer = new QTimer(this);
62  connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollBalanceChanged()));
64 
66 }
67 
69 {
71 }
72 
73 CAmount WalletModel::getBalance(const CCoinControl *coinControl) const
74 {
75  if (coinControl)
76  {
77  CAmount nBalance = 0;
78  std::vector<COutput> vCoins;
79  wallet->AvailableCoins(vCoins, true, coinControl);
80  BOOST_FOREACH(const COutput& out, vCoins)
81  if(out.fSpendable)
82  nBalance += out.tx->vout[out.i].nValue;
83 
84  return nBalance;
85  }
86 
87  return wallet->GetBalance();
88 }
89 
90 
92 {
93  return wallet->GetAnonymizedBalance();
94 }
95 
97 {
98  return wallet->GetUnconfirmedBalance();
99 }
100 
102 {
103  return wallet->GetImmatureBalance();
104 }
105 
107 {
108  return fHaveWatchOnly;
109 }
110 
112 {
113  return wallet->GetWatchOnlyBalance();
114 }
115 
117 {
118  return wallet->GetUnconfirmedWatchOnlyBalance();
119 }
120 
122 {
123  return wallet->GetImmatureWatchOnlyBalance();
124 }
125 
127 {
128  EncryptionStatus newEncryptionStatus = getEncryptionStatus();
129 
130  if(cachedEncryptionStatus != newEncryptionStatus)
131  Q_EMIT encryptionStatusChanged(newEncryptionStatus);
132 }
133 
135 {
136  // Get required locks upfront. This avoids the GUI from getting stuck on
137  // periodical polls if the core is holding the locks for a longer time -
138  // for example, during a wallet rescan.
139  TRY_LOCK(cs_main, lockMain);
140  if(!lockMain)
141  return;
142  TRY_LOCK(wallet->cs_wallet, lockWallet);
143  if(!lockWallet)
144  return;
145 
147  {
149 
150  // Balance and number of transactions might have changed
153 
157  }
158 }
159 
161 {
162  CAmount newBalance = getBalance();
163  CAmount newUnconfirmedBalance = getUnconfirmedBalance();
164  CAmount newImmatureBalance = getImmatureBalance();
165  CAmount newAnonymizedBalance = getAnonymizedBalance();
166  CAmount newWatchOnlyBalance = 0;
167  CAmount newWatchUnconfBalance = 0;
168  CAmount newWatchImmatureBalance = 0;
169  if (haveWatchOnly())
170  {
171  newWatchOnlyBalance = getWatchBalance();
172  newWatchUnconfBalance = getWatchUnconfirmedBalance();
173  newWatchImmatureBalance = getWatchImmatureBalance();
174  }
175 
176  if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance ||
177  cachedAnonymizedBalance != newAnonymizedBalance || cachedTxLocks != nCompleteTXLocks ||
178  cachedWatchOnlyBalance != newWatchOnlyBalance || cachedWatchUnconfBalance != newWatchUnconfBalance || cachedWatchImmatureBalance != newWatchImmatureBalance)
179  {
180  cachedBalance = newBalance;
181  cachedUnconfirmedBalance = newUnconfirmedBalance;
182  cachedImmatureBalance = newImmatureBalance;
183  cachedAnonymizedBalance = newAnonymizedBalance;
185  cachedWatchOnlyBalance = newWatchOnlyBalance;
186  cachedWatchUnconfBalance = newWatchUnconfBalance;
187  cachedWatchImmatureBalance = newWatchImmatureBalance;
188  Q_EMIT balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance, newAnonymizedBalance,
189  newWatchOnlyBalance, newWatchUnconfBalance, newWatchImmatureBalance);
190  }
191 }
192 
194 {
195  // Balance and number of transactions might have changed
197 }
198 
199 void WalletModel::updateAddressBook(const QString &address, const QString &label,
200  bool isMine, const QString &purpose, int status)
201 {
203  addressTableModel->updateEntry(address, label, isMine, purpose, status);
204 }
205 
206 void WalletModel::updateWatchOnlyFlag(bool fHaveWatchonly)
207 {
208  fHaveWatchOnly = fHaveWatchonly;
209  Q_EMIT notifyWatchonlyChanged(fHaveWatchonly);
210 }
211 
212 bool WalletModel::validateAddress(const QString &address)
213 {
214  CBitcoinAddress addressParsed(address.toStdString());
215  return addressParsed.IsValid();
216 }
217 
219 {
220  CAmount total = 0;
221  bool fSubtractFeeFromAmount = false;
222  QList<SendCoinsRecipient> recipients = transaction.getRecipients();
223  std::vector<CRecipient> vecSend;
224 
225  if(recipients.empty())
226  {
227  return OK;
228  }
229 
230  // This should never really happen, yet another safety check, just in case.
231  if(wallet->IsLocked()) {
233  }
234 
235  QSet<QString> setAddress; // Used to detect duplicates
236  int nAddresses = 0;
237 
238  // Pre-check input data for validity
239  Q_FOREACH(const SendCoinsRecipient &rcp, recipients)
240  {
241  if (rcp.fSubtractFeeFromAmount)
242  fSubtractFeeFromAmount = true;
243 
244  if (rcp.paymentRequest.IsInitialized())
245  { // PaymentRequest...
246  CAmount subtotal = 0;
247  const payments::PaymentDetails& details = rcp.paymentRequest.getDetails();
248  for (int i = 0; i < details.outputs_size(); i++)
249  {
250  const payments::Output& out = details.outputs(i);
251  if (out.amount() <= 0) continue;
252  subtotal += out.amount();
253  const unsigned char* scriptStr = (const unsigned char*)out.script().data();
254  CScript scriptPubKey(scriptStr, scriptStr+out.script().size());
255  CAmount nAmount = out.amount();
256  CRecipient recipient = {scriptPubKey, nAmount, rcp.fSubtractFeeFromAmount};
257  vecSend.push_back(recipient);
258  }
259  if (subtotal <= 0)
260  {
261  return InvalidAmount;
262  }
263  total += subtotal;
264  }
265  else
266  { // User-entered dash address / amount:
267  if(!validateAddress(rcp.address))
268  {
269  return InvalidAddress;
270  }
271  if(rcp.amount <= 0)
272  {
273  return InvalidAmount;
274  }
275  setAddress.insert(rcp.address);
276  ++nAddresses;
277 
278  CScript scriptPubKey = GetScriptForDestination(CBitcoinAddress(rcp.address.toStdString()).Get());
279  CRecipient recipient = {scriptPubKey, rcp.amount, rcp.fSubtractFeeFromAmount};
280  vecSend.push_back(recipient);
281 
282  total += rcp.amount;
283  }
284  }
285  if(setAddress.size() != nAddresses)
286  {
287  return DuplicateAddress;
288  }
289 
290  CAmount nBalance = getBalance(coinControl);
291 
292  if(total > nBalance)
293  {
294  return AmountExceedsBalance;
295  }
296 
297  {
298  LOCK2(cs_main, wallet->cs_wallet);
299 
300  transaction.newPossibleKeyChange(wallet);
301 
302  CAmount nFeeRequired = 0;
303  int nChangePosRet = -1;
304  std::string strFailReason;
305 
306  CWalletTx *newTx = transaction.getTransaction();
307  CReserveKey *keyChange = transaction.getPossibleKeyChange();
308 
309  if(recipients[0].fUseInstantSend && total > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN){
310  Q_EMIT message(tr("Send Coins"), tr("InstantSend doesn't support sending values that high yet. Transactions are currently limited to %1 DASH.").arg(sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)),
313  }
314 
315  bool fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, nChangePosRet, strFailReason, coinControl, true, recipients[0].inputType, recipients[0].fUseInstantSend);
316  transaction.setTransactionFee(nFeeRequired);
317  if (fSubtractFeeFromAmount && fCreated)
318  transaction.reassignAmounts(nChangePosRet);
319 
320  if(recipients[0].fUseInstantSend) {
322  Q_EMIT message(tr("Send Coins"), tr("InstantSend doesn't support sending values that high yet. Transactions are currently limited to %1 DASH.").arg(sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)),
325  }
326  if(newTx->vin.size() > CTxLockRequest::WARN_MANY_INPUTS) {
327  Q_EMIT message(tr("Send Coins"), tr("Used way too many inputs (>%1) for this InstantSend transaction, fees could be huge.").arg(CTxLockRequest::WARN_MANY_INPUTS),
329  }
330  }
331 
332  if(!fCreated)
333  {
334  if(!fSubtractFeeFromAmount && (total + nFeeRequired) > nBalance)
335  {
337  }
338  Q_EMIT message(tr("Send Coins"), QString::fromStdString(strFailReason),
341  }
342 
343  // reject absurdly high fee. (This can never happen because the
344  // wallet caps the fee at maxTxFee. This merely serves as a
345  // belt-and-suspenders check)
346  if (nFeeRequired > maxTxFee)
347  return AbsurdFee;
348  }
349 
350  return SendCoinsReturn(OK);
351 }
352 
354 {
355  QByteArray transaction_array; /* store serialized transaction */
356 
357  {
358  LOCK2(cs_main, wallet->cs_wallet);
359  CWalletTx *newTx = transaction.getTransaction();
360  QList<SendCoinsRecipient> recipients = transaction.getRecipients();
361 
362  Q_FOREACH(const SendCoinsRecipient &rcp, recipients)
363  {
364  if (rcp.paymentRequest.IsInitialized())
365  {
366  // Make sure any payment requests involved are still valid.
368  return PaymentRequestExpired;
369  }
370 
371  // Store PaymentRequests in wtx.vOrderForm in wallet.
372  std::string key("PaymentRequest");
373  std::string value;
374  rcp.paymentRequest.SerializeToString(&value);
375  newTx->vOrderForm.push_back(make_pair(key, value));
376  }
377  else if (!rcp.message.isEmpty()) // Message from normal dash:URI (dash:XyZ...?message=example)
378  {
379  newTx->vOrderForm.push_back(make_pair("Message", rcp.message.toStdString()));
380  }
381  }
382 
383  CReserveKey *keyChange = transaction.getPossibleKeyChange();
384 
385  if(!wallet->CommitTransaction(*newTx, *keyChange, g_connman.get(), recipients[0].fUseInstantSend ? NetMsgType::TXLOCKREQUEST : NetMsgType::TX))
387 
388  CTransaction* t = (CTransaction*)newTx;
390  ssTx << *t;
391  transaction_array.append(&(ssTx[0]), ssTx.size());
392  }
393 
394  // Add addresses / update labels that we've sent to to the address book,
395  // and emit coinsSent signal for each recipient
396  Q_FOREACH(const SendCoinsRecipient &rcp, transaction.getRecipients())
397  {
398  // Don't touch the address book when we have a payment request
399  if (!rcp.paymentRequest.IsInitialized())
400  {
401  std::string strAddress = rcp.address.toStdString();
402  CTxDestination dest = CBitcoinAddress(strAddress).Get();
403  std::string strLabel = rcp.label.toStdString();
404  {
405  LOCK(wallet->cs_wallet);
406 
407  std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(dest);
408 
409  // Check if we have a new address or an updated label
410  if (mi == wallet->mapAddressBook.end())
411  {
412  wallet->SetAddressBook(dest, strLabel, "send");
413  }
414  else if (mi->second.name != strLabel)
415  {
416  wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose
417  }
418  }
419  }
420  Q_EMIT coinsSent(wallet, rcp, transaction_array);
421  }
422  checkBalanceChanged(); // update balance immediately, otherwise there could be a short noticeable delay until pollBalanceChanged hits
423 
424  return SendCoinsReturn(OK);
425 }
426 
428 {
429  return optionsModel;
430 }
431 
433 {
434  return addressTableModel;
435 }
436 
438 {
439  return transactionTableModel;
440 }
441 
443 {
445 }
446 
448 {
449  if(!wallet->IsCrypted())
450  {
451  return Unencrypted;
452  }
453  else if(wallet->IsLocked(true))
454  {
455  return Locked;
456  }
457  else if (wallet->IsLocked())
458  {
459  return UnlockedForMixingOnly;
460  }
461  else
462  {
463  return Unlocked;
464  }
465 }
466 
467 bool WalletModel::setWalletEncrypted(bool encrypted, const SecureString &passphrase)
468 {
469  if(encrypted)
470  {
471  // Encrypt
472  return wallet->EncryptWallet(passphrase);
473  }
474  else
475  {
476  // Decrypt -- TODO; not supported yet
477  return false;
478  }
479 }
480 
481 bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase, bool fMixing)
482 {
483  if(locked)
484  {
485  // Lock
486  return wallet->Lock(fMixing);
487  }
488  else
489  {
490  // Unlock
491  return wallet->Unlock(passPhrase, fMixing);
492  }
493 }
494 
495 bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureString &newPass)
496 {
497  bool retval;
498  {
499  LOCK(wallet->cs_wallet);
500  wallet->Lock(); // Make sure wallet is locked before attempting pass change
501  retval = wallet->ChangeWalletPassphrase(oldPass, newPass);
502  }
503  return retval;
504 }
505 
506 bool WalletModel::backupWallet(const QString &filename)
507 {
508  return BackupWallet(*wallet, filename.toLocal8Bit().data());
509 }
510 
511 // Handlers for core signals
513 {
514  qDebug() << "NotifyKeyStoreStatusChanged";
515  QMetaObject::invokeMethod(walletmodel, "updateStatus", Qt::QueuedConnection);
516 }
517 
519  const CTxDestination &address, const std::string &label, bool isMine,
520  const std::string &purpose, ChangeType status)
521 {
522  QString strAddress = QString::fromStdString(CBitcoinAddress(address).ToString());
523  QString strLabel = QString::fromStdString(label);
524  QString strPurpose = QString::fromStdString(purpose);
525 
526  qDebug() << "NotifyAddressBookChanged: " + strAddress + " " + strLabel + " isMine=" + QString::number(isMine) + " purpose=" + strPurpose + " status=" + QString::number(status);
527  QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection,
528  Q_ARG(QString, strAddress),
529  Q_ARG(QString, strLabel),
530  Q_ARG(bool, isMine),
531  Q_ARG(QString, strPurpose),
532  Q_ARG(int, status));
533 }
534 
535 static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet, const uint256 &hash, ChangeType status)
536 {
537  Q_UNUSED(wallet);
538  Q_UNUSED(hash);
539  Q_UNUSED(status);
540  QMetaObject::invokeMethod(walletmodel, "updateTransaction", Qt::QueuedConnection);
541 }
542 
543 static void ShowProgress(WalletModel *walletmodel, const std::string &title, int nProgress)
544 {
545  // emits signal "showProgress"
546  QMetaObject::invokeMethod(walletmodel, "showProgress", Qt::QueuedConnection,
547  Q_ARG(QString, QString::fromStdString(title)),
548  Q_ARG(int, nProgress));
549 }
550 
551 static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly)
552 {
553  QMetaObject::invokeMethod(walletmodel, "updateWatchOnlyFlag", Qt::QueuedConnection,
554  Q_ARG(bool, fHaveWatchonly));
555 }
556 
558 {
559  // Connect signals to wallet
560  wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
561  wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
562  wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
563  wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
564  wallet->NotifyWatchonlyChanged.connect(boost::bind(NotifyWatchonlyChanged, this, _1));
565 }
566 
568 {
569  // Disconnect signals from wallet
570  wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
571  wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
572  wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
573  wallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
574  wallet->NotifyWatchonlyChanged.disconnect(boost::bind(NotifyWatchonlyChanged, this, _1));
575 }
576 
577 // WalletModel::UnlockContext implementation
579 {
580  EncryptionStatus encStatusOld = getEncryptionStatus();
581 
582  // Wallet was completely locked
583  bool was_locked = (encStatusOld == Locked);
584  // Wallet was unlocked for mixing
585  bool was_mixing = (encStatusOld == UnlockedForMixingOnly);
586  // Wallet was unlocked for mixing and now user requested to fully unlock it
587  bool fMixingToFullRequested = !fForMixingOnly && was_mixing;
588 
589  if(was_locked || fMixingToFullRequested) {
590  // Request UI to unlock wallet
591  Q_EMIT requireUnlock(fForMixingOnly);
592  }
593 
594  EncryptionStatus encStatusNew = getEncryptionStatus();
595 
596  // Wallet was locked, user requested to unlock it for mixing and failed to do so
597  bool fMixingUnlockFailed = fForMixingOnly && !(encStatusNew == UnlockedForMixingOnly);
598  // Wallet was unlocked for mixing, user requested to fully unlock it and failed
599  bool fMixingToFullFailed = fMixingToFullRequested && !(encStatusNew == Unlocked);
600  // If wallet is still locked, unlock failed or was cancelled, mark context as invalid
601  bool fInvalid = (encStatusNew == Locked) || fMixingUnlockFailed || fMixingToFullFailed;
602  // Wallet was not locked in any way or user tried to unlock it for mixing only and succeeded, keep it unlocked
603  bool fKeepUnlocked = !was_locked || (fForMixingOnly && !fMixingUnlockFailed);
604 
605  return UnlockContext(this, !fInvalid, !fKeepUnlocked, was_mixing);
606 }
607 
608 WalletModel::UnlockContext::UnlockContext(WalletModel *wallet, bool valid, bool was_locked, bool was_mixing):
609  wallet(wallet),
610  valid(valid),
611  was_locked(was_locked),
612  was_mixing(was_mixing)
613 {
614 }
615 
617 {
618  if(valid && (was_locked || was_mixing))
619  {
620  wallet->setWalletLocked(true, "", was_mixing);
621  }
622 }
623 
625 {
626  // Transfer context; old object no longer relocks wallet
627  *this = rhs;
628  rhs.was_locked = false;
629  rhs.was_mixing = false;
630 }
631 
632 bool WalletModel::getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
633 {
634  return wallet->GetPubKey(address, vchPubKeyOut);
635 }
636 
637 bool WalletModel::havePrivKey(const CKeyID &address) const
638 {
639  return wallet->HaveKey(address);
640 }
641 
642 // returns a list of COutputs from COutPoints
643 void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs)
644 {
645  LOCK2(cs_main, wallet->cs_wallet);
646  BOOST_FOREACH(const COutPoint& outpoint, vOutpoints)
647  {
648  if (!wallet->mapWallet.count(outpoint.hash)) continue;
649  int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain();
650  if (nDepth < 0) continue;
651  COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true, true);
652  vOutputs.push_back(out);
653  }
654 }
655 
656 bool WalletModel::isSpent(const COutPoint& outpoint) const
657 {
658  LOCK2(cs_main, wallet->cs_wallet);
659  return wallet->IsSpent(outpoint.hash, outpoint.n);
660 }
661 
662 // AvailableCoins + LockedCoins grouped by wallet address (put change in one group with wallet address)
663 void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins) const
664 {
665  std::vector<COutput> vCoins;
666  wallet->AvailableCoins(vCoins);
667 
668  LOCK2(cs_main, wallet->cs_wallet); // ListLockedCoins, mapWallet
669  std::vector<COutPoint> vLockedCoins;
670  wallet->ListLockedCoins(vLockedCoins);
671 
672  // add locked coins
673  BOOST_FOREACH(const COutPoint& outpoint, vLockedCoins)
674  {
675  if (!wallet->mapWallet.count(outpoint.hash)) continue;
676  int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain();
677  if (nDepth < 0) continue;
678  COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true, true);
679  if (outpoint.n < out.tx->vout.size() && wallet->IsMine(out.tx->vout[outpoint.n]) == ISMINE_SPENDABLE)
680  vCoins.push_back(out);
681  }
682 
683  BOOST_FOREACH(const COutput& out, vCoins)
684  {
685  COutput cout = out;
686 
687  while (wallet->IsChange(cout.tx->vout[cout.i]) && cout.tx->vin.size() > 0 && wallet->IsMine(cout.tx->vin[0]))
688  {
689  if (!wallet->mapWallet.count(cout.tx->vin[0].prevout.hash)) break;
690  cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0, true, true);
691  }
692 
693  CTxDestination address;
694  if(!out.fSpendable || !ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address))
695  continue;
696  mapCoins[QString::fromStdString(CBitcoinAddress(address).ToString())].push_back(out);
697  }
698 }
699 
700 bool WalletModel::isLockedCoin(uint256 hash, unsigned int n) const
701 {
702  LOCK2(cs_main, wallet->cs_wallet);
703  return wallet->IsLockedCoin(hash, n);
704 }
705 
707 {
708  LOCK2(cs_main, wallet->cs_wallet);
709  wallet->LockCoin(output);
710 }
711 
713 {
714  LOCK2(cs_main, wallet->cs_wallet);
715  wallet->UnlockCoin(output);
716 }
717 
718 void WalletModel::listLockedCoins(std::vector<COutPoint>& vOutpts)
719 {
720  LOCK2(cs_main, wallet->cs_wallet);
721  wallet->ListLockedCoins(vOutpts);
722 }
723 
724 void WalletModel::loadReceiveRequests(std::vector<std::string>& vReceiveRequests)
725 {
726  LOCK(wallet->cs_wallet);
727  BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, wallet->mapAddressBook)
728  BOOST_FOREACH(const PAIRTYPE(std::string, std::string)& item2, item.second.destdata)
729  if (item2.first.size() > 2 && item2.first.substr(0,2) == "rr") // receive request
730  vReceiveRequests.push_back(item2.second);
731 }
732 
733 bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest)
734 {
735  CTxDestination dest = CBitcoinAddress(sAddress).Get();
736 
737  std::stringstream ss;
738  ss << nId;
739  std::string key = "rr" + ss.str(); // "rr" prefix = "receive request" in destdata
740 
741  LOCK(wallet->cs_wallet);
742  if (sRequest.empty())
743  return wallet->EraseDestData(dest, key);
744  else
745  return wallet->AddDestData(dest, key, sRequest);
746 }
747 
749 {
750  LOCK2(cs_main, wallet->cs_wallet);
751  const CWalletTx *wtx = wallet->GetWalletTx(hash);
752  if (!wtx || wtx->isAbandoned() || wtx->GetDepthInMainChain() > 0 || wtx->InMempool())
753  return false;
754  return true;
755 }
756 
758 {
759  LOCK2(cs_main, wallet->cs_wallet);
760  return wallet->AbandonTransaction(hash);
761 }
762 
764 {
765  return wallet->IsHDEnabled();
766 }
void encryptionStatusChanged(int status)
CAmount cachedImmatureBalance
Definition: walletmodel.h:231
uint32_t n
Definition: transaction.h:19
bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString(), bool fMixing=false)
void updateStatus()
CAmount cachedWatchOnlyBalance
Definition: walletmodel.h:233
bool isAbandoned() const
Definition: wallet.h:267
CAmount cachedBalance
Definition: walletmodel.h:229
const CWalletTx * tx
Definition: wallet.h:485
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
Definition: standard.h:69
int nCompleteTXLocks
Definition: instantx.cpp:28
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Definition: standard.cpp:164
int cachedTxLocks
Definition: walletmodel.h:238
CAmount cachedWatchImmatureBalance
Definition: walletmodel.h:235
void unsubscribeFromCoreSignals()
#define TRY_LOCK(cs, name)
Definition: sync.h:170
void coinsSent(CWallet *wallet, SendCoinsRecipient recipient, QByteArray transaction)
bool IsValid() const
Definition: base58.cpp:247
void message(const QString &title, const QString &message, unsigned int style)
static const int SPORK_5_INSTANTSEND_MAX_VALUE
Definition: spork.h:24
void newPossibleKeyChange(CWallet *wallet)
void updateTransaction()
void reassignAmounts(int nChangePosRet)
static const CAmount COIN
Definition: amount.h:16
CAmount maxTxFee
Definition: wallet.cpp:46
static bool verifyExpired(const payments::PaymentDetails &requestDetails)
QList< SendCoinsRecipient > getRecipients()
CCriticalSection cs_main
Definition: validation.cpp:62
EncryptionStatus cachedEncryptionStatus
Definition: walletmodel.h:236
const ::payments::Output & outputs(int index) const
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:61
Definition: pubkey.h:27
const char * TX
Definition: protocol.cpp:24
EncryptionStatus getEncryptionStatus() const
UnlockContext(WalletModel *wallet, bool valid, bool was_locked, bool was_mixing)
void requireUnlock(bool fForMixingOnly=false)
StringMap destdata
Definition: wallet.h:170
CAmount GetValueOut() const
void updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status)
bool BackupWallet(const CWallet &wallet, const string &strDest)
Definition: walletdb.cpp:904
bool haveWatchOnly() const
TransactionTableModel * getTransactionTableModel()
CAmount cachedUnconfirmedBalance
Definition: walletmodel.h:230
bool fSubtractFeeFromAmount
Definition: walletmodel.h:63
CAmount getWatchImmatureBalance() const
CAmount cachedWatchUnconfBalance
Definition: walletmodel.h:234
CAmount getAnonymizedBalance() const
Definition: walletmodel.cpp:91
int64_t CAmount
Definition: amount.h:14
void unlockCoin(COutPoint &output)
void updateWatchOnlyFlag(bool fHaveWatchonly)
bool SerializeToString(std::string *output) const
#define LOCK2(cs1, cs2)
Definition: sync.h:169
RecentRequestsTableModel * recentRequestsTableModel
Definition: walletmodel.h:226
RecentRequestsTableModel * getRecentRequestsTableModel()
void loadReceiveRequests(std::vector< std::string > &vReceiveRequests)
SendCoinsReturn prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl=NULL)
ChangeType
Definition: ui_interface.h:21
SendCoinsReturn sendCoins(WalletModelTransaction &transaction)
bool havePrivKey(const CKeyID &address) const
void notifyWatchonlyChanged(bool fHaveWatchonly)
#define LOCK(cs)
Definition: sync.h:168
bool setWalletEncrypted(bool encrypted, const SecureString &passphrase)
CAmount cachedAnonymizedBalance
Definition: walletmodel.h:232
int Height() const
Definition: chain.h:397
int cachedNumBlocks
Definition: walletmodel.h:237
void listLockedCoins(std::vector< COutPoint > &vOutpts)
std::vector< std::pair< std::string, std::string > > vOrderForm
Definition: wallet.h:282
CChain chainActive
Definition: validation.cpp:65
OptionsModel * getOptionsModel()
bool getPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
CScript GetScriptForDestination(const CTxDestination &dest)
Definition: standard.cpp:262
void setTransactionFee(const CAmount &newFee)
CAmount getWatchUnconfirmedBalance() const
void subscribeToCoreSignals()
void updateEntry(const QString &address, const QString &label, bool isMine, const QString &purpose, int status)
Definition: wallet.py:1
void balanceChanged(const CAmount &balance, const CAmount &unconfirmedBalance, const CAmount &immatureBalance, const CAmount &anonymizedBalance, const CAmount &watchOnlyBalance, const CAmount &watchUnconfBalance, const CAmount &watchImmatureBalance)
bool validateAddress(const QString &address)
static const int MODEL_UPDATE_DELAY
Definition: guiconstants.h:10
void checkBalanceChanged()
void CopyFrom(const UnlockContext &rhs)
bool isSpent(const COutPoint &outpoint) const
PaymentRequestPlus paymentRequest
Definition: walletmodel.h:59
bool isLockedCoin(uint256 hash, unsigned int n) const
static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status)
CSporkManager sporkManager
Definition: spork.cpp:14
TransactionTableModel * transactionTableModel
Definition: walletmodel.h:225
CPrivateSendClient privateSendClient
const std::vector< CTxIn > vin
Definition: transaction.h:233
static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet, const uint256 &hash, ChangeType status)
const char * TXLOCKREQUEST
Definition: protocol.cpp:39
CTxDestination Get() const
Definition: base58.cpp:260
static vector< COutput > vCoins
void lockCoin(COutPoint &output)
bool fHaveWatchOnly
Definition: walletmodel.h:217
bool changePassphrase(const SecureString &oldPass, const SecureString &newPass)
bool saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest)
OptionsModel * optionsModel
Definition: walletmodel.h:222
static const int PROTOCOL_VERSION
Definition: version.h:13
AddressTableModel * addressTableModel
Definition: walletmodel.h:224
bool fForceCheckBalanceChanged
Definition: walletmodel.h:218
int i
Definition: wallet.h:486
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:103
const std::vector< CTxOut > vout
Definition: transaction.h:234
static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel, CCryptoKeyStore *wallet)
QTimer * pollTimer
Definition: walletmodel.h:241
Definition: pubkey.h:37
CAmount getUnconfirmedBalance() const
Definition: walletmodel.cpp:96
static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly)
static const int WARN_MANY_INPUTS
Definition: instantx.h:127
bool backupWallet(const QString &filename)
void pollBalanceChanged()
bool abandonTransaction(uint256 hash) const
CAmount getBalance(const CCoinControl *coinControl=NULL) const
Definition: walletmodel.cpp:73
CAmount getWatchBalance() const
size_type size() const
Definition: streams.h:122
int64_t GetSporkValue(int nSporkID)
Definition: spork.cpp:148
static void ShowProgress(WalletModel *walletmodel, const std::string &title, int nProgress)
int cachedPrivateSendRounds
Definition: walletmodel.h:239
bool transactionCanBeAbandoned(uint256 hash) const
CAmount getImmatureBalance() const
AddressTableModel * getAddressTableModel()
#define PAIRTYPE(t1, t2)
uint256 hash
Definition: transaction.h:18
int GetDepthInMainChain(const CBlockIndex *&pindexRet, bool enableIX=true) const
Definition: wallet.cpp:4416
bool hdEnabled() const
bool InMempool() const
Definition: wallet.cpp:2032
WalletModel(const PlatformStyle *platformStyle, CWallet *wallet, OptionsModel *optionsModel, QObject *parent=0)
Definition: walletmodel.cpp:37
UnlockContext requestUnlock(bool fForMixingOnly=false)
void getOutputs(const std::vector< COutPoint > &vOutpoints, std::vector< COutput > &vOutputs)
const payments::PaymentDetails & getDetails() const
void listCoins(std::map< QString, std::vector< COutput > > &mapCoins) const