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