PIVX Core  5.6.99
P2P Digital Currency
walletmodel.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2014 The Bitcoin developers
2 // Copyright (c) 2014-2015 The Dash developers
3 // Copyright (c) 2015-2021 The PIVX Core developers
4 // Distributed under the MIT/X11 software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 
7 #include "walletmodel.h"
8 
10 #include "interfaces/handler.h"
11 #include "sapling/key_io_sapling.h"
14 #include "shutdown.h"
15 #include "spork.h"
16 #include "wallet/fees.h"
17 
18 #include "qt/addresstablemodel.h"
19 #include "qt/clientmodel.h"
20 #include "qt/guiconstants.h"
21 #include "qt/optionsmodel.h"
24 
25 #include <stdint.h>
26 #include <iostream>
27 
28 #include <QtConcurrent/QtConcurrent>
29 #include <QSet>
30 #include <QTimer>
31 #include <utility>
32 
33 // Util function
34 template <typename T>
35 static std::string toHexStr(const T& obj)
36 {
37  CDataStream ss(SER_DISK, CLIENT_VERSION);
38  ss << obj;
39  return HexStr(ss);
40 }
41 
42 WalletModel::WalletModel(CWallet* wallet, OptionsModel* optionsModel, QObject* parent) : QObject(parent), wallet(wallet), walletWrapper(*wallet),
43  optionsModel(optionsModel),
44  cachedEncryptionStatus(Unencrypted),
45  cachedNumBlocks(0)
46 {
49 
52 }
53 
55 {
57  // This timer will be fired repeatedly to update the balance
58  pollTimer = new QTimer(this);
59  connect(pollTimer, &QTimer::timeout, this, &WalletModel::pollBalanceChanged);
60  pollTimer->start(MODEL_UPDATE_DELAY * 5);
62 }
63 
65 {
67 }
68 
70 {
72  setWalletCustomFee(false, DEFAULT_TRANSACTION_FEE);
74 }
75 
77 {
78  return Params().IsTestnet();
79 }
80 
82 {
83  return Params().IsRegTestNet();
84 }
85 
87 {
88  return ShutdownRequested();
89 }
90 
92 {
94 }
95 
97 {
99 }
100 
102 {
104 }
105 
107 {
109 }
110 
112 {
113  return wallet->IsHDEnabled();
114 }
115 
117 {
119 }
120 
121 bool WalletModel::upgradeWallet(std::string& upgradeError)
122 {
123  // This action must be performed in a separate thread and not the main one.
125 
126  // Get version
127  int prev_version = wallet->GetVersion();
128  // Upgrade wallet's version
131 
132  // Upgrade to HD
133  return wallet->Upgrade(upgradeError, prev_version);
134 }
135 
137 {
138  return QString::fromStdString(wallet->GetPathToDBFile().string());
139 }
140 
141 CAmount WalletModel::getBalance(const CCoinControl* coinControl, bool fIncludeDelegated, bool fUnlockedOnly, bool fIncludeShielded) const
142 {
143  if (coinControl) {
144  CAmount nBalance = 0;
145  CWallet::AvailableCoinsFilter coinsFilter;
146  coinsFilter.fIncludeDelegated = fIncludeDelegated;
147  std::vector<COutput> vCoins;
148  wallet->AvailableCoins(&vCoins, coinControl, coinsFilter);
149  for (const COutput& out : vCoins) {
150  bool fSkip = fUnlockedOnly && isLockedCoin(out.tx->GetHash(), out.i);
151  if (out.fSpendable && !fSkip)
152  nBalance += out.tx->tx->vout[out.i].nValue;
153  }
154 
155  return nBalance;
156  }
157 
158  return wallet->GetAvailableBalance(fIncludeDelegated, fIncludeShielded) - (fUnlockedOnly ? wallet->GetLockedCoins() : CAmount(0));
159 }
160 
161 CAmount WalletModel::getUnlockedBalance(const CCoinControl* coinControl, bool fIncludeDelegated, bool fIncludeShielded) const
162 {
163  return getBalance(coinControl, fIncludeDelegated, true, fIncludeShielded);
164 }
165 
167 {
168  return MIN_COLDSTAKING_AMOUNT;
169 }
170 
171 CAmount WalletModel::getLockedBalance(bool isTransparent) const
172 {
173  return isTransparent ? wallet->GetLockedCoins() : wallet->GetLockedShieldCoins();
174 }
175 
177 {
178  return fHaveWatchOnly;
179 }
180 
182 {
183  return wallet->GetDelegatedBalance();
184 }
185 
187 {
188  // TODO: Complete me..
189  return false;
190 }
191 
192 void WalletModel::getAvailableP2CSCoins(std::vector<COutput>& vCoins) const
193 {
194  return wallet->GetAvailableP2CSCoins(vCoins);
195 }
196 
198 {
199  if (!wallet) return;
200  EncryptionStatus newEncryptionStatus = getEncryptionStatus();
201 
202  if (cachedEncryptionStatus != newEncryptionStatus)
203  Q_EMIT encryptionStatusChanged(newEncryptionStatus);
204 }
205 
207 {
208  if (!wallet) return false;
210  return (status == Unencrypted || status == Unlocked);
211 }
212 
213 bool WalletModel::isWalletLocked(bool fFullUnlocked) const
214 {
215  if (!wallet) return false;
217  return (status == Locked || (!fFullUnlocked && status == UnlockedForStaking));
218 }
219 
220 static bool IsImportingOrReindexing()
221 {
222  return fImporting || fReindex;
223 }
224 
225 std::atomic<bool> processingBalance{false};
226 
228 {
229  int chainHeight = getLastBlockProcessedNum();
230  const uint256& blockHash = getLastBlockProcessed();
231 
232  // Avoid recomputing wallet balances unless a tx changed or BlockTip notification was received.
233  // Extra note: This needs to be done before and after the update task trigger and execution because, as it runs concurrently,
234  // there is no guarantee that the threadpool will execute the task right away.
235  if (!fForceCheckBalanceChanged && m_cached_best_block_hash == blockHash) return false;
236 
237  // Try to get lock only if needed
238  TRY_LOCK(wallet->cs_wallet, lockWallet);
239  if (!lockWallet) return false;
240 
242 
243  // Balance and number of transactions might have changed
244  setCacheNumBlocks(chainHeight);
245  setCacheBlockHash(blockHash);
247  QMetaObject::invokeMethod(this, "updateTxModelData", Qt::QueuedConnection);
248  QMetaObject::invokeMethod(this, "pollFinished", Qt::QueuedConnection);
249 
250  // Address in receive tab may have been used
252  return true;
253 }
254 
255 static void processBalanceChange(WalletModel* walletModel)
256 {
257  if (!walletModel || !walletModel->processBalanceChangeInternal()) {
258  processingBalance = false;
259  }
260 }
261 
263 {
264  if (processingBalance || !m_client_model) return;
265 
266  // Wait a little bit more when the wallet is reindexing and/or importing, no need to lock cs_main so often.
267  if (IsImportingOrReindexing() || m_client_model->inInitialBlockDownload()) {
268  static uint8_t waitLonger = 0;
269  waitLonger++;
270  if (waitLonger < 6) // 30 seconds
271  return;
272  waitLonger = 0;
273  }
274 
275  // Don't continue processing if the chain tip time is less than the first
276  // key creation time as there is no need to iterate over the transaction
277  // table model in this case.
278  int64_t blockTime = clientModel().getLastBlockProcessedTime();
279  if (blockTime < getCreationTime())
280  return;
281 
282  // Avoid recomputing wallet balances unless a tx changed or
283  // BlockTip notification was received.
285 
286  processingBalance = true;
287  pollFuture = QtConcurrent::run(processBalanceChange, this);
288 }
289 
291 {
292  if (transactionTableModel) {
294  }
295 }
296 
298 {
299  // Force update of UI elements even when no values have changed
300  Q_EMIT balanceChanged(getBalances());
301 }
302 
304 {
305  if (newBalance.balanceChanged(m_cached_balances)) {
306  m_cached_balances = newBalance;
307  QMetaObject::invokeMethod(this, "balanceNotify", Qt::QueuedConnection);
308  }
309 }
310 
312 {
314 }
315 
317 {
318  processingBalance = false;
319 }
320 
322 {
323  if (pollFuture.isRunning()) {
324  pollFuture.cancel();
325  pollFuture.setPaused(true);
326  }
327 }
328 
330 {
331  payTxFee = CFeeRate(fee);
332 }
333 
335 {
337  return wallet->fUseCustomFee;
338 }
339 
341 {
343  nFeeRet = wallet->nCustomFee;
344  return wallet->fUseCustomFee;
345 }
346 
347 void WalletModel::setWalletCustomFee(bool fUseCustomFee, const CAmount nFee)
348 {
351  if (wallet->fUseCustomFee != fUseCustomFee) {
352  wallet->fUseCustomFee = fUseCustomFee;
353  db.WriteUseCustomFee(fUseCustomFee);
354  }
355  if (wallet->nCustomFee != nFee) {
356  wallet->nCustomFee = nFee;
357  db.WriteCustomFeeValue(nFee);
358  }
359 }
360 
361 void WalletModel::setWalletStakeSplitThreshold(const CAmount nStakeSplitThreshold)
362 {
363  wallet->SetStakeSplitThreshold(nStakeSplitThreshold);
364 }
365 
367 {
368  return wallet->GetStakeSplitThreshold();
369 }
370 
371 /* returns default minimum value for stake split threshold as double */
373 {
374  return static_cast<double>(CWallet::minStakeSplitThreshold) / COIN;
375 }
376 
378 {
379  // Balance and number of transactions might have changed
381 }
382 
383 void WalletModel::updateAddressBook(const QString& address, const QString& label, bool isMine, const QString& purpose, int status)
384 {
385  try {
386  if (addressTableModel)
387  addressTableModel->updateEntry(address, label, isMine, purpose, status);
388  } catch (...) {
389  std::cout << "Exception updateAddressBook" << std::endl;
390  }
391 }
392 
393 void WalletModel::updateWatchOnlyFlag(bool fHaveWatchonly)
394 {
395  fHaveWatchOnly = fHaveWatchonly;
396  Q_EMIT notifyWatchonlyChanged(fHaveWatchonly);
397 }
398 
399 bool WalletModel::validateAddress(const QString& address)
400 {
401  // Only regular base58 addresses and shielded addresses accepted here
402  bool isStaking = false, isExchange = false;
403  CWDestination dest = Standard::DecodeDestination(address.toStdString(), isStaking, isExchange);
404  const auto regDest = boost::get<CTxDestination>(&dest);
405  if (regDest && IsValidDestination(*regDest) && isStaking) return false;
406  return Standard::IsValidDestination(dest);
407 }
408 
409 bool WalletModel::validateAddress(const QString& address, bool fStaking)
410 {
411  return IsValidDestinationString(address.toStdString(), fStaking);
412 }
413 
414 bool WalletModel::validateAddress(const QString& address, bool fStaking, bool& isShielded)
415 {
416  bool isStaking = false, isExchange = false;
417  CWDestination dest = Standard::DecodeDestination(address.toStdString(), isStaking, isExchange);
418  if (IsShieldedDestination(dest)) {
419  isShielded = true;
420  return true;
421  }
422  return Standard::IsValidDestination(dest) && (isStaking == fStaking);
423 }
424 
425 bool WalletModel::updateAddressBookLabels(const CWDestination& dest, const std::string& strName, const std::string& strPurpose)
426 {
427  auto optAdd = wallet->GetAddressBookEntry(dest);
428  // Check if we have a new address or an updated label
429  if (!optAdd) {
430  return wallet->SetAddressBook(dest, strName, strPurpose);
431  } else if (optAdd->name != strName) {
432  return wallet->SetAddressBook(dest, strName, ""); // "" means don't change purpose
433  }
434  return false;
435 }
436 
437 bool WalletModel::addKeys(const CKey& key, const CPubKey& pubkey, WalletRescanReserver& reserver)
438 {
439  {
441  wallet->mapKeyMetadata[pubkey.GetID()].nCreateTime = 1;
442 
443  if (!wallet->AddKeyPubKey(key, pubkey)) {
444  return false;
445  }
446 
447  // whenever a key is imported, we need to scan the whole chain
448  wallet->nTimeFirstKey = 1; // 0 would be considered 'no value'
449  }
450  CBlockIndex* pindexGenesis = WITH_LOCK(cs_main, return chainActive.Genesis(); );
451  wallet->ScanForWalletTransactions(pindexGenesis, nullptr, reserver, true);
452  return true;
453 }
454 
455 WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction* transaction, const CCoinControl* coinControl, bool fIncludeDelegations)
456 {
457  CAmount total = 0;
458  QList<SendCoinsRecipient> recipients = transaction->getRecipients();
459  std::vector<CRecipient> vecSend;
460 
461  if (recipients.empty()) {
462  return OK;
463  }
464 
465  if (isStakingOnlyUnlocked()) {
466  return StakingOnlyUnlocked;
467  }
468 
469  QSet<QString> setAddress; // Used to detect duplicates
470  int nAddresses = 0;
471 
472  // Pre-check input data for validity
473  for (const SendCoinsRecipient& rcp : recipients) {
474  { // User-entered pivx address / amount:
475  if (!validateAddress(rcp.address, rcp.isP2CS)) {
476  return InvalidAddress;
477  }
478  if (rcp.amount <= 0) {
479  return InvalidAmount;
480  }
481  setAddress.insert(rcp.address);
482  ++nAddresses;
483 
484  CScript scriptPubKey;
485  CTxDestination out = DecodeDestination(rcp.address.toStdString());
486 
487  if (rcp.isP2CS) {
488  Destination ownerAdd;
489  if (rcp.ownerAddress.isEmpty()) {
490  // Create new internal owner address
491  auto res = getNewAddress();
492  if (!res) return CannotCreateInternalAddress;
493  ownerAdd = *res.getObjResult();
494  } else {
495  ownerAdd = Destination(DecodeDestination(rcp.ownerAddress.toStdString()), false, false);
496  }
497 
498  const CKeyID* stakerId = boost::get<CKeyID>(&out);
499  const CKeyID* ownerId = ownerAdd.getKeyID();
500  if (!stakerId || !ownerId) {
501  return InvalidAddress;
502  }
503 
504  scriptPubKey = isV6Enforced() ? GetScriptForStakeDelegation(*stakerId, *ownerId)
505  : GetScriptForStakeDelegationLOF(*stakerId, *ownerId);
506  } else {
507  // Regular P2PK or P2PKH
508  scriptPubKey = GetScriptForDestination(out);
509  }
510  vecSend.emplace_back(scriptPubKey, rcp.amount, rcp.fSubtractFee);
511 
512  total += rcp.amount;
513  }
514  }
515  if (setAddress.size() != nAddresses) {
516  return DuplicateAddress;
517  }
518 
519  CAmount nSpendableBalance = getUnlockedBalance(coinControl, fIncludeDelegations);
520 
521  if (total > nSpendableBalance) {
522  return AmountExceedsBalance;
523  }
524 
525  {
527 
528  CReserveKey* keyChange = transaction->newPossibleKeyChange(wallet);
529  CAmount nFeeRequired = 0;
530  int nChangePosInOut = -1;
531  std::string strFailReason;
532 
533  bool fCreated = wallet->CreateTransaction(vecSend,
534  transaction->getTransaction(),
535  *keyChange,
536  nFeeRequired,
537  nChangePosInOut,
538  strFailReason,
539  coinControl,
540  true,
541  0,
542  fIncludeDelegations,
543  &transaction->fIsStakeDelegationVoided);
544  transaction->setTransactionFee(nFeeRequired);
545 
546  if (!fCreated) {
547  if ((total + nFeeRequired) > nSpendableBalance) {
549  }
550 
551  Q_EMIT message(tr("Send Coins"), tr("Transaction creation failed!\n%1").arg(
552  strFailReason == "Transaction too large" ?
553  tr("The size of the transaction is too big.\nSelect fewer inputs with coin control.") :
554  QString::fromStdString(strFailReason)),
557  }
558 
559  // reject insane fee
560  if (nFeeRequired > ::minRelayTxFee.GetFee(transaction->getTransactionSize()) * 10000)
561  return InsaneFee;
562  }
563 
564  return SendCoinsReturn(OK);
565 }
566 
568 {
569  bool fColdStakingActive = isColdStakingNetworkelyEnabled();
570 
571  // Double check the tx before doing anything
572  CTransactionRef& newTx = transaction.getTransaction();
573  CValidationState state;
574  if (!CheckTransaction(*newTx, state, fColdStakingActive)) {
575  return TransactionCheckFailed;
576  }
577 
578  QByteArray transaction_array; /* store serialized transaction */
579 
580  {
582 
583  CReserveKey* keyChange = transaction.getPossibleKeyChange();
584  const CWallet::CommitResult& res = wallet->CommitTransaction(newTx, keyChange, g_connman.get());
585  if (res.status != CWallet::CommitStatus::OK) {
586  return SendCoinsReturn(res);
587  }
588 
589  CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
590  ssTx << *newTx;
591  transaction_array.append(&(ssTx[0]), ssTx.size());
592  }
593 
594  // Add addresses / update labels that we've sent to to the address book,
595  // and emit coinsSent signal for each recipient
596  for (const SendCoinsRecipient& rcp : transaction.getRecipients()) {
597  // Don't touch the address book when we have a payment request
598  {
599  bool isStaking = false, isExchange = false, isShielded = false;
600  auto address = Standard::DecodeDestination(rcp.address.toStdString(), isStaking, isExchange, isShielded);
601  std::string purpose = isShielded ? AddressBook::AddressBookPurpose::SHIELDED_SEND :
603  std::string strLabel = rcp.label.toStdString();
604  updateAddressBookLabels(address, strLabel, purpose);
605  }
606  Q_EMIT coinsSent(wallet, rcp, transaction_array);
607  }
608  emitBalanceChanged(); // update balance immediately, otherwise there could be a short noticeable delay until pollBalanceChanged hits
609 
610  return SendCoinsReturn(OK);
611 }
612 
614  bool fromTransparent,
615  const CCoinControl* coinControl)
616 {
617  // Load shieldedAddrRecipients.
618  std::vector<SendManyRecipient> recipients;
619  for (const auto& recipient : modelTransaction->getRecipients()) {
620  bool fSubtractFeeFromAmount = recipient.fSubtractFee;
621  if (recipient.isShieldedAddr) {
622  auto pa = KeyIO::DecodeSaplingPaymentAddress(recipient.address.toStdString());
623  if (!pa) return errorOut("Error, invalid shielded address");
624  recipients.emplace_back(*pa, recipient.amount, recipient.message.toStdString(), fSubtractFeeFromAmount);
625  } else {
626  auto dest = DecodeDestination(recipient.address.toStdString());
627  if (!IsValidDestination(dest)) return errorOut("Error, invalid transparent address");
628  recipients.emplace_back(dest, recipient.amount, fSubtractFeeFromAmount);
629  }
630  }
631 
632  // Now check the transaction size
633  auto opResult = CheckTransactionSize(recipients, true);
634  if (!opResult) return opResult;
635 
636  // Create the operation
637  SaplingOperation operation(Params().GetConsensus(), wallet);
638  auto operationResult = operation.setRecipients(recipients)
639  ->setTransparentKeyChange(modelTransaction->getPossibleKeyChange())
640  ->setSelectTransparentCoins(fromTransparent)
641  ->setSelectShieldedCoins(!fromTransparent)
642  ->setCoinControl(coinControl)
643  ->setMinDepth(fromTransparent ? 1 : 5)
644  ->build();
645 
646  if (!operationResult) {
647  return operationResult;
648  }
649 
650  // load the transaction and key change (if needed)
651  CTransactionRef& txRef = modelTransaction->getTransaction();
652  txRef = MakeTransactionRef(operation.getFinalTx());
653  modelTransaction->setTransactionFee(operation.getFee()); // in the future, fee will be dynamically calculated.
654  return operationResult;
655 }
656 
658 {
659  CTransactionRef wtx;
660  const uint256& nHash = proposal.GetHash();
661  CReserveKey keyChange(wallet);
662  if (!wallet->CreateBudgetFeeTX(wtx, nHash, keyChange, BUDGET_FEE_TX_OLD)) { // 50 PIV collateral for proposal
663  return {false , "Error making fee transaction for proposal. Please check your wallet balance."};
664  }
665 
666  // send the tx to the network
667  mapValue_t extraValues;
668  extraValues.emplace("proposal", toHexStr(proposal));
669  const CWallet::CommitResult& res = wallet->CommitTransaction(wtx, &keyChange, g_connman.get(), &extraValues);
670  if (res.status != CWallet::CommitStatus::OK) {
671  return {false, strprintf("Cannot commit proposal fee transaction: %s", res.ToString())};
672  }
673  // Everything went fine, set the fee tx hash
674  proposal.SetFeeTxHash(wtx->GetHash());
675  return {true};
676 }
677 
679 {
680  return wallet->GetWalletTx(id);
681 }
682 
684 {
685  return optionsModel;
686 }
687 
689 {
690  return addressTableModel;
691 }
692 
694 {
695  return transactionTableModel;
696 }
697 
699 {
700  if (!wallet) throw std::runtime_error("Error, cannot get encryption status. Wallet doesn't exist");
701  if (!wallet->IsCrypted()) {
702  return Unencrypted;
703  } else if (wallet->fWalletUnlockStaking) {
704  return UnlockedForStaking;
705  } else if (wallet->IsLocked()) {
706  return Locked;
707  } else {
708  return Unlocked;
709  }
710 
711 }
712 
713 bool WalletModel::setWalletEncrypted(bool encrypted, const SecureString& passphrase)
714 {
715  if (encrypted) {
716  // Encrypt
717  return wallet->EncryptWallet(passphrase);
718  } else {
719  // Decrypt -- TODO; not supported yet
720  return false;
721  }
722 }
723 
724 bool WalletModel::setWalletLocked(bool locked, const SecureString& passPhrase, bool stakingOnly)
725 {
726  if (locked) {
727  // Lock
728  wallet->fWalletUnlockStaking = false;
729  return wallet->Lock();
730  } else {
731  // Unlock
732  return wallet->Unlock(passPhrase, stakingOnly);
733  }
734 }
735 
737 {
738  if (!wallet->IsLocked()) {
740  return true;
741  } else {
742  setWalletLocked(false, passPhrase, true);
743  }
744  return false;
745 }
746 
748 {
750 }
751 
752 bool WalletModel::changePassphrase(const SecureString& oldPass, const SecureString& newPass)
753 {
754  bool retval;
755  {
757  wallet->Lock(); // Make sure wallet is locked before attempting pass change
758  retval = wallet->ChangeWalletPassphrase(oldPass, newPass);
759  }
760  return retval;
761 }
762 
763 bool WalletModel::backupWallet(const QString& filename)
764 {
765  // Attempt regular backup
766  if (!wallet->BackupWallet(filename.toLocal8Bit().data())) {
767  return error("ERROR: Failed to backup wallet!");
768  }
769 
770  return true;
771 }
772 
773 
774 // Handlers for core signals
775 static void NotifyKeyStoreStatusChanged(WalletModel* walletmodel)
776 {
777  qDebug() << "NotifyKeyStoreStatusChanged";
778  QMetaObject::invokeMethod(walletmodel, "updateStatus", Qt::QueuedConnection);
779 }
780 
781 static void NotifyAddressBookChanged(WalletModel* walletmodel, CWallet* wallet, const CWDestination& address, const std::string& label, bool isMine, const std::string& purpose, ChangeType status)
782 {
783  QString strAddress = QString::fromStdString(wallet->ParseIntoAddress(address, purpose));
784  QString strLabel = QString::fromStdString(label);
785  QString strPurpose = QString::fromStdString(purpose);
786 
787  qDebug() << "NotifyAddressBookChanged : " + strAddress + " " + strLabel + " isMine=" + QString::number(isMine) + " purpose=" + strPurpose + " status=" + QString::number(status);
788  QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection,
789  Q_ARG(QString, strAddress),
790  Q_ARG(QString, strLabel),
791  Q_ARG(bool, isMine),
792  Q_ARG(QString, strPurpose),
793  Q_ARG(int, status));
794 }
795 
796 // queue notifications to show a non freezing progress dialog e.g. for rescan
797 static bool fQueueNotifications = false;
798 static std::vector<std::pair<uint256, ChangeType> > vQueueNotifications;
799 static void NotifyTransactionChanged(WalletModel* walletmodel, CWallet* wallet, const uint256& hash, ChangeType status)
800 {
801  if (fQueueNotifications) {
802  vQueueNotifications.emplace_back(hash, status);
803  return;
804  }
805 
806  QString strHash = QString::fromStdString(hash.GetHex());
807 
808  qDebug() << "NotifyTransactionChanged : " + strHash + " status= " + QString::number(status);
809  QMetaObject::invokeMethod(walletmodel, "updateTransaction", Qt::QueuedConnection /*,
810  Q_ARG(QString, strHash),
811  Q_ARG(int, status)*/);
812 }
813 
814 static void ShowProgress(WalletModel* walletmodel, const std::string& title, int nProgress)
815 {
816  // emits signal "showProgress"
817  QMetaObject::invokeMethod(walletmodel, "showProgress", Qt::QueuedConnection,
818  Q_ARG(QString, QString::fromStdString(title)),
819  Q_ARG(int, nProgress));
820 }
821 
822 static void NotifyWatchonlyChanged(WalletModel* walletmodel, bool fHaveWatchonly)
823 {
824  QMetaObject::invokeMethod(walletmodel, "updateWatchOnlyFlag", Qt::QueuedConnection,
825  Q_ARG(bool, fHaveWatchonly));
826 }
827 
828 static void NotifySSTChanged(WalletModel* walletmodel, const CAmount stakeSplitThreshold)
829 {
830  const double val = static_cast<double>(stakeSplitThreshold) / COIN;
831  Q_EMIT walletmodel->notifySSTChanged(val);
832 }
833 
834 static void NotifyWalletBacked(WalletModel* model, const bool fSuccess, const std::string& filename)
835 {
836  std::string message;
837  std::string title = "Backup ";
839 
840  if (fSuccess) {
841  message = "The wallet data was successfully saved to ";
842  title += "Successful: ";
843  method = CClientUIInterface::MessageBoxFlags::MSG_INFORMATION;
844  } else {
845  message = "There was an error trying to save the wallet data to ";
846  title += "Failed: ";
847  method = CClientUIInterface::MessageBoxFlags::MSG_ERROR;
848  }
849 
850  message += _(filename.data());
851 
852  QMetaObject::invokeMethod(model, "message", Qt::QueuedConnection,
853  Q_ARG(QString, QString::fromStdString(title)),
854  Q_ARG(QString, QString::fromStdString(message)),
855  Q_ARG(unsigned int, (unsigned int)method));
856 }
857 
859 {
860  // Connect signals to wallet
861  m_handler_notify_status_changed = interfaces::MakeHandler(wallet->NotifyStatusChanged.connect(std::bind(&NotifyKeyStoreStatusChanged, this)));
862  m_handler_notify_addressbook_changed = interfaces::MakeHandler(wallet->NotifyAddressBookChanged.connect(std::bind(NotifyAddressBookChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6)));
863  m_handler_notify_sst_changed = interfaces::MakeHandler(wallet->NotifySSTChanged.connect(std::bind(NotifySSTChanged, this, std::placeholders::_1)));
864  m_handler_notify_transaction_changed = interfaces::MakeHandler(wallet->NotifyTransactionChanged.connect(std::bind(NotifyTransactionChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)));
865  m_handler_show_progress = interfaces::MakeHandler(wallet->ShowProgress.connect(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2)));
866  m_handler_notify_watch_only_changed = interfaces::MakeHandler(wallet->NotifyWatchonlyChanged.connect(std::bind(NotifyWatchonlyChanged, this, std::placeholders::_1)));
867  m_handler_notify_walletbacked = interfaces::MakeHandler(wallet->NotifyWalletBacked.connect(std::bind(NotifyWalletBacked, this, std::placeholders::_1, std::placeholders::_2)));
868 }
869 
871 {
872  // Disconnect signals from wallet
873  m_handler_notify_status_changed->disconnect();
875  m_handler_notify_sst_changed->disconnect();
877  m_handler_show_progress->disconnect();
879  m_handler_notify_walletbacked->disconnect();
880 }
881 
882 // WalletModel::UnlockContext implementation
884 {
885  const WalletModel::EncryptionStatus status_before = getEncryptionStatus();
886  if (status_before == Locked || status_before == UnlockedForStaking)
887  {
888  // Request UI to unlock wallet
889  Q_EMIT requireUnlock();
890  }
891  // If wallet is still locked, unlock was failed or cancelled, mark context as invalid
892  bool valid = isWalletUnlocked();
893 
894  return UnlockContext(this, valid, status_before);
895 }
896 
898  wallet(_wallet),
899  valid(_valid),
900  was_status(status_before),
901  relock(status_before == Locked || status_before == UnlockedForStaking)
902 {
903 }
904 
906 {
907  if (valid && relock && wallet) {
908  if (was_status == Locked) wallet->setWalletLocked(true);
909  else if (was_status == UnlockedForStaking) wallet->lockForStakingOnly();
910  wallet->updateStatus();
911  }
912 }
913 
915 {
916  // Transfer context; old object no longer relocks wallet
917  *this = rhs;
918  rhs.relock = false;
919 }
920 
921 bool WalletModel::getPubKey(const CKeyID& address, CPubKey& vchPubKeyOut) const
922 {
923  return wallet->GetPubKey(address, vchPubKeyOut);
924 }
925 
927  return wallet->nTimeFirstKey;
928 }
929 
931 {
932  return wallet->GetKeyCreationTime(key);
933 }
934 
936 {
937  if (this->isMine(address)) {
938  return wallet->GetKeyCreationTime(address);
939  }
940  return 0;
941 }
942 
943 int64_t WalletModel::getKeyCreationTime(const std::string& address)
944 {
945  bool isStaking = false, isExchange = false, isShielded = false;
946  return wallet->GetKeyCreationTime(Standard::DecodeDestination(address, isStaking, isExchange, isShielded));
947 }
948 
950 {
951  if (this->isMine(address)) {
952  return wallet->GetKeyCreationTime(address);
953  }
954  return 0;
955 }
956 
958 {
959  auto res = wallet->getNewAddress(label);
960  return res ? CallResult<Destination>(Destination(*res.getObjResult(), false, false)) :
961  CallResult<Destination>(res.getError());
962 }
963 
965 {
966  auto res = wallet->getNewStakingAddress(label);
967  return res ? CallResult<Destination>(Destination(*res.getObjResult(), true, false)) :
968  CallResult<Destination>(res.getError());
969 }
970 
972 {
973  return CallResult<Destination>(Destination(wallet->GenerateNewSaplingZKey(std::move(strLabel))));
974 }
975 
976 bool WalletModel::whitelistAddressFromColdStaking(const QString &addressStr)
977 {
979 }
980 
981 bool WalletModel::blacklistAddressFromColdStaking(const QString &addressStr)
982 {
984 }
985 
986 bool WalletModel::updateAddressBookPurpose(const QString &addressStr, const std::string& purpose)
987 {
988  bool isStaking = false, isExchange = false;
989  CTxDestination address = DecodeDestination(addressStr.toStdString(), isStaking, isExchange);
990  if (isStaking)
991  return error("Invalid PIVX address, cold staking address");
992  CKeyID keyID;
993  if (!getKeyId(address, keyID))
994  return false;
995  return wallet->SetAddressBook(keyID, getLabelForAddress(address), purpose);
996 }
997 
998 bool WalletModel::getKeyId(const CTxDestination& address, CKeyID& keyID)
999 {
1000  if (!IsValidDestination(address))
1001  return error("Invalid PIVX address");
1002 
1003  const CKeyID* inKeyID = boost::get<CKeyID>(&address);
1004  if (!inKeyID)
1005  return error("Unable to get KeyID from PIVX address");
1006 
1007  keyID = *inKeyID;
1008  return true;
1009 }
1010 
1012 {
1013  std::string label = "";
1014  label = wallet->GetNameForAddressBookEntry(address);
1015  return label;
1016 }
1017 
1019 {
1022  if (!opAddr) {
1023  return QString();
1024  }
1025  QString ret = QString::fromStdString(Standard::EncodeDestination(*opAddr));
1026  return ret.left(18) + "..." + ret.right(18);
1027 }
1028 
1029 // returns a COutPoint of 10000 PIV if found
1031 {
1032  CWallet::AvailableCoinsFilter coinsFilter;
1033  coinsFilter.fIncludeDelegated = false;
1035  coinsFilter.nMinOutValue = coinsFilter.nMaxOutValue;
1036  coinsFilter.fIncludeLocked = true;
1037  std::vector<COutput> vCoins;
1038  wallet->AvailableCoins(&vCoins, nullptr, coinsFilter);
1039  for (const COutput& out : vCoins) {
1040  // skip locked collaterals
1041  if (!isLockedCoin(out.tx->GetHash(), out.i)) {
1042  outPoint = COutPoint(out.tx->GetHash(), out.i);
1043  return true;
1044  }
1045  }
1046  return false;
1047 }
1048 
1049 // Depth of a wallet transaction or -1 if not found
1050 int WalletModel::getWalletTxDepth(const uint256& txHash) const
1051 {
1052  const CWalletTx *walletTx = wallet->GetWalletTx(txHash);
1053  if (!walletTx) {
1054  return -1;
1055  }
1056  LOCK(wallet->cs_wallet);
1057  return walletTx->GetDepthInMainChain();
1058 }
1059 
1060 bool WalletModel::isSpent(const COutPoint& outpoint) const
1061 {
1062  LOCK(wallet->cs_wallet);
1063  return wallet->IsSpent(outpoint.hash, outpoint.n);
1064 }
1065 
1066 void WalletModel::listCoins(std::map<ListCoinsKey, std::vector<ListCoinsValue>>& mapCoins, bool fTransparent) const
1067 {
1068  if (fTransparent) {
1069  listCoins(mapCoins);
1070  } else {
1071  listAvailableNotes(mapCoins);
1072  }
1073 }
1074 
1075 void WalletModel::listAvailableNotes(std::map<ListCoinsKey, std::vector<ListCoinsValue>>& mapCoins) const
1076 {
1077  for (const auto& it: wallet->ListNotes()) {
1078  const ListCoinsKey key{QString::fromStdString(KeyIO::EncodePaymentAddress(it.first)), false, nullopt};
1079 
1080  for (const SaplingNoteEntry& note : it.second) {
1081  mapCoins[key].emplace_back(note.op.hash,
1082  (int)note.op.n,
1083  (CAmount)note.note.value(),
1084  0,
1085  note.confirmations);
1086  }
1087  }
1088 }
1089 
1090 // AvailableCoins + LockedCoins grouped by wallet address (put change in one group with wallet address)
1091 void WalletModel::listCoins(std::map<ListCoinsKey, std::vector<ListCoinsValue>>& mapCoins) const
1092 {
1093  for (const auto& it: wallet->ListCoins()) {
1094  const std::pair<CTxDestination, Optional<CTxDestination>>& addresses = it.first;
1095  const std::vector<COutput>& coins = it.second;
1096 
1097  const QString& address = QString::fromStdString(EncodeDestination(addresses.first));
1098  const Optional<QString>& stakerAddr = addresses.second == nullopt ? nullopt : Optional<QString>(
1099  QString::fromStdString(EncodeDestination(*addresses.second, CChainParams::STAKING_ADDRESS)));
1100  // P2CS cannot be "change"
1101  const bool isChange = stakerAddr == nullopt ? wallet->IsChange(addresses.first) : false;
1102 
1103  const ListCoinsKey key{address, isChange, stakerAddr};
1104 
1105  for (const COutput& out: coins) {
1106  mapCoins[key].emplace_back(out.tx->GetHash(),
1107  out.i,
1108  out.tx->tx->vout[out.i].nValue,
1109  out.tx->GetTxTime(),
1110  out.nDepth);
1111  }
1112  }
1113 }
1114 
1115 bool WalletModel::isLockedCoin(uint256 hash, unsigned int n, bool isTransparent) const
1116 {
1117  LOCK(wallet->cs_wallet);
1118  if (isTransparent)
1119  return wallet->IsLockedCoin(hash, n);
1120  else
1121  return wallet->IsLockedNote(SaplingOutPoint(hash, n));
1122 }
1123 
1124 void WalletModel::lockCoin(uint256 hash, unsigned int n, bool isTransparent)
1125 {
1126  LOCK(wallet->cs_wallet);
1127  isTransparent ? wallet->LockCoin(COutPoint(hash, n)) : wallet->LockNote(SaplingOutPoint(hash, n));
1128 }
1129 
1130 void WalletModel::unlockCoin(uint256 hash, unsigned int n, bool isTransparent)
1131 {
1132  LOCK(wallet->cs_wallet);
1133  isTransparent ? wallet->UnlockCoin(COutPoint(hash, n)) : wallet->UnlockNote(SaplingOutPoint(hash, n));
1134 }
1135 
1136 std::set<COutPoint> WalletModel::listLockedCoins()
1137 {
1138  LOCK(wallet->cs_wallet);
1139  return wallet->ListLockedCoins();
1140 }
1141 
1142 std::set<SaplingOutPoint> WalletModel::listLockedNotes()
1143 {
1144  LOCK(wallet->cs_wallet);
1145  return wallet->ListLockedNotes();
1146 }
1147 
1148 void WalletModel::loadReceiveRequests(std::vector<std::string>& vReceiveRequests)
1149 {
1150  vReceiveRequests = wallet->GetDestValues("rr"); // receive request
1151 }
1152 
1153 bool WalletModel::saveReceiveRequest(const std::string& sAddress, const int64_t nId, const std::string& sRequest)
1154 {
1155  CTxDestination dest = DecodeDestination(sAddress);
1156 
1157  std::stringstream ss;
1158  ss << nId;
1159  std::string key = "rr" + ss.str(); // "rr" prefix = "receive request" in destdata
1160 
1161  LOCK(wallet->cs_wallet);
1162  if (sRequest.empty())
1163  return wallet->EraseDestData(dest, key);
1164  else
1165  return wallet->AddDestData(dest, key, sRequest);
1166 }
1167 
1169 {
1170  return IsMine(*wallet, address);
1171 }
1172 
1173 bool WalletModel::isMine(const QString& addressStr)
1174 {
1175  return IsMine(*wallet, DecodeDestination(addressStr.toStdString()));
1176 }
1177 
1179 {
1180  return boost::get<libzcash::SaplingPaymentAddress>(&address);
1181 }
1182 
1184 {
1185  return wallet->IsUsed(address);
1186 }
1187 
1189 {
1191  return opAddr ? Optional<QString>(QString::fromStdString(KeyIO::EncodePaymentAddress(*opAddr))) : nullopt;
1192 }
1193 
1195 {
1196  m_client_model = client_model;
1197 }
1198 
1200 {
1202 }
1203 
1205 {
1207 }
1208 
1210 { // future: unify minimum required fee.
1211  return GetRequiredFee(1000);
1212 }
int64_t CAmount
Amount in PIV (Can be negative)
Definition: amount.h:13
false
Definition: bls_dkg.cpp:151
const CChainParams & Params()
Return the currently selected parameters.
Qt model of the address book in the core.
void updateEntry(const QString &address, const QString &label, bool isMine, const QString &purpose, int status)
uint256 hash
Definition: transaction.h:35
uint32_t n
Definition: transaction.h:36
size_type size() const
Definition: streams.h:165
virtual bool HaveWatchOnly(const CScript &dest) const
Definition: keystore.cpp:104
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:139
void SetFeeTxHash(const uint256 &txid)
uint256 GetHash() const
CBlockIndex * Genesis() const
Returns the index entry for the genesis block of this chain, or nullptr if none.
Definition: chain.h:399
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:72
bool IsTestnet() const
Definition: chainparams.h:99
bool IsRegTestNet() const
Definition: chainparams.h:98
MessageBoxFlags
Flags for CClientUIInterface::ThreadSafeMessageBox.
Definition: guiinterface.h:35
Coin Control Features.
Definition: coincontrol.h:34
bool IsLocked() const
Definition: crypter.cpp:148
bool IsCrypted() const
Definition: crypter.h:154
boost::signals2::signal< void(CCryptoKeyStore *wallet)> NotifyStatusChanged
Wallet status (encrypted, locked) changed.
Definition: crypter.h:175
bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const override
Definition: crypter.cpp:215
Fee rate in PIV per kilobyte: CAmount / kB.
Definition: feerate.h:20
CAmount GetFee(size_t size) const
Definition: feerate.cpp:21
An encapsulated private key.
Definition: key.h:30
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:21
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:72
An encapsulated public key.
Definition: pubkey.h:44
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:167
A key allocated from the key pool.
Definition: wallet.h:1256
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:381
bool IsSporkActive(SporkId nSporkID)
Definition: spork.cpp:220
bool IsActive() const
Definition: wallet.h:213
Capture information about block/transaction validation.
Definition: validation.h:24
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,...
Definition: wallet.h:577
boost::signals2::signal< void(const CAmount stakeSplitThreshold)> NotifySSTChanged
notify stake-split threshold changed
Definition: wallet.h:1251
fs::path GetPathToDBFile()
Get the path to the wallet's db file.
Definition: wallet.h:759
CStakerStatus * pStakerStatus
Definition: wallet.h:737
RecursiveMutex cs_wallet
Definition: wallet.h:720
int GetVersion()
get the current wallet format (the oldest client version guaranteed to understand this wallet)
Definition: wallet.cpp:4701
boost::signals2::signal< void(const bool fSuccess, const std::string &filename)> NotifyWalletBacked
notify wallet file backed up
Definition: wallet.h:1248
boost::signals2::signal< void(CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged
Wallet transaction added, removed or updated.
Definition: wallet.h:1239
static CAmount minStakeSplitThreshold
minimum accpeted value for stake split threshold
Definition: wallet.h:735
bool BackupWallet(const std::string &strDest)
Creates a wallet backup in strDest path.
Definition: wallet.cpp:4457
int64_t nTimeFirstKey
Definition: wallet.h:776
std::vector< std::string > GetDestValues(const std::string &prefix) const
Get all destination values matching a prefix.
Definition: wallet.cpp:4098
bool fUseCustomFee
Definition: wallet.h:740
bool EraseDestData(const CTxDestination &dest, const std::string &key)
Erases a destination data tuple in the store and on disk.
Definition: wallet.cpp:4085
boost::signals2::signal< void(bool fHaveWatchOnly)> NotifyWatchonlyChanged
Watch-only address added.
Definition: wallet.h:1245
bool fWalletUnlockStaking
Definition: wallet.h:722
CAmount nCustomFee
Definition: wallet.h:741
SaplingScriptPubKeyMan * GetSaplingScriptPubKeyMan() const
Definition: wallet.h:712
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:4076
std::map< CKeyID, CKeyMetadata > mapKeyMetadata
Definition: wallet.h:726
libzcash::SaplingPaymentAddress GenerateNewSaplingZKey(std::string label="")
Generates new Sapling key.
Definition: wallet.cpp:4710
static const CAmount DEFAULT_STAKE_SPLIT_THRESHOLD
Definition: wallet.h:679
CAmount GetStakeSplitThreshold() const
Definition: wallet.h:893
boost::signals2::signal< void(CWallet *wallet, const CWDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status)> NotifyAddressBookChanged
Address book entry changed.
Definition: wallet.h:1233
WalletDatabase & GetDBHandle() const
Definition: wallet.h:752
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
Definition: wallet.h:1242
A transaction with a bunch of additional info that only the owner cares about.
Definition: wallet.h:325
int GetDepthInMainChain() const NO_THREAD_SAFETY_ANALYSIS
Return depth of transaction in blockchain: <0 : conflicts with a transaction this deep in the blockch...
Definition: wallet.cpp:4477
Model for PIVX network client.
Definition: clientmodel.h:50
int64_t getLastBlockProcessedTime() const
uint256 getLastBlockProcessed() const
int getLastBlockProcessedHeight() const
bool inInitialBlockDownload() const
Return true if core is doing initial block download.
Wrapper class for every supported address.
const CKeyID * getKeyID()
Interface from Qt to configuration data structure for PIVX client.
Definition: optionsmodel.h:22
void setWalletDefaultOptions(QSettings &settings, bool reset=false)
CTransaction getFinalTx()
SaplingOperation * setSelectShieldedCoins(const bool select)
SaplingOperation * setCoinControl(const CCoinControl *_coinControl)
SaplingOperation * setRecipients(std::vector< SendManyRecipient > &vec)
SaplingOperation * setMinDepth(int _mindepth)
OperationResult build()
SaplingOperation * setSelectTransparentCoins(const bool select, const bool _fIncludeDelegated=false)
SaplingOperation * setTransparentKeyChange(CReserveKey *reserveKey)
An outpoint - a combination of a transaction hash and an index n into its sapling output description ...
Definition: transaction.h:82
Optional< libzcash::SaplingPaymentAddress > GetOutPointAddress(const CWalletTx &tx, const SaplingOutPoint &op) const
Return the shielded address of a specific outpoint of wallet transaction.
Optional< libzcash::SaplingPaymentAddress > GetAddressFromInputIfPossible(const CWalletTx *wtx, int index) const
Return the address from where the shielded spend is taking the funds from (if possible)
UI model for the transaction table of a wallet.
Access to the wallet database.
Definition: walletdb.h:112
bool WriteCustomFeeValue(const CAmount &nCustomFee)
Definition: walletdb.cpp:240
bool WriteUseCustomFee(bool fUse)
Definition: walletdb.cpp:235
UnlockContext(WalletModel *wallet, bool valid, const WalletModel::EncryptionStatus &status_before)
void CopyFrom(UnlockContext &&rhs)
Interface to PIVX wallet from Qt view code.
Definition: walletmodel.h:109
OptionsModel * optionsModel
Definition: walletmodel.h:390
int getLastBlockProcessedNum() const
bool validateAddress(const QString &address)
AddressTableModel * addressTableModel
Definition: walletmodel.h:392
void getAvailableP2CSCoins(std::vector< COutput > &vCoins) const
bool isStakingStatusActive() const
void balanceChanged(const interfaces::WalletBalances &walletBalances)
void loadReceiveRequests(std::vector< std::string > &vReceiveRequests)
std::unique_ptr< interfaces::Handler > m_handler_notify_watch_only_changed
Definition: walletmodel.h:381
void lockCoin(uint256 hash, unsigned int n, bool isTransparent=true)
EncryptionStatus cachedEncryptionStatus
Definition: walletmodel.h:398
QString getSaplingAddressString(const CWalletTx *wtx, const SaplingOutPoint &op) const
CAmount getNetMinFee()
void coinsSent(CWallet *wallet, const SendCoinsRecipient &recipient, const QByteArray &transaction)
void message(const QString &title, const QString &body, unsigned int style, bool *ret=nullptr)
CallResult< Destination > getNewAddress(const std::string &label="") const
ClientModel * m_client_model
Definition: walletmodel.h:383
bool isWalletLocked(bool fFullUnlocked=true) const
bool isMine(const CWDestination &address)
bool isTestNetwork() const
Definition: walletmodel.cpp:76
std::string getLabelForAddress(const CTxDestination &address)
bool updateAddressBookLabels(const CWDestination &address, const std::string &strName, const std::string &strPurpose)
bool isSaplingInMaintenance() const
Definition: walletmodel.cpp:96
void resetWalletOptions(QSettings &settings)
Definition: walletmodel.cpp:69
CAmount getLockedBalance(bool isTransparent) const
bool isShutdownRequested()
Definition: walletmodel.cpp:86
void unlockCoin(uint256 hash, unsigned int n, bool isTransparent=true)
bool setWalletEncrypted(bool encrypted, const SecureString &passphrase)
CAmount getUnlockedBalance(const CCoinControl *coinControl=nullptr, bool fIncludeDelegated=true, bool fIncludeShielded=true) const
void listCoins(std::map< ListCoinsKey, std::vector< ListCoinsValue >> &mapCoins, bool fSelectTransparent) const
void listAvailableNotes(std::map< ListCoinsKey, std::vector< ListCoinsValue >> &mapCoins) const
void setWalletCustomFee(bool fUseCustomFee, const CAmount nFee=DEFAULT_TRANSACTION_FEE)
void encryptionStatusChanged(int status)
void pollBalanceChanged()
SendCoinsReturn sendCoins(WalletModelTransaction &transaction)
bool isHDEnabled() const
bool isV6Enforced() const
CallResult< Destination > getNewShieldedAddress(std::string strLabel="")
Return a new shielded address.
bool getWalletCustomFee(CAmount &nFeeRet)
bool addKeys(const CKey &key, const CPubKey &pubkey, WalletRescanReserver &reserver)
@ UnlockedForStaking
Definition: walletmodel.h:137
bool upgradeWallet(std::string &upgradeError)
TransactionTableModel * transactionTableModel
Definition: walletmodel.h:393
std::unique_ptr< interfaces::Handler > m_handler_notify_transaction_changed
Definition: walletmodel.h:379
ClientModel & clientModel() const
Definition: walletmodel.h:352
void notifyWatchonlyChanged(bool fHaveWatchonly)
bool updateAddressBookPurpose(const QString &addressStr, const std::string &purpose)
bool changePassphrase(const SecureString &oldPass, const SecureString &newPass)
void notifyReceiveAddressChanged()
bool isStakingOnlyUnlocked()
bool getKeyId(const CTxDestination &address, CKeyID &keyID)
void emitBalanceChanged()
void setCacheNumBlocks(int _cachedNumBlocks)
Definition: walletmodel.h:359
CAmount getMinColdStakingAmount() const
bool isWalletUnlocked() const
void setClientModel(ClientModel *client_model)
void pollFinished()
OperationResult PrepareShieldedTransaction(WalletModelTransaction *modelTransaction, bool fromTransparent, const CCoinControl *coinControl=nullptr)
bool saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest)
void updateStatus()
AddressTableModel * getAddressTableModel()
bool blacklistAddressFromColdStaking(const QString &address)
CAmount getWalletStakeSplitThreshold() const
OptionsModel * getOptionsModel()
int getWalletTxDepth(const uint256 &txHash) const
SendCoinsReturn prepareTransaction(WalletModelTransaction *transaction, const CCoinControl *coinControl=nullptr, bool fIncludeDelegations=true)
std::set< COutPoint > listLockedCoins()
bool whitelistAddressFromColdStaking(const QString &addressStr)
bool getMNCollateralCandidate(COutPoint &outPoint)
bool processBalanceChangeInternal()
bool isColdStaking() const
bool backupWallet(const QString &filename)
std::unique_ptr< interfaces::Handler > m_handler_notify_status_changed
Definition: walletmodel.h:376
bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString(), bool stakingOnly=false)
std::unique_ptr< interfaces::Handler > m_handler_notify_sst_changed
Definition: walletmodel.h:378
double getSSTMinimum() const
EncryptionStatus getEncryptionStatus() const
CAmount getDelegatedBalance() const
bool isColdStakingNetworkelyEnabled() const
Whether cold staking is enabled or disabled in the network.
Definition: walletmodel.cpp:91
void balanceNotify()
uint256 m_cached_best_block_hash
Definition: walletmodel.h:400
interfaces::WalletBalances m_cached_balances
Definition: walletmodel.h:396
int64_t getKeyCreationTime(const CPubKey &key)
bool fForceCheckBalanceChanged
Definition: walletmodel.h:386
bool haveWatchOnly() const
interfaces::WalletBalances getBalances()
Definition: walletmodel.h:405
CWallet * wallet
Definition: walletmodel.h:369
void notifySSTChanged(const double sstVal)
notify stake-split threshold changed
bool getPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
Q_INVOKABLE void checkBalanceChanged(const interfaces::WalletBalances &new_balances)
OperationResult createAndSendProposalFeeTx(CBudgetProposal &prop)
QTimer * pollTimer
Definition: walletmodel.h:402
void unsubscribeFromCoreSignals()
bool isSpent(const COutPoint &outpoint) const
bool IsShieldedDestination(const CWDestination &address)
void requireUnlock()
bool isLockedCoin(uint256 hash, unsigned int n, bool isTransparent=true) const
void updateTransaction()
Optional< QString > getShieldedAddressFromSpendDesc(const uint256 &txHash, int index)
std::unique_ptr< interfaces::Handler > m_handler_notify_walletbacked
Definition: walletmodel.h:382
int64_t getCreationTime() const
QString getWalletPath()
void updateTxModelData()
void updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status)
uint256 getLastBlockProcessed() const
bool fHaveWatchOnly
Definition: walletmodel.h:385
void updateWatchOnlyFlag(bool fHaveWatchonly)
CallResult< Destination > getNewStakingAddress(const std::string &label="") const
Return a new address used to receive for delegated cold stake purpose.
void setCacheBlockHash(const uint256 &_blockHash)
Definition: walletmodel.h:361
void setWalletDefaultFee(CAmount fee=DEFAULT_TRANSACTION_FEE)
CAmount getBalance(const CCoinControl *coinControl=nullptr, bool fIncludeDelegated=true, bool fUnlockedOnly=false, bool fIncludeShielded=true) const
std::set< SaplingOutPoint > listLockedNotes()
UnlockContext requestUnlock()
int cachedNumBlocks
Definition: walletmodel.h:399
QFuture< void > pollFuture
Definition: walletmodel.h:403
void setWalletStakeSplitThreshold(const CAmount nStakeSplitThreshold)
std::unique_ptr< interfaces::Handler > m_handler_notify_addressbook_changed
Definition: walletmodel.h:377
WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent=0)
Definition: walletmodel.cpp:42
bool isRegTestNetwork() const
Definition: walletmodel.cpp:81
const CWalletTx * getTx(uint256 id)
void setfForceCheckBalanceChanged(bool _fForceCheckBalanceChanged)
Definition: walletmodel.h:362
std::unique_ptr< interfaces::Handler > m_handler_show_progress
Definition: walletmodel.h:380
bool lockForStakingOnly(const SecureString &passPhrase=SecureString())
bool isUsed(CTxDestination address)
bool isSaplingWalletEnabled() const
@ StakingOnlyUnlocked
Definition: walletmodel.h:128
@ AmountWithFeeExceedsBalance
Definition: walletmodel.h:123
@ TransactionCheckFailed
Definition: walletmodel.h:126
@ TransactionCreationFailed
Definition: walletmodel.h:125
@ CannotCreateInternalAddress
Definition: walletmodel.h:130
@ AmountExceedsBalance
Definition: walletmodel.h:122
void subscribeToCoreSignals()
bool hasWalletCustomFee()
TransactionTableModel * getTransactionTableModel()
Data model for a walletmodel transaction.
void setTransactionFee(const CAmount &newFee)
QList< SendCoinsRecipient > getRecipients()
CReserveKey * newPossibleKeyChange(CWallet *wallet)
CTransactionRef & getTransaction()
RAII object to check and reserve a wallet rescan.
Definition: wallet.h:1324
std::string GetHex() const
Definition: uint256.cpp:21
uint64_t value() const
Definition: note.h:30
Sapling functions.
Definition: address.h:30
256-bit opaque blob.
Definition: uint256.h:138
boost::variant< CTxDestination, libzcash::SaplingPaymentAddress > CWDestination
void UnlockCoin(const COutPoint &output)
Definition: wallet.cpp:3960
void GetAvailableP2CSCoins(std::vector< COutput > &vCoins) const
Available coins (P2CS)
Definition: wallet.cpp:2362
static std::string ParseIntoAddress(const CWDestination &dest, const std::string &purpose)
Definition: wallet.cpp:3630
CAmount GetDelegatedBalance() const
Definition: wallet.cpp:2210
std::map< std::pair< CTxDestination, Optional< CTxDestination > >, std::vector< COutput > > ListCoins() const
Return list of available coins and locked coins grouped by non-change output address.
Definition: wallet.cpp:2909
void LockNote(const SaplingOutPoint &op)
Definition: wallet.cpp:3954
CWallet::CommitResult CommitTransaction(CTransactionRef tx, CReserveKey &opReservekey, CConnman *connman)
Definition: wallet.cpp:3510
bool CreateTransaction(const std::vector< CRecipient > &vecSend, CTransactionRef &txRet, CReserveKey &reservekey, CAmount &nFeeRet, int &nChangePosInOut, std::string &strFailReason, const CCoinControl *coinControl=nullptr, bool sign=true, CAmount nFeePay=0, bool fIncludeDelegated=false, bool *fStakeDelegationVoided=nullptr, int nExtraSize=0, int nMinDepth=0)
Create a new transaction paying the recipients with a set of coins selected by SelectCoins(); Also cr...
Definition: wallet.cpp:3040
CAmount GetLockedShieldCoins() const
Definition: wallet.cpp:2236
bool IsLockedNote(const SaplingOutPoint &op) const
Definition: wallet.cpp:3992
CAmount GetLockedCoins() const
Definition: wallet.cpp:2218
std::set< SaplingOutPoint > ListLockedNotes()
Definition: wallet.cpp:4004
bool AvailableCoins(std::vector< COutput > *pCoins, const CCoinControl *coinControl=nullptr, AvailableCoinsFilter coinsFilter=AvailableCoinsFilter()) const
populate vCoins with vector of available COutputs.
Definition: wallet.cpp:2555
bool SetStakeSplitThreshold(const CAmount sst)
Definition: wallet.cpp:4010
bool CreateBudgetFeeTX(CTransactionRef &tx, const uint256 &hash, CReserveKey &keyChange, CAmount fee)
Definition: wallet.cpp:2944
std::string GetNameForAddressBookEntry(const CWDestination &address) const
Definition: wallet.cpp:3686
std::map< libzcash::SaplingPaymentAddress, std::vector< SaplingNoteEntry > > ListNotes() const
Return list of available shield notes and locked shield notes grouped by sapling address.
Definition: wallet.cpp:2939
CAmount GetAvailableBalance(bool fIncludeDelegated=true, bool fIncludeShielded=true) const
Definition: wallet.cpp:2162
std::set< COutPoint > ListLockedCoins()
Definition: wallet.cpp:3998
bool SetAddressBook(const CWDestination &address, const std::string &strName, const std::string &purpose)
Definition: wallet.cpp:3642
bool IsLockedCoin(const uint256 &hash, unsigned int n) const
Definition: wallet.cpp:3984
std::string ToString() const
Definition: wallet.cpp:3489
void LockCoin(const COutPoint &output)
Definition: wallet.cpp:3948
Optional< AddressBook::CAddressBookData > GetAddressBookEntry(const CWDestination &address) const
Definition: wallet.cpp:3693
void UnlockNote(const SaplingOutPoint &op)
Definition: wallet.cpp:3966
bool Lock()
Definition: wallet.cpp:397
CallResult< CTxDestination > getNewAddress(const std::string &addressLabel, const std::string purpose, const CChainParams::Base58Type addrType=CChainParams::PUBKEY_ADDRESS)
Definition: wallet.cpp:196
bool SetMaxVersion(int nVersion)
change which version we're allowed to upgrade to (note that this does not immediately imply upgrading...
Definition: wallet.cpp:606
bool Upgrade(std::string &error, const int prevVersion)
Upgrade wallet to HD and Sapling if needed.
Definition: wallet.cpp:1824
bool ChangeWalletPassphrase(const SecureString &strOldWalletPassphrase, const SecureString &strNewWalletPassphrase)
Definition: wallet.cpp:457
CBlockIndex * ScanForWalletTransactions(CBlockIndex *pindexStart, CBlockIndex *pindexStop, const WalletRescanReserver &reserver, bool fUpdate=false, bool fromStartup=false)
Scan the block chain (starting in pindexStart) for transactions from or to us.
Definition: wallet.cpp:1896
bool SetMinVersion(enum WalletFeature, WalletBatch *batch_in=nullptr, bool fExplicit=false)
signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVe...
Definition: wallet.cpp:580
bool Unlock(const SecureString &strWalletPassphrase, bool anonimizeOnly=false)
Definition: wallet.cpp:376
CallResult< CTxDestination > getNewStakingAddress(const std::string &label)
Definition: wallet.cpp:191
bool IsHDEnabled() const
Whether the wallet is hd or not //.
Definition: wallet.cpp:156
bool EncryptWallet(const SecureString &strWalletPassphrase)
Definition: wallet.cpp:773
bool IsChange(const CTxOut &txout) const
Definition: wallet.cpp:1515
int64_t GetKeyCreationTime(const CWDestination &dest)
Definition: wallet.cpp:221
const CWalletTx * GetWalletTx(const uint256 &hash) const
Definition: wallet.cpp:166
bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) override
Adds a key to the store, and saves it to disk.
Definition: wallet.cpp:252
bool IsUsed(const CTxDestination address) const
Definition: wallet.cpp:1462
bool IsSaplingUpgradeEnabled() const
Whether the wallet supports Sapling or not //.
Definition: wallet.cpp:161
bool IsSpent(const COutPoint &outpoint) const
Outpoint is spent if any non-conflicted transaction spends it:
Definition: wallet.cpp:720
ChangeType
General change type (added, updated, removed).
Definition: guiinterface.h:24
#define T(expected, seed, data)
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:90
isminetype IsMine(const CKeyStore &keystore, const CTxDestination &dest)
Definition: ismine.cpp:29
bool IsValidDestinationString(const std::string &str, bool fStaking, const CChainParams &params)
Definition: key_io.cpp:113
@ LOCK
Definition: lockunlock.h:16
const std::string COLD_STAKING_SEND
Definition: addressbook.cpp:16
const std::string SHIELDED_SEND
Definition: addressbook.cpp:18
@ UPGRADE_V6_0
Definition: params.h:41
std::string EncodePaymentAddress(const libzcash::PaymentAddress &zaddr)
Optional< libzcash::SaplingPaymentAddress > DecodeSaplingPaymentAddress(const std::string &strAddress)
bool IsValidDestination(const CWDestination &address)
std::string EncodeDestination(const CWDestination &address, const CChainParams::Base58Type addrType)
CWDestination DecodeDestination(const std::string &strAddress)
std::unique_ptr< Handler > MakeHandler(boost::signals2::connection connection)
Return handler wrapping a boost signal connection.
Definition: handler.cpp:26
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:80
OperationResult errorOut(const std::string &errorStr)
boost::optional< T > Optional
Substitute for C++17 std::optional.
Definition: optional.h:12
QSettings * settings
Definition: qtutils.cpp:197
OperationResult CheckTransactionSize(std::vector< SendManyRecipient > &recipients, bool fromTaddr)
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:61
@ SER_DISK
Definition: serialize.h:175
@ SER_NETWORK
Definition: serialize.h:174
bool ShutdownRequested()
Definition: shutdown.cpp:22
CSporkManager sporkManager
Definition: spork.cpp:29
@ SPORK_19_COLDSTAKING_MAINTENANCE
Definition: sporkid.h:26
@ SPORK_20_SAPLING_MAINTENANCE
Definition: sporkid.h:27
CScript GetScriptForStakeDelegation(const CKeyID &stakingKey, const CKeyID &spendingKey)
Generate a P2CS script for the given staker and owner keys.
Definition: standard.cpp:291
CScript GetScriptForStakeDelegationLOF(const CKeyID &stakingKey, const CKeyID &spendingKey)
Definition: standard.cpp:301
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a PIVX scriptPubKey for the given CTxDestination.
Definition: standard.cpp:278
boost::variant< CNoDestination, CKeyID, CScriptID, CExchangeKeyID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:72
CWallet::CommitStatus status
Definition: wallet.h:1106
CAmount nMNCollateralAmt
Definition: params.h:184
bool NetworkUpgradeActive(int nHeight, Consensus::UpgradeIndex idx) const
Returns true if the given network upgrade is active as of the given block height.
Definition: params.cpp:12
Sapling note, its location in a transaction, and number of confirmations.
SaplingOutPoint op
int confirmations
libzcash::SaplingNote note
Collection of wallet balances.
Definition: wallet.h:16
bool balanceChanged(const WalletBalances &prev) const
Definition: wallet.h:30
#define LOCK2(cs1, cs2)
Definition: sync.h:221
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:247
#define TRY_LOCK(cs, name)
Definition: sync.h:224
bool error(const char *fmt, const Args &... args)
Definition: system.h:77
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a Optional result.
Definition: system.h:65
#define strprintf
Definition: tinyformat.h:1056
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:456
bool CheckTransaction(const CTransaction &tx, CValidationState &state, bool fColdStakingActive)
Transaction validation functions.
Definition: tx_verify.cpp:54
const uint256 UINT256_ZERO
constant uint256 instances
Definition: uint256.h:175
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
CFeeRate minRelayTxFee
Fees smaller than this (in upiv) are considered zero fee (for relaying, mining and transaction creati...
Definition: validation.cpp:108
std::atomic< bool > fImporting
Definition: validation.cpp:94
std::atomic< bool > fReindex
Definition: validation.cpp:95
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:84
CAmount GetRequiredFee(unsigned int nTxBytes)
Return the minimum required fee taking into account the floating relay fee and user set minimum trans...
Definition: fees.cpp:15
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE)
Settings.
@ FEATURE_LATEST
Definition: wallet.h:120
std::map< std::string, std::string > mapValue_t
Definition: wallet.h:273
std::atomic< bool > processingBalance