forked from bitcoin/bitcoin
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathwallet.h
1141 lines (933 loc) · 53.8 KB
/
wallet.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2021 The Bitcoin Core developers
// Copyright (c) 2014-2025 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_WALLET_WALLET_H
#define BITCOIN_WALLET_WALLET_H
#include <consensus/amount.h>
#include <fs.h>
#include <governance/common.h>
#include <interfaces/chain.h>
#include <interfaces/coinjoin.h>
#include <interfaces/handler.h>
#include <policy/feerate.h>
#include <psbt.h>
#include <saltedhasher.h>
#include <tinyformat.h>
#include <util/message.h>
#include <util/string.h>
#include <util/system.h>
#include <util/strencodings.h>
#include <util/ui_change_type.h>
#include <validationinterface.h>
#include <wallet/coincontrol.h>
#include <wallet/crypter.h>
#include <wallet/coinselection.h>
#include <wallet/receive.h>
#include <wallet/scriptpubkeyman.h>
#include <wallet/spend.h>
#include <wallet/transaction.h>
#include <wallet/walletdb.h>
#include <wallet/walletutil.h>
#include <algorithm>
#include <atomic>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <stdexcept>
#include <stdint.h>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
#include <boost/signals2/signal.hpp>
struct bilingual_str;
struct WalletContext;
using LoadWalletFn = std::function<void(std::unique_ptr<interfaces::Wallet> wallet)>;
//! Explicitly unload and delete the wallet.
// Blocks the current thread after signaling the unload intent so that all
// wallet pointer owners release the wallet.
// Note that, when blocking is not required, the wallet is implicitly unloaded
// by the shared pointer deleter.
void UnloadWallet(std::shared_ptr<CWallet>&& wallet);
bool AddWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet);
bool RemoveWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start, std::vector<bilingual_str>& warnings);
bool RemoveWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet, std::optional<bool> load_on_start);
std::vector<std::shared_ptr<CWallet>> GetWallets(WalletContext& context);
std::shared_ptr<CWallet> GetWallet(WalletContext& context, const std::string& name);
std::shared_ptr<CWallet> LoadWallet(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings);
std::shared_ptr<CWallet> CreateWallet(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings);
std::shared_ptr<CWallet> RestoreWallet(WalletContext& context, const fs::path& backup_file, const std::string& wallet_name, std::optional<bool> load_on_start, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings);
std::unique_ptr<interfaces::Handler> HandleLoadWallet(WalletContext& context, LoadWalletFn load_wallet);
std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
//! -paytxfee default
constexpr CAmount DEFAULT_PAY_TX_FEE = 0;
//! -fallbackfee default
static const CAmount DEFAULT_FALLBACK_FEE = 1000;
//! -discardfee default
static const CAmount DEFAULT_DISCARD_FEE = 10000;
//! -mintxfee default
static const CAmount DEFAULT_TRANSACTION_MINFEE = 1000;
//! -consolidatefeerate default
static const CAmount DEFAULT_CONSOLIDATE_FEERATE{1000}; // 10 sat/vbyte
/**
* maximum fee increase allowed to do partial spend avoidance, even for nodes with this feature disabled by default
*
* A value of -1 disables this feature completely.
* A value of 0 (current default) means to attempt to do partial spend avoidance, and use its results if the fees remain *unchanged*
* A value > 0 means to do partial spend avoidance if the fee difference against a regular coin selection instance is in the range [0..value].
*/
static const CAmount DEFAULT_MAX_AVOIDPARTIALSPEND_FEE = 0;
//! discourage APS fee higher than this amount
constexpr CAmount HIGH_APS_FEE{COIN / 10000};
//! minimum recommended increment for BIP 125 replacement txs
static const CAmount WALLET_INCREMENTAL_RELAY_FEE = 5000;
//! Default for -spendzeroconfchange
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE = true;
//! Default for -walletrejectlongchains
static const bool DEFAULT_WALLET_REJECT_LONG_CHAINS = false;
//! -txconfirmtarget default
static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 6;
static const bool DEFAULT_WALLETBROADCAST = true;
static const bool DEFAULT_DISABLE_WALLET = false;
//! -maxtxfee default
static const CAmount DEFAULT_TRANSACTION_MAXFEE = COIN / 10;
//! Discourage users to set fees higher than this amount (in satoshis) per kB
static const CAmount HIGH_TX_FEE_PER_KB = COIN / 100;
//! -maxtxfee will warn if called with a higher fee than this amount (in satoshis)
static const CAmount HIGH_MAX_TX_FEE = 100 * HIGH_TX_FEE_PER_KB;
//! Pre-calculated constants for input size estimation in *virtual size*
static constexpr size_t DUMMY_NESTED_P2PKH_INPUT_SIZE = 113;
//! if set, all keys will be derived by using BIP39/BIP44
static const bool DEFAULT_USE_HD_WALLET = true;
class CCoinControl;
class CKey;
class COutput;
class CScript;
class CTxDSIn;
class CWalletTx;
struct FeeCalculation;
enum class FeeEstimateMode;
class ReserveDestination;
extern RecursiveMutex cs_main;
/** (client) version numbers for particular wallet features */
struct CompactTallyItem
{
CTxDestination txdest;
CAmount nAmount{0};
std::vector<CInputCoin> vecInputCoins;
CompactTallyItem() = default;
};
static constexpr uint64_t KNOWN_WALLET_FLAGS =
WALLET_FLAG_AVOID_REUSE
| WALLET_FLAG_BLANK_WALLET
| WALLET_FLAG_KEY_ORIGIN_METADATA
| WALLET_FLAG_LAST_HARDENED_XPUB_CACHED
| WALLET_FLAG_DISABLE_PRIVATE_KEYS
| WALLET_FLAG_DESCRIPTORS;
static constexpr uint64_t MUTABLE_WALLET_FLAGS =
WALLET_FLAG_AVOID_REUSE;
static const std::map<std::string,WalletFlags> WALLET_FLAG_MAP{
{"avoid_reuse", WALLET_FLAG_AVOID_REUSE},
{"blank", WALLET_FLAG_BLANK_WALLET},
{"key_origin_metadata", WALLET_FLAG_KEY_ORIGIN_METADATA},
{"last_hardened_xpub_cached", WALLET_FLAG_LAST_HARDENED_XPUB_CACHED},
{"disable_private_keys", WALLET_FLAG_DISABLE_PRIVATE_KEYS},
{"descriptor_wallet", WALLET_FLAG_DESCRIPTORS},
};
extern const std::map<uint64_t,std::string> WALLET_FLAG_CAVEATS;
// Use a macro instead of a function for conditional logging to prevent
// evaluating arguments when logging for the category is not enabled.
#define WalletCJLogPrint(wallet, ...) \
do { \
if (LogAcceptDebug(BCLog::COINJOIN)) { \
wallet->WalletLogPrintf(__VA_ARGS__); \
} \
} while (0)
/** A wrapper to reserve an address from a wallet
*
* ReserveDestination is used to reserve an address. It is passed around
* during the CreateTransaction/CommitTransaction procedure.
*
* Instantiating a ReserveDestination does not reserve an address. To do so,
* GetReservedDestination() needs to be called on the object. Once an address has been
* reserved, call KeepDestination() on the ReserveDestination object to make sure it is not
* returned. Call ReturnDestination() to return the address so it can be re-used (for
* example, if the address was used in a new transaction
* and that transaction was not completed and needed to be aborted).
*
* If an address is reserved and KeepDestination() is not called, then the address will be
* returned when the ReserveDestination goes out of scope.
*/
class ReserveDestination
{
protected:
//! The wallet to reserve from
const CWallet* const pwallet;
//! The ScriptPubKeyMan to reserve from. Based on type when GetReservedDestination is called
ScriptPubKeyMan* m_spk_man{nullptr};
//! The index of the address's key in the keypool
int64_t nIndex{-1};
//! The destination
CTxDestination address;
//! Whether this is from the internal (change output) keypool
bool fInternal{false};
public:
//! Construct a ReserveDestination object. This does NOT reserve an address yet
explicit ReserveDestination(CWallet* pwallet)
: pwallet(pwallet)
{ }
ReserveDestination(const ReserveDestination&) = delete;
ReserveDestination& operator=(const ReserveDestination&) = delete;
//! Destructor. If a key has been reserved and not KeepKey'ed, it will be returned to the keypool
~ReserveDestination()
{
ReturnDestination();
}
//! Reserve an address
bool GetReservedDestination(CTxDestination& pubkey, bool internal);
//! Return reserved address
void ReturnDestination();
//! Keep the address. Do not return its key to the keypool when this object goes out of scope
void KeepDestination();
};
/** Address book data */
class CAddressBookData
{
private:
bool m_change{true};
std::string m_label;
public:
std::string purpose;
CAddressBookData() : purpose("unknown") {}
typedef std::map<std::string, std::string> StringMap;
StringMap destdata;
bool IsChange() const { return m_change; }
const std::string& GetLabel() const { return m_label; }
void SetLabel(const std::string& label) {
m_change = false;
m_label = label;
}
};
struct CRecipient
{
CScript scriptPubKey;
CAmount nAmount;
bool fSubtractFeeFromAmount;
};
struct WalletTxHasher
{
StaticSaltedHasher h;
size_t operator()(const CWalletTx* a) const
{
return h(a->GetHash());
}
};
class WalletRescanReserver; //forward declarations for ScanForWalletTransactions/RescanFromTime
/**
* A CWallet maintains a set of transactions and balances, and provides the ability to create new transactions.
*/
class CWallet final : public WalletStorage, public interfaces::Chain::Notifications
{
private:
CKeyingMaterial vMasterKey GUARDED_BY(cs_wallet);
//! if fOnlyMixingAllowed is true, only mixing should be allowed in unlocked wallet
bool fOnlyMixingAllowed;
bool Unlock(const CKeyingMaterial& vMasterKeyIn, bool fForMixingOnly = false, bool accept_no_keys = false);
std::atomic<bool> fAbortRescan{false}; // reset by WalletRescanReserver::reserve()
std::atomic<bool> fScanningWallet{false}; // controlled by WalletRescanReserver
std::atomic<bool> m_attaching_chain{false};
std::atomic<int64_t> m_scanning_start{0};
std::atomic<double> m_scanning_progress{0};
friend class WalletRescanReserver;
//! the current wallet version: clients below this version are not able to load the wallet
int nWalletVersion GUARDED_BY(cs_wallet){FEATURE_BASE};
int64_t nNextResend = 0;
/** Whether this wallet will submit newly created transactions to the node's mempool and
* prompt rebroadcasts (see ResendWalletTransactions()). */
bool fBroadcastTransactions = false;
// Local time that the tip block was received. Used to schedule wallet rebroadcasts.
std::atomic<int64_t> m_best_block_time {0};
mutable bool fAnonymizableTallyCached = false;
mutable std::vector<CompactTallyItem> vecAnonymizableTallyCached;
mutable bool fAnonymizableTallyCachedNonDenom = false;
mutable std::vector<CompactTallyItem> vecAnonymizableTallyCachedNonDenom;
/**
* Used to keep track of spent outpoints, and
* detect and report conflicts (double-spends or
* mutated transactions where the mutant gets mined).
*/
typedef std::multimap<COutPoint, uint256> TxSpends;
TxSpends mapTxSpends GUARDED_BY(cs_wallet);
void AddToSpends(const COutPoint& outpoint, const uint256& wtxid, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void AddToSpends(const CWalletTx& wtx, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
std::set<COutPoint> setWalletUTXO;
/** Add new UTXOs to the wallet UTXO set
*
* @param[in] tx Transaction to scan eligible UTXOs from
* @param[in] ret_dups Allow UTXOs already in set to be included in return value
* @returns Set of all new UTXOs (eligible to be) added to set */
std::set<COutPoint> AddWalletUTXOs(CTransactionRef tx, bool ret_dups) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
mutable std::map<COutPoint, int> mapOutpointRoundsCache GUARDED_BY(cs_wallet);
/**
* Add a transaction to the wallet, or update it. confirm.block_* should
* be set when the transaction was known to be included in a block. When
* block_hash.IsNull(), then wallet state is not updated in AddToWallet, but
* notifications happen and cached balances are marked dirty.
*
* If fUpdate is true, existing transactions will be updated.
* TODO: One exception to this is that the abandoned state is cleared under the
* assumption that any further notification of a transaction that was considered
* abandoned is an indication that it is not safe to be considered abandoned.
* Abandoned state should probably be more carefully tracked via different
* chain notifications or by checking mempool presence when necessary.
*/
bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, CWalletTx::Confirmation confirm, WalletBatch& batch, bool fUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/** Mark a transaction (and its in-wallet descendants) as conflicting with a particular block. */
void MarkConflicted(const uint256& hashBlock, int conflicting_height, const uint256& hashTx);
/** Mark a transaction's inputs dirty, thus forcing the outputs to be recomputed */
void MarkInputsDirty(const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void SyncTransaction(const CTransactionRef& tx, CWalletTx::Confirmation confirm, WalletBatch& batch, bool update_tx = true) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/** WalletFlags set on this wallet. */
std::atomic<uint64_t> m_wallet_flags{0};
bool SetAddressBookWithDB(WalletBatch& batch, const CTxDestination& address, const std::string& strName, const std::string& strPurpose);
//! Unsets a wallet flag and saves it to disk
void UnsetWalletFlagWithDB(WalletBatch& batch, uint64_t flag);
//! Unset the blank wallet flag and saves it to disk
void UnsetBlankWalletFlag(WalletBatch& batch) override;
// Reset coinjoin and reset key counter
void NewKeyPoolCallback() override;
// Decreases amount of nKeysLeftSinceAutoBackup after KeepDestination
void KeepDestinationCallback(bool erased) override;
/** Interface for accessing chain state. */
interfaces::Chain* m_chain;
/** Interface for accessing CoinJoin state. */
interfaces::CoinJoin::Loader* m_coinjoin_loader;
/** Wallet name: relative directory name or "" for default wallet. */
std::string m_name;
/** Internal database handle. */
std::unique_ptr<WalletDatabase> const m_database;
// A helper function which loops through wallet UTXOs
std::unordered_set<const CWalletTx*, WalletTxHasher> GetSpendableTXs() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* The following is used to keep track of how far behind the wallet is
* from the chain sync, and to allow clients to block on us being caught up.
*
* Processed hash is a pointer on node's tip and doesn't imply that the wallet
* has scanned sequentially all blocks up to this one.
*/
uint256 m_last_block_processed GUARDED_BY(cs_wallet);
/** Pulled from wallet DB ("cj_salt") and used when mixing a random number of rounds.
* This salt is needed to prevent an attacker from learning how many extra times
* the input was mixed based only on information in the blockchain.
*/
uint256 nCoinJoinSalt;
/**
* Populates nCoinJoinSalt with value from database (and migrates salt stored with legacy key).
*/
void InitCJSaltFromDb();
/** Height of last block processed is used by wallet to know depth of transactions
* without relying on Chain interface beyond asynchronous updates. For safety, we
* initialize it to -1. Height is a pointer on node's tip and doesn't imply
* that the wallet has scanned sequentially all blocks up to this one.
*/
int m_last_block_processed_height GUARDED_BY(cs_wallet) = -1;
ScriptPubKeyMan* m_external_spk_managers{nullptr};
ScriptPubKeyMan* m_internal_spk_managers{nullptr};
// Indexed by a unique identifier produced by each ScriptPubKeyMan using
// ScriptPubKeyMan::GetID. In many cases it will be the hash of an internal structure
std::map<uint256, std::unique_ptr<ScriptPubKeyMan>> m_spk_managers;
bool CreateTransactionInternal(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, const CCoinControl& coin_control, FeeCalculation& fee_calc_out, bool sign, int nExtraPayloadSize) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Catch wallet up to current chain, scanning new blocks, updating the best
* block locator and m_last_block_processed, and registering for
* notifications about new blocks and transactions.
*/
static bool AttachChain(const std::shared_ptr<CWallet>& wallet, interfaces::Chain& chain, bilingual_str& error, std::vector<bilingual_str>& warnings);
public:
/**
* Main wallet lock.
* This lock protects all the fields added by CWallet.
*/
mutable RecursiveMutex cs_wallet;
WalletDatabase& GetDatabase() const override
{
assert(static_cast<bool>(m_database));
return *m_database;
}
/**
* Select a set of coins such that nValueRet >= nTargetValue and at least
* all coins from coin_control are selected; never select unconfirmed coins if they are not ours
* param@[out] setCoinsRet Populated with inputs including pre-selected inputs from
* coin_control and Coin Selection if successful.
* param@[out] nValueRet Total value of selected coins including pre-selected ones
* from coin_control and Coin Selection if successful.
*/
bool SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet,
const CCoinControl& coin_control, CoinSelectionParams& coin_selection_params) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/** Get a name for this wallet for logging/debugging purposes.
*/
const std::string& GetName() const { return m_name; }
/**
* Get an existing CoinJoin salt. Will attempt to read database (and migrate legacy salts) if
* nCoinJoinSalt is empty but will skip database read if nCoinJoinSalt is populated.
**/
const uint256& GetCoinJoinSalt();
/**
* Write a new CoinJoin salt. This will directly write the new salt value into the wallet database.
* Ensuring that undesirable behaviour like overwriting the salt of a wallet that already uses CoinJoin
* is the responsibility of the caller.
**/
bool SetCoinJoinSalt(const uint256& cj_salt);
// Map from governance object hash to governance object, they are added by gobject_prepare.
std::map<uint256, Governance::Object> m_gobjects;
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
MasterKeyMap mapMasterKeys;
unsigned int nMasterKeyMaxID = 0;
/** Construct wallet with specified name and database implementation. */
CWallet(interfaces::Chain* chain, interfaces::CoinJoin::Loader* coinjoin_loader, const std::string& name, std::unique_ptr<WalletDatabase> database)
: fOnlyMixingAllowed(false),
m_chain(chain),
m_coinjoin_loader(coinjoin_loader),
m_name(name),
m_database(std::move(database))
{
}
~CWallet()
{
// Should not have slots connected at this point.
assert(NotifyUnload.empty());
}
/** Interface to assert chain access */
bool HaveChain() const { return m_chain ? true : false; }
bool IsCrypted() const;
bool IsLocked(bool fForMixing = false) const override;
bool Lock(bool fForMixing = false);
void UpdateProgress(const std::string& title, int nProgress) override;
/** Map from txid to CWalletTx for all transactions this wallet is
* interested in, including received and sent transactions. */
std::map<uint256, CWalletTx> mapWallet GUARDED_BY(cs_wallet);
typedef std::multimap<int64_t, CWalletTx*> TxItems;
TxItems wtxOrdered;
int64_t nOrderPosNext GUARDED_BY(cs_wallet) = 0;
uint64_t nAccountingEntryNumber = 0;
std::map<CTxDestination, CAddressBookData> m_address_book GUARDED_BY(cs_wallet);
const CAddressBookData* FindAddressBookEntry(const CTxDestination&, bool allow_change = false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/** Set of Coins owned by this wallet that we won't try to spend from. A
* Coin may be locked if it has already been used to fund a transaction
* that hasn't confirmed yet. We wouldn't consider the Coin spent already,
* but also shouldn't try to use it again. */
std::set<COutPoint> setLockedCoins GUARDED_BY(cs_wallet);
int64_t nKeysLeftSinceAutoBackup;
/** Registered interfaces::Chain::Notifications handler. */
std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
/** Interface for accessing chain state. */
interfaces::Chain& chain() const { assert(m_chain); return *m_chain; }
/** Interface for accessing CoinJoin state. */
interfaces::CoinJoin::Loader& coinjoin_loader() { assert(m_coinjoin_loader); return *m_coinjoin_loader; }
/** Interface for availability status of CoinJoin. */
bool coinjoin_available() { return m_coinjoin_loader != nullptr; }
const CWalletTx* GetWalletTx(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool IsTrusted(const CWalletTx& wtx, std::set<uint256>& trusted_parents) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! check whether we support the named feature
bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); return IsFeatureSupported(nWalletVersion, wf); }
/**
* populate vCoins with vector of available COutputs.
*/
void AvailableCoins(std::vector<COutput>& vCoins, const CCoinControl* coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Return list of available coins and locked coins grouped by non-change output address.
*/
std::map<CTxDestination, std::vector<COutput>> ListCoins() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Find non-change parent output.
*/
const CTxOut& FindNonChangeParentOutput(const CTransaction& tx, int output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Shuffle and select coins until nTargetValue is reached while avoiding
* small change; This method is stochastic for some inputs and upon
* completion the coin set and corresponding actual target value is
* assembled
* param@[in] coins Set of UTXOs to consider. These will be categorized into
* OutputGroups and filtered using eligibility_filter before
* selecting coins.
* param@[out] setCoinsRet Populated with the coins selected if successful.
* param@[out] nValueRet Used to return the total value of selected coins.
*/
bool AttemptSelection(const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<COutput> coins, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CoinSelectionParams& coin_selection_params, CoinType nCoinType = CoinType::ALL_COINS) const;
// Coin selection
bool SelectTxDSInsByDenomination(int nDenom, CAmount nValueMax, std::vector<CTxDSIn>& vecTxDSInRet);
bool SelectDenominatedAmounts(CAmount nValueMax, std::set<CAmount>& setAmountsRet) const;
std::vector<CompactTallyItem> SelectCoinsGroupedByAddresses(bool fSkipDenominated = true, bool fAnonymizable = true, bool fSkipUnconfirmed = true, int nMaxOupointsPerAddress = -1) const;
bool HasCollateralInputs(bool fOnlyConfirmed = true) const;
int CountInputsWithAmount(CAmount nInputAmount) const;
// get the CoinJoin chain depth for a given input
int GetRealOutpointCoinJoinRounds(const COutPoint& outpoint, int nRounds = 0) const;
// respect current settings
int GetCappedOutpointCoinJoinRounds(const COutPoint& outpoint) const;
// drop the internal cache to let Get...Rounds recalculate CJ balance from scratch and notify UI
void ClearCoinJoinRoundsCache();
bool IsDenominated(const COutPoint& outpoint) const;
bool IsFullyMixed(const COutPoint& outpoint) const;
bool IsSpent(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
// Whether this or any known UTXO with the same single key has been spent.
bool IsSpentKey(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void SetSpentKeyState(WalletBatch& batch, const uint256& hash, unsigned int n, bool used, std::set<CTxDestination>& tx_destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
std::vector<OutputGroup> GroupOutputs(const std::vector<COutput>& outputs, const CoinSelectionParams& coin_sel_params, const CoinEligibilityFilter& filter, bool positive_only) const;
void RecalculateMixedCredit(const uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool IsLockedCoin(uint256 hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool LockCoin(const COutPoint& output, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool UnlockCoin(const COutPoint& output, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
std::vector<COutPoint> ListLockedCoins() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
std::vector<COutPoint> ListProTxCoins() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
std::vector<COutPoint> ListProTxCoins(const std::set<COutPoint>& utxos) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void LockProTxCoins(const std::set<COutPoint>& utxos, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/*
* Rescan abort properties
*/
void AbortRescan() { fAbortRescan = true; }
bool IsAbortingRescan() const { return fAbortRescan; }
bool IsScanning() const { return fScanningWallet; }
int64_t ScanningDuration() const { return fScanningWallet ? GetTimeMillis() - m_scanning_start : 0; }
double ScanningProgress() const { return fScanningWallet ? (double) m_scanning_progress : 0; }
//! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Upgrade DescriptorCaches
void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; return true; }
//! Adds a destination data tuple to the store, without saving it to disk
void LoadDestData(const CTxDestination& dest, const std::string& key, const std::string& value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Holds a timestamp at which point the wallet is scheduled (externally) to be relocked. Caller must arrange for actual relocking to occur via Lock().
int64_t nRelockTime GUARDED_BY(cs_wallet){0};
// Used to prevent concurrent calls to walletpassphrase RPC.
Mutex m_unlock_mutex;
bool Unlock(const SecureString& strWalletPassphrase, bool fForMixingOnly = false, bool accept_no_keys = false);
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
bool EncryptWallet(const SecureString& strWalletPassphrase);
void GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
unsigned int ComputeTimeSmart(const CWalletTx& wtx) const;
/**
* Increment the next transaction order id
* @return next transaction order id
*/
int64_t IncOrderPosNext(WalletBatch *batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
DBErrors ReorderTransactions();
void MarkDirty();
//! Callback for updating transaction metadata in mapWallet.
//!
//! @param wtx - reference to mapWallet transaction to update
//! @param new_tx - true if wtx is newly inserted, false if it previously existed
//!
//! @return true if wtx is changed and needs to be saved to disk, otherwise false
using UpdateWalletTxFn = std::function<bool(CWalletTx& wtx, bool new_tx)>;
CWalletTx* AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation& confirm, const UpdateWalletTxFn& update_wtx=nullptr, bool fFlushOnClose=true);
bool LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void transactionAddedToMempool(const CTransactionRef& tx, int64_t nAcceptTime, uint64_t mempool_sequence) override;
void blockConnected(const CBlock& block, int height) override;
void blockDisconnected(const CBlock& block, int height) override;
void updatedBlockTip() override;
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update);
struct ScanResult {
enum { SUCCESS, FAILURE, USER_ABORT } status = SUCCESS;
//! Hash and height of most recent block that was successfully scanned.
//! Unset if no blocks were scanned due to read errors or the chain
//! being empty.
uint256 last_scanned_block;
std::optional<int> last_scanned_height;
//! Height of the most recent block that could not be scanned due to
//! read errors or pruning. Will be set if status is FAILURE, unset if
//! status is SUCCESS, and may or may not be set if status is
//! USER_ABORT.
uint256 last_failed_block;
};
ScanResult ScanForWalletTransactions(const uint256& start_block, int start_height, std::optional<int> max_height, const WalletRescanReserver& reserver, bool fUpdate);
void transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason, uint64_t mempool_sequence) override;
void ReacceptWalletTransactions() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void ResendWalletTransactions();
struct Balance {
CAmount m_mine_trusted{0}; //!< Trusted, at depth=GetBalance.min_depth or more
CAmount m_mine_untrusted_pending{0}; //!< Untrusted, but in mempool (pending)
CAmount m_mine_immature{0}; //!< Immature coinbases in the main chain
CAmount m_watchonly_trusted{0};
CAmount m_watchonly_untrusted_pending{0};
CAmount m_watchonly_immature{0};
CAmount m_anonymized{0};
CAmount m_denominated_trusted{0};
CAmount m_denominated_untrusted_pending{0};
};
Balance GetBalance(const int min_depth = 0, const bool avoid_reuse = true, const bool fAddLocked = false) const;
CAmount GetBalanceAnonymized(const CCoinControl& coinControl) const;
CAmount GetAnonymizableBalance(bool fSkipDenominated = false, bool fSkipUnconfirmed = true) const;
float GetAverageAnonymizedRounds() const;
CAmount GetNormalizedAnonymizedBalance() const;
bool GetBudgetSystemCollateralTX(CTransactionRef& tx, uint256 hash, CAmount amount, const COutPoint& outpoint=COutPoint()/*defaults null*/);
CAmount GetAvailableBalance(const CCoinControl* coinControl = nullptr) const;
/**
* Insert additional inputs into the transaction by
* calling CreateTransaction();
*/
bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl);
/** Fetch the inputs and sign with SIGHASH_ALL. */
bool SignTransaction(CMutableTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/** Sign the tx given the input coins and sighash. */
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const;
SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const;
/** Sign the payload of special transaction.
* Because wallet is not aware about special transactions entity,
* but it should work for any its type, we pass there directly a hash of payload.
*/
bool SignSpecialTxPayload(const uint256& hash, const CKeyID& keyid, std::vector<unsigned char>& vchSig) const;
/**
* Fills out a PSBT with information from the wallet. Fills in UTXOs if we have
* them. Tries to sign if sign=true. Sets `complete` if the PSBT is now complete
* (i.e. has all required signatures or signature-parts, and is ready to
* finalize.) Sets `error` and returns false if something goes wrong.
*
* @param[in] psbtx PartiallySignedTransaction to fill in
* @param[out] complete indicates whether the PSBT is now complete
* @param[in] sighash_type the sighash type to use when signing (if PSBT does not specify)
* @param[in] sign whether to sign or not
* @param[in] bip32derivs whether to fill in bip32 derivation information if available
* @param[out] n_signed the number of inputs signed by this wallet
* @param[in] finalize whether to create the final scriptSig
* return error
*/
[[nodiscard]] TransactionError FillPSBT(PartiallySignedTransaction& psbtx,
bool& complete,
int sighash_type = 1 /* SIGHASH_ALL */,
bool sign = true,
bool bip32derivs = true,
size_t* n_signed = nullptr,
bool finalize = true) const;
/**
* Create a new transaction paying the recipients with a set of coins
* selected by SelectCoins(); Also create the change output, when needed
* @note passing nChangePosInOut as -1 will result in setting a random position
*/
bool CreateTransaction(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, const CCoinControl& coin_control, FeeCalculation& fee_calc_out, bool sign = true, int nExtraPayloadSize = 0);
/**
* Submit the transaction to the node's mempool and then relay to peers.
* Should be called after CreateTransaction unless you want to abort
* broadcasting the transaction.
*
* @param[in] tx The transaction to be broadcast.
* @param[in] mapValue key-values to be set on the transaction.
* @param[in] orderForm BIP 70 / BIP 21 order form details to be set on the transaction.
*/
void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm);
bool DummySignTx(CMutableTransaction &txNew, const std::set<CTxOut> &txouts, bool use_max_sig = false) const
{
std::vector<CTxOut> v_txouts(txouts.size());
std::copy(txouts.begin(), txouts.end(), v_txouts.begin());
return DummySignTx(txNew, v_txouts, use_max_sig);
}
bool DummySignTx(CMutableTransaction &txNew, const std::vector<CTxOut> &txouts, bool use_max_sig = false) const;
bool DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig = false) const;
bool ImportScripts(const std::set<CScript> scripts, int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool ImportPubKeys(const std::vector<CKeyID>& ordered_pubkeys, const std::map<CKeyID, CPubKey>& pubkey_map, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins, const bool add_keypool, const bool internal, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool ImportScriptPubKeys(const std::string& label, const std::set<CScript>& script_pub_keys, const bool have_solving_data, const bool apply_label, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
CFeeRate m_pay_tx_fee{DEFAULT_PAY_TX_FEE};
unsigned int m_confirm_target{DEFAULT_TX_CONFIRM_TARGET};
/** Allow Coin Selection to pick unconfirmed UTXOs that were sent from our own wallet if it
* cannot fund the transaction otherwise. */
bool m_spend_zero_conf_change{DEFAULT_SPEND_ZEROCONF_CHANGE};
bool m_allow_fallback_fee{true}; //!< will be false if -fallbackfee=0
CFeeRate m_min_fee{DEFAULT_TRANSACTION_MINFEE}; //!< Override with -mintxfee
/**
* If fee estimation does not have enough data to provide estimates, use this fee instead.
* Has no effect if not using fee estimation
* Override with -fallbackfee
*/
CFeeRate m_fallback_fee{DEFAULT_FALLBACK_FEE};
/** If the cost to spend a change output at this feerate is greater than the value of the
* output itself, just drop it to fees. */
CFeeRate m_discard_rate{DEFAULT_DISCARD_FEE};
/** When the actual feerate is less than the consolidate feerate, we will tend to make transactions which
* consolidate inputs. When the actual feerate is greater than the consolidate feerate, we will tend to make
* transactions which have the lowest fees.
*/
CFeeRate m_consolidate_feerate{DEFAULT_CONSOLIDATE_FEERATE};
/** The maximum fee amount we're willing to pay to prioritize partial spend avoidance. */
CAmount m_max_aps_fee{DEFAULT_MAX_AVOIDPARTIALSPEND_FEE}; //!< note: this is absolute fee, not fee rate
/** Absolute maximum transaction fee (in satoshis) used by default for the wallet */
CAmount m_default_max_tx_fee{DEFAULT_TRANSACTION_MAXFEE};
size_t KeypoolCountExternalKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool TopUpKeyPool(unsigned int kpSize = 0);
std::optional<int64_t> GetOldestKeyPoolTime() const;
std::set<std::set<CTxDestination>> GetAddressGroupings() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
std::map<CTxDestination, CAmount> GetAddressBalances() const;
std::set<CTxDestination> GetLabelAddresses(const std::string& label) const;
/**
* Marks all outputs in each one of the destinations dirty, so their cache is
* reset and does not return outdated information.
*/
void MarkDestinationsDirty(const std::set<CTxDestination>& destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool GetNewDestination(const std::string label, CTxDestination& dest, bilingual_str& error);
bool GetNewChangeDestination(CTxDestination& dest, bilingual_str& error);
isminetype IsMine(const CTxDestination& dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
isminetype IsMine(const CScript& script) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
isminetype IsMine(const CTxIn& txin) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Returns amount of debit if the input matches the
* filter, otherwise returns 0
*/
CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const;
isminetype IsMine(const CTxOut& txout) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const;
bool IsChange(const CTxOut& txout) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool IsChange(const CScript& script) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
CAmount GetChange(const CTxOut& txout) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool IsMine(const CTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/** should probably be renamed to IsRelevantToMe */
bool IsFromMe(const CTransaction& tx) const;
CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const;
/** Returns whether all of the inputs match the filter */
bool IsAllFromMe(const CTransaction& tx, const isminefilter& filter) const;
CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const;
CAmount GetChange(const CTransaction& tx) const;
void chainStateFlushed(const CBlockLocator& loc) override;
DBErrors LoadWallet();
void AutoLockMasternodeCollaterals();
DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose);
bool DelAddressBook(const CTxDestination& address);
bool IsAddressUsed(const CTxDestination& dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool SetAddressUsed(WalletBatch& batch, const CTxDestination& dest, bool used) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
std::vector<std::string> GetAddressReceiveRequests() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool SetAddressReceiveRequest(WalletBatch& batch, const CTxDestination& dest, const std::string& id, const std::string& value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
unsigned int GetKeyPoolSize() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! signify that a particular wallet feature is now used.
void SetMinVersion(enum WalletFeature, WalletBatch* batch_in = nullptr) override;
//! get the current wallet format (the oldest client version guaranteed to understand this wallet)
int GetVersion() const { LOCK(cs_wallet); return nWalletVersion; }
//! Get wallet transactions that conflict with given transaction (spend same outputs)
std::set<uint256> GetConflicts(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Check if a given transaction has any of its outputs spent by another transaction in the wallet
bool HasWalletSpend(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Flush wallet (bitdb flush)
void Flush();
//! Close wallet database
void Close();
/** Wallet is about to be unloaded */
boost::signals2::signal<void ()> NotifyUnload;
/**
* Address book entry changed.
* @note called without lock cs_wallet held.
*/
boost::signals2::signal<void(const CTxDestination& address,
const std::string& label, bool isMine,
const std::string& purpose, ChangeType status)>
NotifyAddressBookChanged;
/**
* Wallet transaction added, removed or updated.
* @note called with lock cs_wallet held.
*/
boost::signals2::signal<void(const uint256& hashTx, ChangeType status)> NotifyTransactionChanged;
/** Show progress e.g. for rescan */
boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress;
/** Watch-only address added */
boost::signals2::signal<void (bool fHaveWatchOnly)> NotifyWatchonlyChanged;
/** Keypool has new keys */
boost::signals2::signal<void ()> NotifyCanGetAddressesChanged;
/** IS-lock received */
boost::signals2::signal<void ()> NotifyISLockReceived;
/** ChainLock received */
boost::signals2::signal<void (int height)> NotifyChainLockReceived;
/**
* Wallet status (encrypted, locked) changed.
* Note: Called without locks held.
*/
boost::signals2::signal<void (CWallet* wallet)> NotifyStatusChanged;
/** Inquire whether this wallet broadcasts transactions. */
bool GetBroadcastTransactions() const { return fBroadcastTransactions; }
/** Set whether this wallet broadcasts transactions. */
void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; }
/** Return whether transaction can be abandoned */
bool TransactionCanBeAbandoned(const uint256& hashTx) const;
/** Return whether transaction can be resent */
bool TransactionCanBeResent(const uint256& hashTx) const;
/* Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent. */
bool AbandonTransaction(const uint256& hashTx);
/* Resend a transaction */
bool ResendTransaction(const uint256& hashTx);
/* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
static std::shared_ptr<CWallet> Create(WalletContext& context, const std::string& name, std::unique_ptr<WalletDatabase> database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings);
/**
* Wallet post-init setup
* Gives the wallet a chance to register repetitive tasks and complete post-init tasks
*/
void postInitProcess();
/* AutoBackup functionality */
static bool InitAutoBackup();
bool AutoBackupWallet(const fs::path& wallet_path, bilingual_str& error_string, std::vector<bilingual_str>& warnings);
bool BackupWallet(const std::string& strDest) const;
/**
* HD Wallet Functions
*/
/* Returns true if HD is enabled */
bool IsHDEnabled() const;
// TODO: move it to scriptpubkeyman
/* Generates a new HD chain */
bool GenerateNewHDChain(const SecureString& secureMnemonic, const SecureString& secureMnemonicPassphrase, const SecureString& secureWalletPassphrase = "");
/* Returns true if the wallet can give out new addresses. This means it has keys in the keypool or can generate new keys */
bool CanGetAddresses(bool internal = false) const;
void notifyTransactionLock(const CTransactionRef &tx, const std::shared_ptr<const llmq::CInstantSendLock>& islock) override;
void notifyChainLock(const CBlockIndex* pindexChainLock, const std::shared_ptr<const llmq::CChainLockSig>& clsig) override;
/** Load a CGovernanceObject into m_gobjects. */
bool LoadGovernanceObject(const Governance::Object& obj) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/** Store a CGovernanceObject in the wallet database. This should only be used by governance objects that are created by this wallet via `gobject prepare`. */
bool WriteGovernanceObject(const Governance::Object& obj) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/** Returns a vector containing pointers to the governance objects in m_gobjects */
std::vector<const Governance::Object*> GetGovernanceObjects() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
* Blocks until the wallet state is up-to-date to /at least/ the current
* chain at the time this function is entered
* Obviously holding cs_main/cs_wallet when going into this call may cause
* deadlock
*/
void BlockUntilSyncedToCurrentChain() const LOCKS_EXCLUDED(::cs_main) EXCLUSIVE_LOCKS_REQUIRED(!cs_wallet);
/** set a single wallet flag */
void SetWalletFlag(uint64_t flags);
/** Unsets a single wallet flag */
void UnsetWalletFlag(uint64_t flag);
/** check if a certain wallet flag is set */
bool IsWalletFlagSet(uint64_t flag) const override;
/** overwrite all flags by the given uint64_t
flags must be uninitialised (or 0)
only known flags may be present */
void InitWalletFlags(uint64_t flags);
/** Loads the flags into the wallet. (used by LoadWallet) */
bool LoadWalletFlags(uint64_t flags);
/** Determine if we are a legacy wallet */
bool IsLegacy() const;
/** Returns a bracketed wallet name for displaying in logs, will return [default wallet] if the wallet has no name */
const std::string GetDisplayName() const override {
std::string wallet_name = GetName().length() == 0 ? "default wallet" : GetName();
return strprintf("[%s]", wallet_name);
};
/** Prepends the wallet name in logging output to ease debugging in multi-wallet use cases */
template<typename... Params>
void WalletLogPrintf(std::string fmt, Params... parameters) const {
LogPrintf(("%s " + fmt).c_str(), GetDisplayName(), parameters...);
};
/** Upgrade the wallet */
bool UpgradeWallet(int version, bilingual_str& error);
/** Upgrade non-HD wallet to HD wallet */
bool UpgradeToHD(const SecureString& secureMnemonic, const SecureString& secureMnemonicPassphrase, const SecureString& secureWalletPassphrase, bilingual_str& error);