Fabcoin Core  0.16.2
P2P Digital Currency
walletmodel.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2017 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <walletmodel.h>
6 
7 #include <addresstablemodel.h>
8 #include <consensus/validation.h>
9 #include <guiconstants.h>
10 #include <guiutil.h>
11 #include <optionsmodel.h>
12 #include <paymentserver.h>
14 #include <sendcoinsdialog.h>
15 #include <transactiontablemodel.h>
16 #include <tokenitemmodel.h>
18 #include <contracttablemodel.h>
19 
20 #include <base58.h>
21 #include <chain.h>
22 #include <keystore.h>
23 #include <validation.h>
24 #include <net.h> // for g_connman
25 #include <policy/fees.h>
26 #include <policy/rbf.h>
27 #include <sync.h>
28 #include <ui_interface.h>
29 #include <util.h> // for GetBoolArg
30 #include <wallet/coincontrol.h>
31 #include <wallet/feebumper.h>
32 #include <wallet/wallet.h>
33 #include <wallet/walletdb.h> // for BackupWallet
34 
35 #include <stdint.h>
36 
37 #include <QDebug>
38 #include <QMessageBox>
39 #include <QSet>
40 #include <QTimer>
41 #include <QFile>
42 #include <QSettings>
43 
44 
45 WalletModel::WalletModel(const PlatformStyle *platformStyle, CWallet *_wallet, OptionsModel *_optionsModel, QObject *parent) :
46  QObject(parent), wallet(_wallet), optionsModel(_optionsModel), addressTableModel(0),
47  contractTableModel(0),
48  transactionTableModel(0),
49  recentRequestsTableModel(0),
50  tokenItemModel(0),
51  tokenTransactionTableModel(0),
52  cachedBalance(0),
53  cachedUnconfirmedBalance(0),
54  cachedImmatureBalance(0),
55  cachedStake(0),
56  cachedWatchOnlyBalance(0),
57  cachedWatchUnconfBalance(0),
58  cachedWatchImmatureBalance(0),
59  cachedWatchOnlyStake(0),
60  cachedEncryptionStatus(Unencrypted),
61  cachedNumBlocks(0)
62 {
65 
68  transactionTableModel = new TransactionTableModel(platformStyle, wallet, this);
72 
73  // This timer will be fired repeatedly to update the balance
74  pollTimer = new QTimer(this);
75  connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollBalanceChanged()));
76  pollTimer->start(MODEL_UPDATE_DELAY);
77 
79 }
80 
82 {
84 }
85 
86 CAmount WalletModel::getBalance(const CCoinControl *coinControl) const
87 {
88  if (coinControl)
89  {
90  return wallet->GetAvailableBalance(coinControl);
91  }
92 
93  return wallet->GetBalance();
94 }
96 {
97  //return wallet->GetStake();
98  return 0;
99 }
100 
102 {
103  //return wallet->GetWatchOnlyStake();
104  return 0;
105 }
106 
108 {
109  return wallet->GetUnconfirmedBalance();
110 }
111 
113 {
114  return wallet->GetImmatureBalance();
115 }
116 
118 {
119  return fHaveWatchOnly;
120 }
121 
123 {
124  return wallet->GetWatchOnlyBalance();
125 }
126 
128 {
130 }
131 
133 {
135 }
136 
138 {
139  EncryptionStatus newEncryptionStatus = getEncryptionStatus();
140 
141  if(cachedEncryptionStatus != newEncryptionStatus)
142  Q_EMIT encryptionStatusChanged(newEncryptionStatus);
143 }
144 
146 {
147  // Get required locks upfront. This avoids the GUI from getting stuck on
148  // periodical polls if the core is holding the locks for a longer time -
149  // for example, during a wallet rescan.
150  TRY_LOCK(cs_main, lockMain);
151  if(!lockMain)
152  return;
153  TRY_LOCK(wallet->cs_wallet, lockWallet);
154  if(!lockWallet)
155  return;
156 
157  bool cachedNumBlocksChanged = chainActive.Height() != cachedNumBlocks;
158  if(fForceCheckBalanceChanged || cachedNumBlocksChanged)
159  {
161 
162  // Balance and number of transactions might have changed
164 
168 
171 
172  if(cachedNumBlocksChanged)
173  {
175  }
176  }
177 }
178 
179 void WalletModel::updateContractBook(const QString &address, const QString &label, const QString &abi, int status)
180 {
182  contractTableModel->updateEntry(address, label, abi, status);
183 }
184 
186 {
187  CAmount newBalance = getBalance();
188  CAmount newUnconfirmedBalance = getUnconfirmedBalance();
189  CAmount newImmatureBalance = getImmatureBalance();
190  CAmount newStake = getStake();
191  CAmount newWatchOnlyBalance = 0;
192  CAmount newWatchUnconfBalance = 0;
193  CAmount newWatchImmatureBalance = 0;
194  CAmount newWatchOnlyStake = 0;
195  if (haveWatchOnly())
196  {
197  newWatchOnlyBalance = getWatchBalance();
198  newWatchUnconfBalance = getWatchUnconfirmedBalance();
199  newWatchImmatureBalance = getWatchImmatureBalance();
200  newWatchOnlyStake = getWatchStake();
201  }
202 
203  if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance ||
204  cachedWatchOnlyBalance != newWatchOnlyBalance || cachedWatchUnconfBalance != newWatchUnconfBalance || cachedWatchImmatureBalance != newWatchImmatureBalance || cachedStake != newStake || cachedWatchOnlyStake != newWatchOnlyStake)
205  {
206  cachedBalance = newBalance;
207  cachedUnconfirmedBalance = newUnconfirmedBalance;
208  cachedImmatureBalance = newImmatureBalance;
209  cachedStake = newStake;
210  cachedWatchOnlyBalance = newWatchOnlyBalance;
211  cachedWatchUnconfBalance = newWatchUnconfBalance;
212  cachedWatchImmatureBalance = newWatchImmatureBalance;
213  cachedWatchOnlyStake = newWatchOnlyStake;
214  Q_EMIT balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance, newStake,
215  newWatchOnlyBalance, newWatchUnconfBalance, newWatchImmatureBalance, newWatchOnlyStake);
216  }
217 }
218 
220 {
221  if(tokenItemModel)
222  {
224  }
225 }
226 
228 {
229  // Balance and number of transactions might have changed
231 }
232 
233 void WalletModel::updateAddressBook(const QString &address, const QString &label,
234  bool isMine, const QString &purpose, int status)
235 {
237  addressTableModel->updateEntry(address, label, isMine, purpose, status);
238 }
239 
240 void WalletModel::updateWatchOnlyFlag(bool fHaveWatchonly)
241 {
242  fHaveWatchOnly = fHaveWatchonly;
243  Q_EMIT notifyWatchonlyChanged(fHaveWatchonly);
244 }
245 
247 {
248  CFabcoinAddress addressParsed(address.toStdString());
249  return addressParsed.IsValid();
250 }
251 
253 {
254  CAmount total = 0;
255  bool fSubtractFeeFromAmount = false;
256  QList<SendCoinsRecipient> recipients = transaction.getRecipients();
257  std::vector<CRecipient> vecSend;
258 
259  if(recipients.empty())
260  {
261  return OK;
262  }
263 
264  QSet<QString> setAddress; // Used to detect duplicates
265  int nAddresses = 0;
266 
267  // Pre-check input data for validity
268  for (const SendCoinsRecipient &rcp : recipients)
269  {
270  if (rcp.fSubtractFeeFromAmount)
271  fSubtractFeeFromAmount = true;
272 
273  if (rcp.paymentRequest.IsInitialized())
274  { // PaymentRequest...
275  CAmount subtotal = 0;
276  const payments::PaymentDetails& details = rcp.paymentRequest.getDetails();
277  for (int i = 0; i < details.outputs_size(); i++)
278  {
279  const payments::Output& out = details.outputs(i);
280  if (out.amount() <= 0) continue;
281  subtotal += out.amount();
282  const unsigned char* scriptStr = (const unsigned char*)out.script().data();
283  CScript scriptPubKey(scriptStr, scriptStr+out.script().size());
284  CAmount nAmount = out.amount();
285  CRecipient recipient = {scriptPubKey, nAmount, rcp.fSubtractFeeFromAmount};
286  vecSend.push_back(recipient);
287  }
288  if (subtotal <= 0)
289  {
290  return InvalidAmount;
291  }
292  total += subtotal;
293  }
294  else
295  { // User-entered fabcoin address / amount:
296  if(!validateAddress(rcp.address))
297  {
298  return InvalidAddress;
299  }
300  if(rcp.amount <= 0)
301  {
302  return InvalidAmount;
303  }
304  setAddress.insert(rcp.address);
305  ++nAddresses;
306 
307  CScript scriptPubKey = GetScriptForDestination(CFabcoinAddress(rcp.address.toStdString()).Get());
308  CRecipient recipient = {scriptPubKey, rcp.amount, rcp.fSubtractFeeFromAmount};
309  vecSend.push_back(recipient);
310 
311  total += rcp.amount;
312  }
313  }
314  if(setAddress.size() != nAddresses)
315  {
316  return DuplicateAddress;
317  }
318 
319  CAmount nBalance = getBalance(&coinControl);
320 
321  if(total > nBalance)
322  {
323  return AmountExceedsBalance;
324  }
325 
326  {
328 
329  transaction.newPossibleKeyChange(wallet);
330 
331  CAmount nFeeRequired = 0;
332  int nChangePosRet = -1;
333  std::string strFailReason;
334 
335  CWalletTx *newTx = transaction.getTransaction();
336  CReserveKey *keyChange = transaction.getPossibleKeyChange();
337  bool fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, nChangePosRet, strFailReason, coinControl);
338 
339  transaction.setTransactionFee(nFeeRequired);
340  if (fSubtractFeeFromAmount && fCreated)
341  transaction.reassignAmounts(nChangePosRet);
342 
343  if(!fCreated)
344  {
345  if(!fSubtractFeeFromAmount && (total + nFeeRequired) > nBalance)
346  {
348  }
349  Q_EMIT message(tr("Send Coins"), QString::fromStdString(strFailReason),
352  }
353 
354  // reject absurdly high fee. (This can never happen because the
355  // wallet caps the fee at maxTxFee. This merely serves as a
356  // belt-and-suspenders check)
357  if (nFeeRequired > maxTxFee)
358  return AbsurdFee;
359  }
360 
361  return SendCoinsReturn(OK);
362 }
363 
365 {
366  QByteArray transaction_array; /* store serialized transaction */
367 
368  {
370  CWalletTx *newTx = transaction.getTransaction();
371 
372  for (const SendCoinsRecipient &rcp : transaction.getRecipients())
373  {
374  if (rcp.paymentRequest.IsInitialized())
375  {
376  // Make sure any payment requests involved are still valid.
377  if (PaymentServer::verifyExpired(rcp.paymentRequest.getDetails())) {
378  return PaymentRequestExpired;
379  }
380 
381  // Store PaymentRequests in wtx.vOrderForm in wallet.
382  std::string key("PaymentRequest");
383  std::string value;
384  rcp.paymentRequest.SerializeToString(&value);
385  newTx->vOrderForm.push_back(make_pair(key, value));
386  }
387  else if (!rcp.message.isEmpty()) // Message from normal fabcoin:URI (fabcoin:123...?message=example)
388  newTx->vOrderForm.push_back(make_pair("Message", rcp.message.toStdString()));
389  }
390 
391  CReserveKey *keyChange = transaction.getPossibleKeyChange();
392  CValidationState state;
393  if(!wallet->CommitTransaction(*newTx, *keyChange, g_connman.get(), state))
394  return SendCoinsReturn(TransactionCommitFailed, QString::fromStdString(state.GetRejectReason()));
395 
396  CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
397  ssTx << *newTx->tx;
398  transaction_array.append(&(ssTx[0]), ssTx.size());
399  }
400 
401  // Add addresses / update labels that we've sent to the address book,
402  // and emit coinsSent signal for each recipient
403  for (const SendCoinsRecipient &rcp : transaction.getRecipients())
404  {
405  // Don't touch the address book when we have a payment request
406  if (!rcp.paymentRequest.IsInitialized())
407  {
408  std::string strAddress = rcp.address.toStdString();
409  CTxDestination dest = CFabcoinAddress(strAddress).Get();
410  std::string strLabel = rcp.label.toStdString();
411  {
413 
414  std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(dest);
415 
416  // Check if we have a new address or an updated label
417  if (mi == wallet->mapAddressBook.end())
418  {
419  wallet->SetAddressBook(dest, strLabel, "send");
420  }
421  else if (mi->second.name != strLabel)
422  {
423  wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose
424  }
425  }
426  }
427  Q_EMIT coinsSent(wallet, rcp, transaction_array);
428  }
429  checkBalanceChanged(); // update balance immediately, otherwise there could be a short noticeable delay until pollBalanceChanged hits
430 
431  return SendCoinsReturn(OK);
432 }
433 
435 {
436  return optionsModel;
437 }
438 
440 {
441  return addressTableModel;
442 }
443 
445 {
446  return contractTableModel;
447 }
448 
450 {
451  return transactionTableModel;
452 }
453 
455 {
457 }
458 
460 {
461  return tokenItemModel;
462 }
463 
465 {
467 }
468 
469 
471 {
472  if(!wallet->IsCrypted())
473  {
474  return Unencrypted;
475  }
476  else if(wallet->IsLocked())
477  {
478  return Locked;
479  }
480  else
481  {
482  return Unlocked;
483  }
484 }
485 
486 bool WalletModel::setWalletEncrypted(bool encrypted, const SecureString &passphrase)
487 {
488  if(encrypted)
489  {
490  // Encrypt
491  return wallet->EncryptWallet(passphrase);
492  }
493  else
494  {
495  // Decrypt -- TODO; not supported yet
496  return false;
497  }
498 }
499 
500 bool WalletModel::setWalletLocked(bool locked, const SecureString &passPhrase)
501 {
502  if(locked)
503  {
504  // Lock
505  return wallet->Lock();
506  }
507  else
508  {
509  // Unlock
510  return wallet->Unlock(passPhrase);
511  }
512 }
513 
514 bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureString &newPass)
515 {
516  bool retval;
517  {
519  wallet->Lock(); // Make sure wallet is locked before attempting pass change
520  retval = wallet->ChangeWalletPassphrase(oldPass, newPass);
521  }
522  return retval;
523 }
524 
525 bool WalletModel::backupWallet(const QString &filename)
526 {
527  bool ret = wallet->BackupWallet(filename.toLocal8Bit().data());
528 
529  // Set number of backups
530  QSettings settings;
531  int walletHasBackup = settings.value("walletBackupsNumber", 0).toInt();
532  settings.setValue("walletBackupsNumber", walletHasBackup + (ret ? 1 : 0));
533 
534  return ret;
535 }
536 
538 {
539  QSettings settings;
540  return settings.value("walletBackupsNumber", 0).toBool();
541 }
542 
543 bool WalletModel::restoreWallet(const QString &filename, const QString &param)
544 {
545  if(QFile::exists(filename))
546  {
547  fs::path pathWalletBak = GetDataDir() / strprintf("wallet.%d.bak", GetTime());
548  QString walletBak = QString::fromStdString(pathWalletBak.string());
549  if(backupWallet(walletBak))
550  {
551  restorePath = filename;
552  restoreParam = param;
553  return true;
554  }
555  }
556 
557  return false;
558 }
559 
560 
561 // Handlers for core signals
562 static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel, CCryptoKeyStore *wallet)
563 {
564  qDebug() << "NotifyKeyStoreStatusChanged";
565  QMetaObject::invokeMethod(walletmodel, "updateStatus", Qt::QueuedConnection);
566 }
567 
568 static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet,
569  const CTxDestination &address, const std::string &label, bool isMine,
570  const std::string &purpose, ChangeType status)
571 {
572  QString strAddress = QString::fromStdString(CFabcoinAddress(address).ToString());
573  QString strLabel = QString::fromStdString(label);
574  QString strPurpose = QString::fromStdString(purpose);
575 
576  qDebug() << "NotifyAddressBookChanged: " + strAddress + " " + strLabel + " isMine=" + QString::number(isMine) + " purpose=" + strPurpose + " status=" + QString::number(status);
577  QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection,
578  Q_ARG(QString, strAddress),
579  Q_ARG(QString, strLabel),
580  Q_ARG(bool, isMine),
581  Q_ARG(QString, strPurpose),
582  Q_ARG(int, status));
583 }
584 
585 static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet, const uint256 &hash, ChangeType status)
586 {
587  Q_UNUSED(wallet);
588  Q_UNUSED(hash);
589  Q_UNUSED(status);
590  QMetaObject::invokeMethod(walletmodel, "updateTransaction", Qt::QueuedConnection);
591 }
592 
593 static void ShowProgress(WalletModel *walletmodel, const std::string &title, int nProgress)
594 {
595  // emits signal "showProgress"
596  QMetaObject::invokeMethod(walletmodel, "showProgress", Qt::QueuedConnection,
597  Q_ARG(QString, QString::fromStdString(title)),
598  Q_ARG(int, nProgress));
599 }
600 
601 static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly)
602 {
603  QMetaObject::invokeMethod(walletmodel, "updateWatchOnlyFlag", Qt::QueuedConnection,
604  Q_ARG(bool, fHaveWatchonly));
605 }
606 
607 static void NotifyContractBookChanged(WalletModel *walletmodel, CWallet *wallet,
608  const std::string &address, const std::string &label, const std::string &abi, ChangeType status)
609 {
610  QString strAddress = QString::fromStdString(address);
611  QString strLabel = QString::fromStdString(label);
612  QString strAbi = QString::fromStdString(abi);
613 
614  qDebug() << "NotifyContractBookChanged: " + strAddress + " " + strLabel + " status=" + QString::number(status);
615  QMetaObject::invokeMethod(walletmodel, "updateContractBook", Qt::QueuedConnection,
616  Q_ARG(QString, strAddress),
617  Q_ARG(QString, strLabel),
618  Q_ARG(QString, strAbi),
619  Q_ARG(int, status));
620 }
621 
623 {
624  // Connect signals to wallet
625  wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
626  wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
627  wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
628  wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
629  wallet->NotifyWatchonlyChanged.connect(boost::bind(NotifyWatchonlyChanged, this, _1));
630  wallet->NotifyContractBookChanged.connect(boost::bind(NotifyContractBookChanged, this, _1, _2, _3, _4, _5));
631 }
632 
634 {
635  // Disconnect signals from wallet
636  wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
637  wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
638  wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
639  wallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
640  wallet->NotifyWatchonlyChanged.disconnect(boost::bind(NotifyWatchonlyChanged, this, _1));
641  wallet->NotifyContractBookChanged.disconnect(boost::bind(NotifyContractBookChanged, this, _1, _2, _3, _4, _5));
642 }
643 
644 // WalletModel::UnlockContext implementation
646 {
647  bool was_locked = getEncryptionStatus() == Locked;
648 
649  if ((!was_locked) && fWalletUnlockStakingOnly)
650  {
651  setWalletLocked(true);
652  was_locked = getEncryptionStatus() == Locked;
653  }
654 
655  if(was_locked)
656  {
657  // Request UI to unlock wallet
658  Q_EMIT requireUnlock();
659  }
660  // If wallet is still locked, unlock was failed or cancelled, mark context as invalid
661  bool valid = getEncryptionStatus() != Locked;
662 
663  return UnlockContext(this, valid, was_locked && !fWalletUnlockStakingOnly);
664 }
665 
666 WalletModel::UnlockContext::UnlockContext(WalletModel *_wallet, bool _valid, bool _relock):
667  wallet(_wallet),
668  valid(_valid),
669  relock(_relock),
670  stakingOnly(false)
671 {
672  if(!relock)
673  {
675  fWalletUnlockStakingOnly = false;
676  }
677 }
678 
680 {
681  if(valid && relock)
682  {
683  wallet->setWalletLocked(true);
684  }
685 
686  if(!relock)
687  {
689  wallet->updateStatus();
690  }
691 }
692 
694 {
695  // Transfer context; old object no longer relocks wallet
696  *this = rhs;
697  rhs.relock = false;
698 }
699 
700 bool WalletModel::getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
701 {
702  return wallet->GetPubKey(address, vchPubKeyOut);
703 }
704 
706 {
707  return IsMine(*wallet, dest) & ISMINE_SPENDABLE;
708 }
709 
710 bool WalletModel::getPrivKey(const CKeyID &address, CKey& vchPrivKeyOut) const
711 {
712  return wallet->GetKey(address, vchPrivKeyOut);
713 }
714 
715 // returns a list of COutputs from COutPoints
716 void WalletModel::getOutputs(const std::vector<COutPoint>& vOutpoints, std::vector<COutput>& vOutputs)
717 {
718  LOCK2(cs_main, wallet->cs_wallet);
719  for (const COutPoint& outpoint : vOutpoints)
720  {
721  if (!wallet->mapWallet.count(outpoint.hash)) continue;
722  int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain();
723  if (nDepth < 0) continue;
724  COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true /* spendable */, true /* solvable */, true /* safe */);
725  vOutputs.push_back(out);
726  }
727 }
728 
729 bool WalletModel::isSpent(const COutPoint& outpoint) const
730 {
731  LOCK2(cs_main, wallet->cs_wallet);
732  return wallet->IsSpent(outpoint.hash, outpoint.n);
733 }
734 
735 bool WalletModel::isUnspentAddress(const std::string &fabTokenAddress) const
736 {
737  LOCK2(cs_main, wallet->cs_wallet);
738 
739  std::vector<COutput> vecOutputs;
740  wallet->AvailableCoins(vecOutputs);
741  for (const COutput& out : vecOutputs)
742  {
744  const CScript& scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey;
745  bool fValidAddress = ExtractDestination(scriptPubKey, address);
746 
747  if(fValidAddress && CFabcoinAddress(address).ToString() == fabTokenAddress && out.tx->tx->vout[out.i].nValue)
748  {
749  return true;
750  }
751  }
752  return false;
753 }
754 
755 // AvailableCoins + LockedCoins grouped by wallet address (put change in one group with wallet address)
756 void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins) const
757 {
758  for (auto& group : wallet->ListCoins()) {
759  auto& resultGroup = mapCoins[QString::fromStdString(CFabcoinAddress(group.first).ToString())];
760  for (auto& coin : group.second) {
761  resultGroup.emplace_back(std::move(coin));
762  }
763  }
764 }
765 
766 bool WalletModel::isLockedCoin(uint256 hash, unsigned int n) const
767 {
768  LOCK2(cs_main, wallet->cs_wallet);
769  return wallet->IsLockedCoin(hash, n);
770 }
771 
773 {
774  LOCK2(cs_main, wallet->cs_wallet);
775  wallet->LockCoin(output);
776 }
777 
779 {
780  LOCK2(cs_main, wallet->cs_wallet);
781  wallet->UnlockCoin(output);
782 }
783 
784 void WalletModel::listLockedCoins(std::vector<COutPoint>& vOutpts)
785 {
786  LOCK2(cs_main, wallet->cs_wallet);
787  wallet->ListLockedCoins(vOutpts);
788 }
789 
790 void WalletModel::loadReceiveRequests(std::vector<std::string>& vReceiveRequests)
791 {
792  vReceiveRequests = wallet->GetDestValues("rr"); // receive request
793 }
794 
795 bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest)
796 {
797  CTxDestination dest = CFabcoinAddress(sAddress).Get();
798 
799  std::stringstream ss;
800  ss << nId;
801  std::string key = "rr" + ss.str(); // "rr" prefix = "receive request" in destdata
802 
803  LOCK(wallet->cs_wallet);
804  if (sRequest.empty())
805  return wallet->EraseDestData(dest, key);
806  else
807  return wallet->AddDestData(dest, key, sRequest);
808 }
809 
811 {
812  return wallet->TransactionCanBeAbandoned(hash);
813 }
814 
816 {
817  LOCK2(cs_main, wallet->cs_wallet);
818  return wallet->AbandonTransaction(hash);
819 }
820 
822 {
823  LOCK2(cs_main, wallet->cs_wallet);
824  const CWalletTx *wtx = wallet->GetWalletTx(hash);
825  return wtx && SignalsOptInRBF(*wtx) && !wtx->mapValue.count("replaced_by_txid");
826 }
827 
829 {
830  std::unique_ptr<CFeeBumper> feeBump;
831  {
832  CCoinControl coin_control;
833  coin_control.signalRbf = true;
834  LOCK2(cs_main, wallet->cs_wallet);
835  feeBump.reset(new CFeeBumper(wallet, hash, coin_control, 0));
836  }
837  if (feeBump->getResult() != BumpFeeResult::OK)
838  {
839  QMessageBox::critical(0, tr("Fee bump error"), tr("Increasing transaction fee failed") + "<br />(" +
840  (feeBump->getErrors().size() ? QString::fromStdString(feeBump->getErrors()[0]) : "") +")");
841  return false;
842  }
843 
844  // allow a user based fee verification
845  QString questionString = tr("Do you want to increase the fee?");
846  questionString.append("<br />");
847  CAmount oldFee = feeBump->getOldFee();
848  CAmount newFee = feeBump->getNewFee();
849  questionString.append("<table style=\"text-align: left;\">");
850  questionString.append("<tr><td>");
851  questionString.append(tr("Current fee:"));
852  questionString.append("</td><td>");
853  questionString.append(FabcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), oldFee));
854  questionString.append("</td></tr><tr><td>");
855  questionString.append(tr("Increase:"));
856  questionString.append("</td><td>");
857  questionString.append(FabcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), newFee - oldFee));
858  questionString.append("</td></tr><tr><td>");
859  questionString.append(tr("New fee:"));
860  questionString.append("</td><td>");
861  questionString.append(FabcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), newFee));
862  questionString.append("</td></tr></table>");
863  SendConfirmationDialog confirmationDialog(tr("Confirm fee bump"), questionString);
864  confirmationDialog.exec();
865  QMessageBox::StandardButton retval = (QMessageBox::StandardButton)confirmationDialog.result();
866 
867  // cancel sign&broadcast if users doesn't want to bump the fee
868  if (retval != QMessageBox::Yes) {
869  return false;
870  }
871 
873  if(!ctx.isValid())
874  {
875  return false;
876  }
877 
878  // sign bumped transaction
879  bool res = false;
880  {
881  LOCK2(cs_main, wallet->cs_wallet);
882  res = feeBump->signTransaction(wallet);
883  }
884  if (!res) {
885  QMessageBox::critical(0, tr("Fee bump error"), tr("Can't sign transaction."));
886  return false;
887  }
888  // commit the bumped transaction
889  {
890  LOCK2(cs_main, wallet->cs_wallet);
891  res = feeBump->commit(wallet);
892  }
893  if(!res) {
894  QMessageBox::critical(0, tr("Fee bump error"), tr("Could not commit transaction") + "<br />(" +
895  QString::fromStdString(feeBump->getErrors()[0])+")");
896  return false;
897  }
898  return true;
899 }
900 
902 {
903  return !gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET);
904 }
905 
907 {
908  return wallet->IsHDEnabled();
909 }
910 
912 {
913  return nTxConfirmTarget;
914 }
915 
917 {
918  return fWalletRbf;
919 }
920 
922 {
923  return wallet->AddTokenEntry(token, true);
924 }
925 
926 bool WalletModel::addTokenTxEntry(const CTokenTx& tokenTx, bool fFlushOnClose)
927 {
928  return wallet->AddTokenTxEntry(tokenTx, fFlushOnClose);
929 }
930 
932 {
933  LOCK2(cs_main, wallet->cs_wallet);
934 
935  uint256 hash = token.GetHash();
936  std::map<uint256, CTokenInfo>::iterator it = wallet->mapToken.find(hash);
937 
938  return it != wallet->mapToken.end();
939 }
940 
941 bool WalletModel::removeTokenEntry(const std::string &sHash)
942 {
943  return wallet->RemoveTokenEntry(uint256S(sHash), true);
944 }
945 
947 {
948  return restorePath;
949 }
950 
952 {
953  return restoreParam;
954 }
955 
956 std::vector<CTokenInfo> WalletModel::getInvalidTokens()
957 {
958  LOCK2(cs_main, wallet->cs_wallet);
959 
960  std::vector<CTokenInfo> listInvalid;
961  for(auto& info : wallet->mapToken)
962  {
963  std::string strAddress = info.second.strSenderAddress;
964  CFabcoinAddress address(strAddress);
965  if(!IsMine(*wallet, address.Get()))
966  {
967  listInvalid.push_back(info.second);
968  }
969  }
970 
971  return listInvalid;
972 }
973 
974 bool WalletModel::isMineAddress(const std::string &strAddress)
975 {
976  LOCK2(cs_main, wallet->cs_wallet);
977 
978  CFabcoinAddress address(strAddress);
979  if(!address.IsValid() || !IsMine(*wallet, address.Get()))
980  {
981  return false;
982  }
983  return true;
984 }
985 
uint256 GetHash() const
Definition: wallet.cpp:4543
void loadReceiveRequests(std::vector< std::string > &vReceiveRequests)
Model for list of recently generated payment requests / fabcoin: URIs.
TransactionTableModel * transactionTableModel
Definition: walletmodel.h:263
bool IsCrypted() const
Definition: crypter.h:140
void getOutputs(const std::vector< COutPoint > &vOutpoints, std::vector< COutput > &vOutputs)
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:79
bool IsHDEnabled() const
Definition: wallet.cpp:1500
RecentRequestsTableModel * recentRequestsTableModel
Definition: walletmodel.h:264
bool abandonTransaction(uint256 hash) const
void lockCoin(COutPoint &output)
void AvailableCoins(std::vector< COutput > &vCoins, bool fOnlySafe=true, const CCoinControl *coinControl=nullptr, const CAmount &nMinimumAmount=1, const CAmount &nMaximumAmount=MAX_MONEY, const CAmount &nMinimumSumAmount=MAX_MONEY, const uint64_t &nMaximumCount=0, const int &nMinDepth=0, const int &nMaxDepth=9999999) const
populate vCoins with vector of available COutputs.
Definition: wallet.cpp:2167
CAmount GetAvailableBalance(const CCoinControl *coinControl=nullptr) const
Definition: wallet.cpp:2152
#define TRY_LOCK(cs, name)
Definition: sync.h:177
static bool isWalletEnabled()
TokenTransactionTableModel * tokenTransactionTableModel
Definition: walletmodel.h:266
bool IsSpendable(const CTxDestination &dest) const
std::map< CTxDestination, CAddressBookData > mapAddressBook
Definition: wallet.h:826
CCriticalSection cs_wallet
Definition: wallet.h:748
#define strprintf
Definition: tinyformat.h:1054
CAmount maxTxFee
Absolute maximum transaction fee (in liu) used by wallet and mempool (rejects high fee in sendrawtran...
Definition: validation.cpp:104
UnlockContext requestUnlock()
void unsubscribeFromCoreSignals()
std::map< uint256, CTokenInfo > mapToken
Definition: wallet.h:834
bool bumpFee(uint256 hash)
bool isLockedCoin(uint256 hash, unsigned int n) const
CCriticalSection cs_main
Definition: validation.cpp:77
base58-encoded Fabcoin addresses.
Definition: base58.h:104
CAmount GetUnconfirmedBalance() const
Definition: wallet.cpp:2035
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:56
ContractTableModel * contractTableModel
Definition: walletmodel.h:262
bool backupWallet(const QString &filename)
void updateEntry(const QString &address, const QString &label, const QString &abi, int status)
bool GetBoolArg(const std::string &strArg, bool fDefault)
Return boolean argument or default value.
Definition: util.cpp:520
SendCoinsReturn sendCoins(WalletModelTransaction &transaction)
isminetype IsMine(const CKeyStore &keystore, const CScript &scriptPubKey, SigVersion sigversion)
Definition: ismine.cpp:29
bool IsLocked() const
Definition: crypter.h:145
void ListLockedCoins(std::vector< COutPoint > &vOutpts) const
Definition: wallet.cpp:3781
bool AddTokenEntry(const CTokenInfo &token, bool fFlushOnClose=true)
Definition: wallet.cpp:4372
bool isMineAddress(const std::string &strAddress)
bool existTokenEntry(const CTokenInfo &token)
ContractTableModel * getContractTableModel()
bool fSubtractFeeFromAmount
Definition: wallet.h:172
bool IsValid() const
Definition: base58.cpp:247
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:146
CAmount getUnconfirmedBalance() const
bool hasWalletBackup()
AddressTableModel * getAddressTableModel()
Keystore which keeps the private keys encrypted.
Definition: crypter.h:113
void balanceChanged(const CAmount &balance, const CAmount &unconfirmedBalance, const CAmount &immatureBalance, const CAmount &stake, const CAmount &watchOnlyBalance, const CAmount &watchUnconfBalance, const CAmount &watchImmatureBalance, const CAmount &watchOnlyStake)
bool EncryptWallet(const SecureString &strWalletPassphrase)
Definition: wallet.cpp:663
QString getRestoreParam()
bool getPrivKey(const CKeyID &address, CKey &vchPrivKeyOut) const
TokenTransactionTableModel * getTokenTransactionTableModel()
Coin Control Features.
Definition: coincontrol.h:16
const ::std::string & script() const
void updateStatus()
bool transactionCanBeAbandoned(uint256 hash) const
void newPossibleKeyChange(CWallet *wallet)
CAmount GetImmatureBalance() const
Definition: wallet.cpp:2050
bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const override
Definition: crypter.cpp:260
mapValue_t mapValue
Key/value map with information about the transaction.
Definition: wallet.h:318
void setTransactionFee(const CAmount &newFee)
bool CreateTransaction(const std::vector< CRecipient > &vecSend, CWalletTx &wtxNew, CReserveKey &reservekey, CAmount &nFeeRet, int &nChangePosInOut, std::string &strFailReason, const CCoinControl &coin_control, bool sign=true, CAmount nGasFee=0, bool hasSender=false)
Create a new transaction paying the recipients with a set of coins selected by SelectCoins(); Also cr...
Definition: wallet.cpp:2650
CAmount GetUnconfirmedWatchOnlyBalance() const
Definition: wallet.cpp:2080
UnlockContext(WalletModel *wallet, bool valid, bool relock)
QString restoreParam
Definition: walletmodel.h:283
int64_t CAmount
Amount in lius (Can be negative)
Definition: amount.h:15
QList< SendCoinsRecipient > getRecipients()
boost::signals2::signal< void(CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
Definition: wallet.h:1120
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
Definition: wallet.cpp:3258
boost::signals2::signal< void(CCryptoKeyStore *wallet)> NotifyStatusChanged
Wallet status (encrypted, locked) changed.
Definition: crypter.h:193
void checkBalanceChanged()
#define LOCK2(cs1, cs2)
Definition: sync.h:176
CAmount getWatchBalance() const
int Height() const
Return the maximal height in the chain.
Definition: chain.h:543
void push_back(const T &value)
Definition: prevector.h:411
unsigned int nTxConfirmTarget
Definition: wallet.cpp:44
CWallet * wallet
Definition: walletmodel.h:253
bool AbandonTransaction(const uint256 &hashTx)
Definition: wallet.cpp:1137
void UnlockCoin(const COutPoint &output)
Definition: wallet.cpp:3761
bool signalRbf
Signal BIP-125 replace by fee.
Definition: coincontrol.h:31
void updateTransaction()
CAmount cachedImmatureBalance
Definition: walletmodel.h:271
ChangeType
General change type (added, updated, removed).
Definition: ui_interface.h:19
bool isSpent(const COutPoint &outpoint) const
CTransactionRef tx
Definition: wallet.h:211
bool fWalletRbf
Definition: wallet.cpp:47
#define LOCK(cs)
Definition: sync.h:175
bool changePassphrase(const SecureString &oldPass, const SecureString &newPass)
size_type size() const
Definition: streams.h:237
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet, txnouttype *typeRet)
Definition: standard.cpp:268
void reassignAmounts(int nChangePosRet)
QString restorePath
Definition: walletmodel.h:282
bool TransactionCanBeAbandoned(const uint256 &hashTx) const
Return whether transaction can be abandoned.
Definition: wallet.cpp:1130
const ::payments::Output & outputs(int index) const
uint256 uint256S(const char *str)
Definition: uint256.h:153
An encapsulated public key.
Definition: pubkey.h:39
UI model for the transaction table of a wallet.
bool getPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
CAmount GetBalance() const
Definition: wallet.cpp:2019
uint32_t n
Definition: transaction.h:22
TokenItemModel * getTokenItemModel()
TokenItemModel * tokenItemModel
Definition: walletmodel.h:265
SendCoinsReturn prepareTransaction(WalletModelTransaction &transaction, const CCoinControl &coinControl)
static bool verifyExpired(const payments::PaymentDetails &requestDetails)
bool EraseDestData(const CTxDestination &dest, const std::string &key)
Erases a destination data tuple in the store and on disk.
Definition: wallet.cpp:3921
std::string ToString() const
Definition: base58.cpp:193
CAmount cachedBalance
Definition: walletmodel.h:269
bool GetKey(const CKeyID &address, CKey &keyOut) const override
Definition: crypter.cpp:242
OptionsModel * optionsModel
Definition: walletmodel.h:259
CAmount cachedWatchOnlyBalance
Definition: walletmodel.h:273
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:80
CScript GetScriptForDestination(const CTxDestination &dest)
Definition: standard.cpp:370
TransactionTableModel * getTransactionTableModel()
EncryptionStatus cachedEncryptionStatus
Definition: walletmodel.h:277
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:18
bool transactionCanBeBumped(uint256 hash) const
void CopyFrom(const UnlockContext &rhs)
bool restoreWallet(const QString &filename, const QString &param)
UI model for the transaction table of a wallet.
CTxDestination Get() const
Definition: base58.cpp:260
inline::google::protobuf::uint64 amount() const
std::vector< CTokenInfo > getInvalidTokens()
void LockCoin(const COutPoint &output)
Definition: wallet.cpp:3755
Qt model of the address book in the core.
CAmount getWatchImmatureBalance() const
bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString())
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:287
void encryptionStatusChanged(int status)
QTimer * pollTimer
Definition: walletmodel.h:280
EncryptionStatus getEncryptionStatus() const
std::map< CTxDestination, std::vector< COutput > > ListCoins() const
Return list of available coins and locked coins grouped by non-change output address.
Definition: wallet.cpp:2278
Qt model of the contract book in the core.
std::string GetRejectReason() const
Definition: validation.h:89
CAmount cachedStake
Definition: walletmodel.h:272
CAmount GetWatchOnlyBalance() const
Definition: wallet.cpp:2064
bool validateAddress(const QString &address)
WalletModel(const PlatformStyle *platformStyle, CWallet *wallet, OptionsModel *optionsModel, QObject *parent=0)
Definition: walletmodel.cpp:45
void updateWatchOnlyFlag(bool fHaveWatchonly)
CAmount cachedWatchOnlyStake
Definition: walletmodel.h:276
Capture information about block/transaction validation.
Definition: validation.h:27
256-bit opaque blob.
Definition: uint256.h:132
CAmount getStake() const
Definition: walletmodel.cpp:95
int cachedNumBlocks
Definition: walletmodel.h:278
bool isUnspentAddress(const std::string &address) const
CAmount cachedWatchUnconfBalance
Definition: walletmodel.h:274
ArgsManager gArgs
Definition: util.cpp:94
bool fForceCheckBalanceChanged
Definition: walletmodel.h:255
CAmount GetImmatureWatchOnlyBalance() const
Definition: wallet.cpp:2095
const CWalletTx * GetWalletTx(const uint256 &hash) const
Definition: wallet.cpp:139
CAmount cachedWatchImmatureBalance
Definition: walletmodel.h:275
RecentRequestsTableModel * getRecentRequestsTableModel()
boost::signals2::signal< void(CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status)> NotifyAddressBookChanged
Address book entry changed.
Definition: wallet.h:1113
bool ChangeWalletPassphrase(const SecureString &strOldWalletPassphrase, const SecureString &strNewWalletPassphrase)
Definition: wallet.cpp:400
void listLockedCoins(std::vector< COutPoint > &vOutpts)
A key allocated from the key pool.
Definition: wallet.h:1209
Interface from Qt to configuration data structure for Fabcoin client.
Definition: optionsmodel.h:22
boost::signals2::signal< void(CWallet *wallet, const std::string &address, const std::string &label, const std::string &abi, ChangeType status)> NotifyContractBookChanged
Contract book entry changed.
Definition: wallet.h:1142
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:417
Interface to Fabcoin wallet from Qt view code.
Definition: walletmodel.h:103
bool RemoveTokenEntry(const uint256 &tokenHash, bool fFlushOnClose=true)
Definition: wallet.cpp:4607
bool SignalsOptInRBF(const CTransaction &tx)
Definition: rbf.cpp:7
bool fWalletUnlockStakingOnly
Definition: wallet.cpp:328
CAmount getWatchStake() const
bool setWalletEncrypted(bool encrypted, const SecureString &passphrase)
void unlockCoin(COutPoint &output)
void message(const QString &title, const QString &message, unsigned int style)
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:29
CAmount cachedUnconfirmedBalance
Definition: walletmodel.h:270
bool haveWatchOnly() const
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
Definition: wallet.h:672
bool removeTokenEntry(const std::string &sHash)
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:75
void notifyWatchonlyChanged(bool fHaveWatchonly)
Data model for a walletmodel transaction.
void coinsSent(CWallet *wallet, SendCoinsRecipient recipient, QByteArray transaction)
std::map< uint256, CWalletTx > mapWallet
Definition: wallet.h:815
CAmount getImmatureBalance() const
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
Definition: wallet.h:1130
void checkTokenBalanceChanged()
AddressTableModel * addressTableModel
Definition: walletmodel.h:261
std::vector< std::string > GetDestValues(const std::string &prefix) const
Get all destination values matching a prefix.
Definition: wallet.cpp:3950
static QString formatHtmlWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=separatorStandard)
Format as HTML string (with unit)
const fs::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:623
bool IsLockedCoin(uint256 hash, unsigned int n) const
Definition: wallet.cpp:3773
int64_t GetTime()
GetTimeMicros() and GetTimeMillis() both return the system time, but in different units...
Definition: utiltime.cpp:19
struct evm_uint160be address(struct evm_env *env)
Definition: capi.c:13
An encapsulated private key.
Definition: key.h:35
void updateContractBook(const QString &address, const QString &label, const QString &abi, int status)
virtual bool HaveWatchOnly(const CScript &dest) const override
Definition: keystore.cpp:103
void checkTokenBalanceChanged()
bool AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
Adds a destination data tuple to the store, and saves it to disk.
Definition: wallet.cpp:3912
bool fHaveWatchOnly
Definition: walletmodel.h:254
bool getDefaultWalletRbf() const
void listCoins(std::map< QString, std::vector< COutput > > &mapCoins) const
bool IsSpent(const uint256 &hash, unsigned int n) const
Outpoint is spent if any non-conflicted transaction spends it:
Definition: wallet.cpp:623
bool BackupWallet(const std::string &strDest)
Definition: wallet.cpp:4351
bool saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest)
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
Definition: wallet.h:1133
bool addTokenEntry(const CTokenInfo &token)
CAmount getWatchUnconfirmedBalance() const
void updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status)
void updateEntry(const QString &address, const QString &label, bool isMine, const QString &purpose, int status)
bool addTokenTxEntry(const CTokenTx &tokenTx, bool fFlushOnClose=true)
bool AddTokenTxEntry(const CTokenTx &tokenTx, bool fFlushOnClose=true)
Definition: wallet.cpp:4421
int getDefaultConfirmTarget() const
void pollBalanceChanged()
CAmount getBalance(const CCoinControl *coinControl=nullptr) const
Definition: walletmodel.cpp:86
OptionsModel * getOptionsModel()
bool Unlock(const SecureString &strWalletPassphrase)
Definition: wallet.cpp:380
void subscribeToCoreSignals()
QString getRestorePath()
std::vector< std::pair< std::string, std::string > > vOrderForm
Definition: wallet.h:319
uint256 hash
Definition: transaction.h:21
bool hdEnabled() const
bool CommitTransaction(CWalletTx &wtxNew, CReserveKey &reservekey, CConnman *connman, CValidationState &state)
Call after CreateTransaction unless you want to abort.
Definition: wallet.cpp:3045