1 // Copyright (c) 2011-2020 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 #ifndef BITCOIN_QT_WALLETMODEL_H 6 #define BITCOIN_QT_WALLETMODEL_H 7 8 #if defined(HAVE_CONFIG_H) 9 #include <config/bitcoin-config.h> 10 #endif 11 12 #include <key.h> 13 #include <script/standard.h> 14 15 #include <qt/walletmodeltransaction.h> 16 17 #include <interfaces/wallet.h> 18 #include <support/allocators/secure.h> 19 20 #include <vector> 21 22 #include <QObject> 23 24 enum class OutputType; 25 26 class AddressTableModel; 27 class ClientModel; 28 class OptionsModel; 29 class PlatformStyle; 30 class RecentRequestsTableModel; 31 class SendCoinsRecipient; 32 class TransactionTableModel; 33 class WalletModelTransaction; 34 35 class CCoinControl; 36 class CKeyID; 37 class COutPoint; 38 class COutput; 39 class CPubKey; 40 class uint256; 41 42 namespace interfaces { 43 class Node; 44 } // namespace interfaces 45 46 QT_BEGIN_NAMESPACE 47 class QTimer; 48 QT_END_NAMESPACE 49 50 /** Interface to Bitcoin wallet from Qt view code. */ 51 class WalletModel : public QObject 52 { 53 Q_OBJECT 54 55 public: 56 explicit WalletModel(std::unique_ptr<interfaces::Wallet> wallet, ClientModel& client_model, const PlatformStyle *platformStyle, QObject *parent = nullptr); 57 ~WalletModel(); 58 59 enum StatusCode // Returned by sendCoins 60 { 61 OK, 62 InvalidAmount, 63 InvalidAddress, 64 AmountExceedsBalance, 65 AmountWithFeeExceedsBalance, 66 DuplicateAddress, 67 TransactionCreationFailed, // Error returned when wallet is still locked 68 AbsurdFee, 69 PaymentRequestExpired 70 }; 71 72 enum EncryptionStatus 73 { 74 Unencrypted, // !wallet->IsCrypted() 75 Locked, // wallet->IsCrypted() && wallet->IsLocked() 76 Unlocked // wallet->IsCrypted() && !wallet->IsLocked() 77 }; 78 79 OptionsModel *getOptionsModel(); 80 AddressTableModel *getAddressTableModel(); 81 TransactionTableModel *getTransactionTableModel(); 82 RecentRequestsTableModel *getRecentRequestsTableModel(); 83 84 EncryptionStatus getEncryptionStatus() const; 85 86 // Check address for validity 87 bool validateAddress(const QString &address); 88 89 // Return status record for SendCoins, contains error id + information 90 struct SendCoinsReturn 91 { 92 SendCoinsReturn(StatusCode _status = OK, QString _reasonCommitFailed = "") statusSendCoinsReturn93 : status(_status), 94 reasonCommitFailed(_reasonCommitFailed) 95 { 96 } 97 StatusCode status; 98 QString reasonCommitFailed; 99 }; 100 101 // prepare transaction for getting txfee before sending coins 102 SendCoinsReturn prepareTransaction(WalletModelTransaction &transaction, const CCoinControl& coinControl); 103 104 // Send coins to a list of recipients 105 SendCoinsReturn sendCoins(WalletModelTransaction &transaction); 106 107 // Wallet encryption 108 bool setWalletEncrypted(const SecureString& passphrase); 109 // Passphrase only needed when unlocking 110 bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString()); 111 bool changePassphrase(const SecureString &oldPass, const SecureString &newPass); 112 113 // RAI object for unlocking wallet, returned by requestUnlock() 114 class UnlockContext 115 { 116 public: 117 UnlockContext(WalletModel *wallet, bool valid, bool relock); 118 ~UnlockContext(); 119 isValid()120 bool isValid() const { return valid; } 121 122 // Copy constructor is disabled. 123 UnlockContext(const UnlockContext&) = delete; 124 // Move operator and constructor transfer the context UnlockContext(UnlockContext && obj)125 UnlockContext(UnlockContext&& obj) { CopyFrom(std::move(obj)); } 126 UnlockContext& operator=(UnlockContext&& rhs) { CopyFrom(std::move(rhs)); return *this; } 127 private: 128 WalletModel *wallet; 129 bool valid; 130 mutable bool relock; // mutable, as it can be set to false by copying 131 132 UnlockContext& operator=(const UnlockContext&) = default; 133 void CopyFrom(UnlockContext&& rhs); 134 }; 135 136 UnlockContext requestUnlock(); 137 138 bool bumpFee(uint256 hash, uint256& new_hash); 139 bool displayAddress(std::string sAddress); 140 141 static bool isWalletEnabled(); 142 node()143 interfaces::Node& node() const { return m_node; } wallet()144 interfaces::Wallet& wallet() const { return *m_wallet; } clientModel()145 ClientModel& clientModel() const { return *m_client_model; } 146 void setClientModel(ClientModel* client_model); 147 148 QString getWalletName() const; 149 QString getDisplayName() const; 150 151 bool isMultiwallet(); 152 getAddressTableModel()153 AddressTableModel* getAddressTableModel() const { return addressTableModel; } 154 155 void refresh(bool pk_hash_only = false); 156 157 uint256 getLastBlockProcessed() const; 158 159 private: 160 std::unique_ptr<interfaces::Wallet> m_wallet; 161 std::unique_ptr<interfaces::Handler> m_handler_unload; 162 std::unique_ptr<interfaces::Handler> m_handler_status_changed; 163 std::unique_ptr<interfaces::Handler> m_handler_address_book_changed; 164 std::unique_ptr<interfaces::Handler> m_handler_transaction_changed; 165 std::unique_ptr<interfaces::Handler> m_handler_show_progress; 166 std::unique_ptr<interfaces::Handler> m_handler_watch_only_changed; 167 std::unique_ptr<interfaces::Handler> m_handler_can_get_addrs_changed; 168 ClientModel* m_client_model; 169 interfaces::Node& m_node; 170 171 bool fHaveWatchOnly; 172 bool fForceCheckBalanceChanged{false}; 173 174 // Wallet has an options model for wallet-specific options 175 // (transaction fee, for example) 176 OptionsModel *optionsModel; 177 178 AddressTableModel *addressTableModel; 179 TransactionTableModel *transactionTableModel; 180 RecentRequestsTableModel *recentRequestsTableModel; 181 182 // Cache some values to be able to detect changes 183 interfaces::WalletBalances m_cached_balances; 184 EncryptionStatus cachedEncryptionStatus; 185 QTimer* timer; 186 187 // Block hash denoting when the last balance update was done. 188 uint256 m_cached_last_update_tip{}; 189 190 void subscribeToCoreSignals(); 191 void unsubscribeFromCoreSignals(); 192 void checkBalanceChanged(const interfaces::WalletBalances& new_balances); 193 194 Q_SIGNALS: 195 // Signal that balance in wallet changed 196 void balanceChanged(const interfaces::WalletBalances& balances); 197 198 // Encryption status of wallet changed 199 void encryptionStatusChanged(); 200 201 // Signal emitted when wallet needs to be unlocked 202 // It is valid behaviour for listeners to keep the wallet locked after this signal; 203 // this means that the unlocking failed or was cancelled. 204 void requireUnlock(); 205 206 // Fired when a message should be reported to the user 207 void message(const QString &title, const QString &message, unsigned int style); 208 209 // Coins sent: from wallet, to recipient, in (serialized) transaction: 210 void coinsSent(WalletModel* wallet, SendCoinsRecipient recipient, QByteArray transaction); 211 212 // Show progress dialog e.g. for rescan 213 void showProgress(const QString &title, int nProgress); 214 215 // Watch-only address added 216 void notifyWatchonlyChanged(bool fHaveWatchonly); 217 218 // Signal that wallet is about to be removed 219 void unload(); 220 221 // Notify that there are now keys in the keypool 222 void canGetAddressesChanged(); 223 224 void timerTimeout(); 225 226 public Q_SLOTS: 227 /* Starts a timer to periodically update the balance */ 228 void startPollBalance(); 229 230 /* Wallet status might have changed */ 231 void updateStatus(); 232 /* New transaction, or transaction changed status */ 233 void updateTransaction(); 234 /* New, updated or removed address book entry */ 235 void updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status); 236 /* Watch-only added */ 237 void updateWatchOnlyFlag(bool fHaveWatchonly); 238 /* Current, immature or unconfirmed balance might have changed - emit 'balanceChanged' if so */ 239 void pollBalanceChanged(); 240 }; 241 242 #endif // BITCOIN_QT_WALLETMODEL_H 243