wallet.h raw
1 // Copyright (c) 2018-2022 The Limenka 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 LIMENKA_INTERFACES_WALLET_H
6 #define LIMENKA_INTERFACES_WALLET_H
7
8 #include <addresstype.h>
9 #include <common/signmessage.h>
10 #include <consensus/amount.h>
11 #include <interfaces/chain.h>
12 #include <pubkey.h>
13 #include <script/script.h>
14 #include <support/allocators/secure.h>
15 #include <util/fs.h>
16 #include <util/result.h>
17 #include <util/ui_change_type.h>
18
19 #include <cstdint>
20 #include <functional>
21 #include <map>
22 #include <memory>
23 #include <string>
24 #include <tuple>
25 #include <type_traits>
26 #include <utility>
27 #include <vector>
28
29 class CFeeRate;
30 class CKey;
31 enum class FeeReason;
32 enum class OutputType;
33 struct PartiallySignedTransaction;
34 struct bilingual_str;
35 namespace common {
36 enum class PSBTError;
37 } // namespace common
38 namespace node {
39 enum class TransactionError;
40 } // namespace node
41 namespace wallet {
42 class CCoinControl;
43 class CWallet;
44 enum class AddressPurpose;
45 enum isminetype : unsigned int;
46 struct CRecipient;
47 struct WalletContext;
48 using isminefilter = std::underlying_type<isminetype>::type;
49 } // namespace wallet
50
51 enum class WalletBackupFormat {
52 Raw, // Literal db copy
53 DbDump, // DumpWallet plaintext low-level db dump
54 };
55
56 namespace interfaces {
57
58 class Handler;
59 struct WalletAddress;
60 struct WalletBalances;
61 struct WalletTx;
62 struct WalletTxOut;
63 struct WalletTxStatus;
64 struct WalletMigrationResult;
65
66 using WalletOrderForm = std::vector<std::pair<std::string, std::string>>;
67 using WalletValueMap = std::map<std::string, std::string>;
68
69 //! Interface for accessing a wallet.
70 class Wallet
71 {
72 public:
73 virtual ~Wallet() = default;
74
75 //! Encrypt wallet.
76 virtual bool encryptWallet(const SecureString& wallet_passphrase) = 0;
77
78 //! Return whether wallet is encrypted.
79 virtual bool isCrypted() = 0;
80
81 //! Lock wallet.
82 virtual bool lock() = 0;
83
84 //! Unlock wallet.
85 virtual bool unlock(const SecureString& wallet_passphrase) = 0;
86
87 //! Return whether wallet is locked.
88 virtual bool isLocked() = 0;
89
90 //! Change wallet passphrase.
91 virtual bool changeWalletPassphrase(const SecureString& old_wallet_passphrase,
92 const SecureString& new_wallet_passphrase) = 0;
93
94 //! Abort a rescan.
95 virtual void abortRescan() = 0;
96
97 virtual bool canBackupToDbDump() = 0;
98
99 //! Back up wallet.
100 virtual bool backupWallet(const std::string& filename, const WalletBackupFormat format, bilingual_str& error) = 0;
101
102 //! Get wallet name.
103 virtual std::string getWalletName() = 0;
104
105 // Get a new address.
106 virtual util::Result<CTxDestination> getNewDestination(const OutputType type, const std::string& label) = 0;
107
108 //! Get public key.
109 virtual bool getPubKey(const CScript& script, const CKeyID& address, CPubKey& pub_key) = 0;
110
111 //! Sign message
112 virtual SigningResult signMessage(const MessageSignatureFormat format, const std::string& message, const CTxDestination& address, std::string& str_sig) = 0;
113
114 //! Return whether wallet has private key.
115 virtual bool isSpendable(const CTxDestination& dest) = 0;
116
117 //! Return whether wallet has watch only keys.
118 virtual bool haveWatchOnly() = 0;
119
120 //! Add or update address.
121 virtual bool setAddressBook(const CTxDestination& dest, const std::string& name, const std::optional<wallet::AddressPurpose>& purpose) = 0;
122
123 // Remove address.
124 virtual bool delAddressBook(const CTxDestination& dest) = 0;
125
126 //! Look up address in wallet, return whether exists.
127 virtual bool getAddress(const CTxDestination& dest,
128 std::string* name,
129 wallet::isminetype* is_mine,
130 wallet::AddressPurpose* purpose) = 0;
131
132 //! Get wallet address list.
133 virtual std::vector<WalletAddress> getAddresses() = 0;
134
135 //! Get receive requests.
136 virtual std::vector<std::string> getAddressReceiveRequests() = 0;
137
138 //! Save or remove receive request.
139 virtual bool setAddressReceiveRequest(const CTxDestination& dest, const std::string& id, const std::string& value) = 0;
140
141 //! Display address on external signer
142 virtual util::Result<void> displayAddress(const CTxDestination& dest) = 0;
143
144 virtual bool checkAddressForUsage(const std::vector<std::string>& addresses) const = 0;
145 virtual bool findAddressUsage(const std::vector<std::string>& addresses, std::function<void(const std::string&, const WalletTx&, uint32_t)> callback) const = 0;
146
147 //! Lock coin.
148 virtual bool lockCoin(const COutPoint& output, const bool write_to_db) = 0;
149
150 //! Unlock coin.
151 virtual bool unlockCoin(const COutPoint& output) = 0;
152
153 //! Return whether coin is locked.
154 virtual bool isLockedCoin(const COutPoint& output) = 0;
155
156 //! List locked coins.
157 virtual void listLockedCoins(std::vector<COutPoint>& outputs) = 0;
158
159 //! Create transaction.
160 virtual util::Result<CTransactionRef> createTransaction(const std::vector<wallet::CRecipient>& recipients,
161 const wallet::CCoinControl& coin_control,
162 bool sign,
163 int& change_pos,
164 CAmount& fee) = 0;
165
166 //! Commit transaction.
167 virtual void commitTransaction(CTransactionRef tx,
168 WalletValueMap value_map,
169 WalletOrderForm order_form) = 0;
170
171 //! Return whether transaction can be abandoned.
172 virtual bool transactionCanBeAbandoned(const uint256& txid) = 0;
173
174 //! Abandon transaction.
175 virtual bool abandonTransaction(const uint256& txid) = 0;
176
177 //! Return whether transaction can be bumped.
178 virtual bool transactionCanBeBumped(const uint256& txid) = 0;
179
180 //! Create bump transaction.
181 virtual bool createBumpTransaction(const uint256& txid,
182 const wallet::CCoinControl& coin_control,
183 std::vector<bilingual_str>& errors,
184 CAmount& old_fee,
185 CAmount& new_fee,
186 CMutableTransaction& mtx) = 0;
187
188 //! Sign bump transaction.
189 virtual bool signBumpTransaction(CMutableTransaction& mtx) = 0;
190
191 //! Commit bump transaction.
192 virtual bool commitBumpTransaction(const uint256& txid,
193 CMutableTransaction&& mtx,
194 std::vector<bilingual_str>& errors,
195 uint256& bumped_txid) = 0;
196
197 //! Get a transaction.
198 virtual CTransactionRef getTx(const uint256& txid) = 0;
199
200 //! Get transaction information.
201 virtual WalletTx getWalletTx(const uint256& txid) = 0;
202
203 //! Get list of all wallet transactions.
204 virtual std::set<WalletTx> getWalletTxs() = 0;
205
206 //! Try to get updated status for a particular transaction, if possible without blocking.
207 virtual bool tryGetTxStatus(const uint256& txid,
208 WalletTxStatus& tx_status,
209 int& num_blocks,
210 int64_t& block_time) = 0;
211
212 //! Get transaction details.
213 virtual WalletTx getWalletTxDetails(const uint256& txid,
214 WalletTxStatus& tx_status,
215 WalletOrderForm& order_form,
216 bool& in_mempool,
217 int& num_blocks) = 0;
218
219 //! Fill PSBT.
220 virtual std::optional<common::PSBTError> fillPSBT(int sighash_type,
221 bool sign,
222 bool bip32derivs,
223 size_t* n_signed,
224 PartiallySignedTransaction& psbtx,
225 bool& complete) = 0;
226
227 //! Get balances.
228 virtual WalletBalances getBalances() = 0;
229
230 //! Get balances if possible without blocking.
231 virtual bool tryGetBalances(WalletBalances& balances, uint256& block_hash) = 0;
232
233 //! Get balance.
234 virtual CAmount getBalance() = 0;
235
236 //! Full-precision balance as a lambda string (26 decimals, trimmed):
237 //! satoshis plus sub-satoshi fractions plus confidential outputs.
238 virtual std::string getPreciseBalance() = 0;
239
240 //! Sum of unspent confidential output values in attosats.
241 virtual CAmount getConfidentialBalance() = 0;
242
243 //! Send a confidential payment to an lm2 stealth address (amounts in
244 //! attosats). Returns the txid on success.
245 virtual util::Result<uint256> sendStealthPayment(const CTxDestination& dest, CAmount amount_attosats, CAmount fee_attosats, int change_outputs = 1) = 0;
246
247 //! Mint transparent wallet funds into confidential outputs (amounts in
248 //! attosats). Returns the txid on success.
249 virtual util::Result<uint256> mintConfidential(CAmount amount_attosats, CAmount fee_attosats, int output_count = 2) = 0;
250
251 //! Get available balance.
252 virtual CAmount getAvailableBalance(const wallet::CCoinControl& coin_control) = 0;
253
254 //! Return whether transaction input belongs to wallet.
255 virtual wallet::isminetype txinIsMine(const CTxIn& txin) = 0;
256
257 //! Return whether transaction output belongs to wallet.
258 virtual wallet::isminetype txoutIsMine(const CTxOut& txout) = 0;
259
260 //! Return debit amount if transaction input belongs to wallet.
261 virtual CAmount getDebit(const CTxIn& txin, wallet::isminefilter filter) = 0;
262
263 //! Return credit amount if transaction input belongs to wallet.
264 virtual CAmount getCredit(const CTxOut& txout, wallet::isminefilter filter) = 0;
265
266 //! Return AvailableCoins + LockedCoins grouped by wallet address.
267 //! (put change in one group with wallet address)
268 using CoinsList = std::map<CTxDestination, std::vector<std::tuple<COutPoint, WalletTxOut>>>;
269 virtual CoinsList listCoins() = 0;
270
271 //! Return wallet transaction output information.
272 virtual std::vector<WalletTxOut> getCoins(const std::vector<COutPoint>& outputs) = 0;
273
274 //! Get required fee.
275 virtual CAmount getRequiredFee(unsigned int tx_bytes) = 0;
276
277 //! Get minimum fee.
278 virtual CAmount getMinimumFee(unsigned int tx_bytes,
279 const wallet::CCoinControl& coin_control,
280 int* returned_target,
281 FeeReason* reason) = 0;
282
283 //! Get tx confirm target.
284 virtual unsigned int getConfirmTarget() = 0;
285
286 // Return whether HD enabled.
287 virtual bool hdEnabled() = 0;
288
289 // Return whether the wallet is blank.
290 virtual bool canGetAddresses() = 0;
291
292 // Return whether private keys enabled.
293 virtual bool privateKeysDisabled() = 0;
294
295 // Return whether the wallet contains a Taproot scriptPubKeyMan
296 virtual bool taprootEnabled() = 0;
297
298 // Return whether wallet uses an external signer.
299 virtual bool hasExternalSigner() = 0;
300
301 // Get default address type.
302 virtual OutputType getDefaultAddressType() = 0;
303
304 //! Get max tx fee.
305 virtual CAmount getDefaultMaxTxFee() = 0;
306
307 // Remove wallet.
308 virtual void remove() = 0;
309
310 //! Return whether is a legacy wallet
311 virtual bool isLegacy() = 0;
312
313 //! Register handler for unload message.
314 using UnloadFn = std::function<void()>;
315 virtual std::unique_ptr<Handler> handleUnload(UnloadFn fn) = 0;
316
317 //! Register handler for show progress messages.
318 using ShowProgressFn = std::function<void(const std::string& title, int progress)>;
319 virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0;
320
321 //! Register handler for status changed messages.
322 using StatusChangedFn = std::function<void()>;
323 virtual std::unique_ptr<Handler> handleStatusChanged(StatusChangedFn fn) = 0;
324
325 //! Register handler for address book changed messages.
326 using AddressBookChangedFn = std::function<void(const CTxDestination& address,
327 const std::string& label,
328 bool is_mine,
329 wallet::AddressPurpose purpose,
330 ChangeType status)>;
331 virtual std::unique_ptr<Handler> handleAddressBookChanged(AddressBookChangedFn fn) = 0;
332
333 //! Register handler for transaction changed messages.
334 using TransactionChangedFn = std::function<void(const uint256& txid, ChangeType status)>;
335 virtual std::unique_ptr<Handler> handleTransactionChanged(TransactionChangedFn fn) = 0;
336
337 //! Register handler for watchonly changed messages.
338 using WatchOnlyChangedFn = std::function<void(bool have_watch_only)>;
339 virtual std::unique_ptr<Handler> handleWatchOnlyChanged(WatchOnlyChangedFn fn) = 0;
340
341 //! Register handler for keypool changed messages.
342 using CanGetAddressesChangedFn = std::function<void()>;
343 virtual std::unique_ptr<Handler> handleCanGetAddressesChanged(CanGetAddressesChangedFn fn) = 0;
344
345 //! Return pointer to internal wallet class, useful for testing.
346 virtual wallet::CWallet* wallet() { return nullptr; }
347 };
348
349 //! Wallet chain client that in addition to having chain client methods for
350 //! starting up, shutting down, and registering RPCs, also has additional
351 //! methods (called by the GUI) to load and create wallets.
352 class WalletLoader : public ChainClient
353 {
354 public:
355 //! Create new wallet.
356 virtual util::Result<std::unique_ptr<Wallet>> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, std::vector<bilingual_str>& warnings) = 0;
357
358 //! Load existing wallet.
359 virtual util::Result<std::unique_ptr<Wallet>> loadWallet(const std::string& name, std::vector<bilingual_str>& warnings) = 0;
360
361 //! Return default wallet directory.
362 virtual std::string getWalletDir() = 0;
363
364 //! Restore backup wallet
365 virtual util::Result<std::unique_ptr<Wallet>> restoreWallet(const fs::path& backup_file, const std::string& wallet_name, std::vector<bilingual_str>& warnings) = 0;
366
367 //! Migrate a wallet
368 virtual util::Result<WalletMigrationResult> migrateWallet(const std::string& name, const SecureString& passphrase) = 0;
369
370 //! Returns true if wallet stores encryption keys
371 virtual bool isEncrypted(const std::string& wallet_name) = 0;
372
373 //! Return available wallets in wallet directory.
374 virtual std::vector<std::pair<std::string, std::string>> listWalletDir() = 0;
375
376 //! Return interfaces for accessing wallets (if any).
377 virtual std::vector<std::unique_ptr<Wallet>> getWallets() = 0;
378
379 //! Register handler for load wallet messages. This callback is triggered by
380 //! createWallet and loadWallet above, and also triggered when wallets are
381 //! loaded at startup or by RPC.
382 using LoadWalletFn = std::function<void(std::unique_ptr<Wallet> wallet)>;
383 virtual std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) = 0;
384
385 //! Return pointer to internal context, useful for testing.
386 virtual wallet::WalletContext* context() { return nullptr; }
387 };
388
389 //! Information about one wallet address.
390 struct WalletAddress
391 {
392 CTxDestination dest;
393 wallet::isminetype is_mine;
394 wallet::AddressPurpose purpose;
395 std::string name;
396
397 WalletAddress(CTxDestination dest, wallet::isminetype is_mine, wallet::AddressPurpose purpose, std::string name)
398 : dest(std::move(dest)), is_mine(is_mine), purpose(std::move(purpose)), name(std::move(name))
399 {
400 }
401 };
402
403 //! Collection of wallet balances.
404 struct WalletBalances
405 {
406 CAmount balance = 0;
407 CAmount unconfirmed_balance = 0;
408 CAmount immature_balance = 0;
409 bool have_watch_only = false;
410 CAmount watch_only_balance = 0;
411 CAmount unconfirmed_watch_only_balance = 0;
412 CAmount immature_watch_only_balance = 0;
413
414 bool balanceChanged(const WalletBalances& prev) const
415 {
416 return balance != prev.balance || unconfirmed_balance != prev.unconfirmed_balance ||
417 immature_balance != prev.immature_balance || watch_only_balance != prev.watch_only_balance ||
418 unconfirmed_watch_only_balance != prev.unconfirmed_watch_only_balance ||
419 immature_watch_only_balance != prev.immature_watch_only_balance;
420 }
421 };
422
423 // Wallet transaction information.
424 struct WalletTx
425 {
426 CTransactionRef tx;
427 std::vector<wallet::isminetype> txin_is_mine;
428 std::vector<wallet::isminetype> txout_is_mine;
429 std::vector<bool> txout_is_change;
430 std::vector<CTxDestination> txout_address;
431 std::vector<wallet::isminetype> txout_address_is_mine;
432 CAmount credit;
433 CAmount debit;
434 CAmount change;
435 int64_t time;
436 std::map<std::string, std::string> value_map;
437 bool is_coinbase;
438
439 bool operator<(const WalletTx& a) const { return tx->GetHash() < a.tx->GetHash(); }
440 };
441
442 //! Updated transaction status.
443 struct WalletTxStatus
444 {
445 int block_height;
446 int blocks_to_maturity;
447 int depth_in_main_chain;
448 unsigned int time_received;
449 uint32_t lock_time;
450 bool is_trusted;
451 bool is_abandoned;
452 bool is_coinbase;
453 bool is_in_main_chain;
454 // The block containing this transaction is assumed valid
455 bool is_assumed;
456 };
457
458 //! Wallet transaction output.
459 struct WalletTxOut
460 {
461 CTxOut txout;
462 int64_t time;
463 int depth_in_main_chain = -1;
464 bool is_spent = false;
465 };
466
467 //! Migrated wallet info
468 struct WalletMigrationResult
469 {
470 std::unique_ptr<Wallet> wallet;
471 std::optional<std::string> watchonly_wallet_name;
472 std::optional<std::string> solvables_wallet_name;
473 fs::path backup_path;
474 };
475
476 //! Return implementation of Wallet interface. This function is defined in
477 //! dummywallet.cpp and throws if the wallet component is not compiled.
478 std::unique_ptr<Wallet> MakeWallet(wallet::WalletContext& context, const std::shared_ptr<wallet::CWallet>& wallet);
479
480 //! Return implementation of ChainClient interface for a wallet loader. This
481 //! function will be undefined in builds where ENABLE_WALLET is false.
482 std::unique_ptr<WalletLoader> MakeWalletLoader(Chain& chain, ArgsManager& args);
483
484 } // namespace interfaces
485
486 #endif // LIMENKA_INTERFACES_WALLET_H
487