diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 97ab81d5b..428fe75bd 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -1,1683 +1,1683 @@
 // Copyright (c) 2009-2010 Satoshi Nakamoto
 // Copyright (c) 2009-2016 The Bitcoin Core developers
 // Copyright (c) 2018-2020 The Bitcoin 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 <amount.h>
 #include <interfaces/chain.h>
 #include <interfaces/handler.h>
 #include <outputtype.h>
 #include <primitives/blockhash.h>
 #include <streams.h>
 #include <tinyformat.h>
 #include <ui_interface.h>
 #include <util/strencodings.h>
 #include <util/system.h>
 #include <validationinterface.h>
 #include <wallet/coinselection.h>
 #include <wallet/crypter.h>
 #include <wallet/ismine.h>
 #include <wallet/rpcwallet.h>
 #include <wallet/walletdb.h>
 #include <wallet/walletutil.h>
 
 #include <algorithm>
 #include <atomic>
 #include <cstdint>
 #include <map>
 #include <memory>
 #include <set>
 #include <stdexcept>
 #include <string>
 #include <utility>
 #include <vector>
 
 #include <boost/signals2/signal.hpp>
 
 //! Explicitly unload and delete the wallet.
 //! Blocks the current thread after signaling the unload intent so that all
 //! wallet clients 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(const std::shared_ptr<CWallet> &wallet);
 bool RemoveWallet(const std::shared_ptr<CWallet> &wallet);
 bool HasWallets();
 std::vector<std::shared_ptr<CWallet>> GetWallets();
 std::shared_ptr<CWallet> GetWallet(const std::string &name);
 std::shared_ptr<CWallet> LoadWallet(const CChainParams &chainParams,
                                     interfaces::Chain &chain,
                                     const WalletLocation &location,
                                     std::string &error, std::string &warning);
 
 enum class WalletCreationStatus { SUCCESS, CREATION_FAILED, ENCRYPTION_FAILED };
 
 WalletCreationStatus
 CreateWallet(const CChainParams &params, interfaces::Chain &chain,
              const SecureString &passphrase, uint64_t wallet_creation_flags,
              const std::string &name, std::string &error, std::string &warning,
              std::shared_ptr<CWallet> &result);
 
 //! Default for -keypool
 static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
 //! -paytxfee default
 constexpr Amount DEFAULT_PAY_TX_FEE = Amount::zero();
 //! -fallbackfee default
 static const Amount DEFAULT_FALLBACK_FEE(20000 * SATOSHI);
 //! -mintxfee default
 static const Amount DEFAULT_TRANSACTION_MINFEE_PER_KB = 1000 * SATOSHI;
 //! minimum recommended increment for BIP 125 replacement txs
 static const Amount WALLET_INCREMENTAL_RELAY_FEE(5000 * SATOSHI);
 //! Default for -spendzeroconfchange
 static const bool DEFAULT_SPEND_ZEROCONF_CHANGE = true;
 //! Default for -walletrejectlongchains
 static const bool DEFAULT_WALLET_REJECT_LONG_CHAINS = false;
 //! Default for -avoidpartialspends
 static const bool DEFAULT_AVOIDPARTIALSPENDS = false;
 static const bool DEFAULT_WALLETBROADCAST = true;
 static const bool DEFAULT_DISABLE_WALLET = false;
 //! -maxtxfee default
 constexpr Amount DEFAULT_TRANSACTION_MAXFEE{COIN / 10};
 //! Discourage users to set fees higher than this amount (in satoshis) per kB
 constexpr Amount HIGH_TX_FEE_PER_KB{COIN / 100};
 //! -maxtxfee will warn if called with a higher fee than this amount (in
 //! satoshis)
 constexpr Amount HIGH_MAX_TX_FEE{100 * HIGH_TX_FEE_PER_KB};
 
 class CChainParams;
 class CCoinControl;
 class COutput;
 class CScript;
 class CTxMemPool;
 class CWalletTx;
 class ReserveDestination;
 
 /** (client) version numbers for particular wallet features */
 enum WalletFeature {
     // the earliest version new wallets supports (only useful for
     // getwalletinfo's clientversion output)
     FEATURE_BASE = 10500,
 
     // wallet encryption
     FEATURE_WALLETCRYPT = 40000,
     // compressed public keys
     FEATURE_COMPRPUBKEY = 60000,
 
     // Hierarchical key derivation after BIP32 (HD Wallet)
     FEATURE_HD = 130000,
 
     // Wallet with HD chain split (change outputs will use m/0'/1'/k)
     FEATURE_HD_SPLIT = 160300,
 
     // Wallet without a default key written
     FEATURE_NO_DEFAULT_KEY = 190700,
 
     // Upgraded to HD SPLIT and can have a pre-split keypool
     FEATURE_PRE_SPLIT_KEYPOOL = 200300,
 
     FEATURE_LATEST = FEATURE_PRE_SPLIT_KEYPOOL,
 };
 
 //! Default for -addresstype
 constexpr OutputType DEFAULT_ADDRESS_TYPE{OutputType::LEGACY};
 
 //! Default for -changetype
 constexpr OutputType DEFAULT_CHANGE_TYPE{OutputType::CHANGE_AUTO};
 
 enum WalletFlags : uint64_t {
     // Wallet flags in the upper section (> 1 << 31) will lead to not opening
     // the wallet if flag is unknown.
     // Unknown wallet flags in the lower section <= (1 << 31) will be tolerated.
 
     // will categorize coins as clean (not reused) and dirty (reused), and
     // handle
     // them with privacy considerations in mind
     WALLET_FLAG_AVOID_REUSE = (1ULL << 0),
 
     // Indicates that the metadata has already been upgraded to contain key
     // origins
     WALLET_FLAG_KEY_ORIGIN_METADATA = (1ULL << 1),
 
     // Will enforce the rule that the wallet can't contain any private keys
     // (only watch-only/pubkeys).
     WALLET_FLAG_DISABLE_PRIVATE_KEYS = (1ULL << 32),
 
     //! Flag set when a wallet contains no HD seed and no private keys, scripts,
     //! addresses, and other watch only things, and is therefore "blank."
     //!
     //! The only function this flag serves is to distinguish a blank wallet from
     //! a newly created wallet when the wallet database is loaded, to avoid
     //! initialization that should only happen on first run.
     //!
     //! This flag is also a mandatory flag to prevent previous versions of
     //! bitcoin from opening the wallet, thinking it was newly created, and
     //! then improperly reinitializing it.
     WALLET_FLAG_BLANK_WALLET = (1ULL << 33),
 };
 
 static constexpr uint64_t KNOWN_WALLET_FLAGS =
     WALLET_FLAG_AVOID_REUSE | WALLET_FLAG_BLANK_WALLET |
     WALLET_FLAG_KEY_ORIGIN_METADATA | WALLET_FLAG_DISABLE_PRIVATE_KEYS;
 
 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},
     {"disable_private_keys", WALLET_FLAG_DISABLE_PRIVATE_KEYS},
 };
 
 extern const std::map<uint64_t, std::string> WALLET_FLAG_CAVEATS;
 
 /**
  * A key from a CWallet's keypool
  *
  * The wallet holds one (for pre HD-split wallets) or several keypools. These
  * are sets of keys that have not yet been used to provide addresses or receive
  * change.
  *
  * The Bitcoin ABC wallet was originally a collection of unrelated private
  * keys with their associated addresses. If a non-HD wallet generated a
  * key/address, gave that address out and then restored a backup from before
  * that key's generation, then any funds sent to that address would be
  * lost definitively.
  *
  * The keypool was implemented to avoid this scenario (commit: 10384941). The
  * wallet would generate a set of keys (100 by default). When a new public key
  * was required, either to give out as an address or to use in a change output,
  * it would be drawn from the keypool. The keypool would then be topped up to
  * maintain 100 keys. This ensured that as long as the wallet hadn't used more
  * than 100 keys since the previous backup, all funds would be safe, since a
  * restored wallet would be able to scan for all owned addresses.
  *
  * A keypool also allowed encrypted wallets to give out addresses without
  * having to be decrypted to generate a new private key.
  *
  * With the introduction of HD wallets (commit: f1902510), the keypool
  * essentially became an address look-ahead pool. Restoring old backups can no
  * longer definitively lose funds as long as the addresses used were from the
  * wallet's HD seed (since all private keys can be rederived from the seed).
  * However, if many addresses were used since the backup, then the wallet may
  * not know how far ahead in the HD chain to look for its addresses. The
  * keypool is used to implement a 'gap limit'. The keypool maintains a set of
  * keys (by default 1000) ahead of the last used key and scans for the
  * addresses of those keys.  This avoids the risk of not seeing transactions
  * involving the wallet's addresses, or of re-using the same address.
  *
  * The HD-split wallet feature added a second keypool (commit: 02592f4c). There
  * is an external keypool (for addresses to hand out) and an internal keypool
  * (for change addresses).
  *
  * Keypool keys are stored in the wallet/keystore's keymap. The keypool data is
  * stored as sets of indexes in the wallet (setInternalKeyPool,
  * setExternalKeyPool and set_pre_split_keypool), and a map from the key to the
  * index (m_pool_key_to_index). The CKeyPool object is used to
  * serialize/deserialize the pool data to/from the database.
  */
 class CKeyPool {
 public:
     //! The time at which the key was generated. Set in AddKeypoolPubKeyWithDB
     int64_t nTime;
     //! The public key
     CPubKey vchPubKey;
     //! Whether this keypool entry is in the internal keypool (for change
     //! outputs)
     bool fInternal;
     //! Whether this key was generated for a keypool before the wallet was
     //! upgraded to HD-split
     bool m_pre_split;
 
     CKeyPool();
     CKeyPool(const CPubKey &vchPubKeyIn, bool internalIn);
 
     ADD_SERIALIZE_METHODS;
 
     template <typename Stream, typename Operation>
     inline void SerializationOp(Stream &s, Operation ser_action) {
         int nVersion = s.GetVersion();
         if (!(s.GetType() & SER_GETHASH)) {
             READWRITE(nVersion);
         }
 
         READWRITE(nTime);
         READWRITE(vchPubKey);
         if (ser_action.ForRead()) {
             try {
                 READWRITE(fInternal);
             } catch (std::ios_base::failure &) {
                 /**
                  * flag as external address if we can't read the internal
                  * boolean (this will be the case for any wallet before the HD
                  * chain split version)
                  */
                 fInternal = false;
             }
             try {
                 READWRITE(m_pre_split);
             } catch (std::ios_base::failure &) {
                 /**
                  * flag as postsplit address if we can't read the m_pre_split
                  * boolean (this will be the case for any wallet that upgrades
                  * to HD chain split)
                  */
                 m_pre_split = false;
             }
         } else {
             READWRITE(fInternal);
             READWRITE(m_pre_split);
         }
     }
 };
 
 /**
  * A wrapper to reserve an address from a wallet
  *
  * ReserveDestination is used to reserve an address.
  * It is currently only used inside of CreateTransaction.
  *
  * 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
     CWallet *pwallet;
     //! The index of the address's key in the keypool
     int64_t nIndex{-1};
     //! The public key for the address
     CPubKey vchPubKey;
     //! 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 *pwalletIn) { pwallet = pwalletIn; }
 
     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(const OutputType type, CTxDestination &pubkey,
                                 bool internal);
     //! Return reserved address
     void ReturnDestination();
     //! Keep the address. Do not return it's key to the keypool when this object
     //! goes out of scope
     void KeepDestination();
 };
 
 /** Address book data */
 class CAddressBookData {
 public:
     std::string name;
     std::string purpose;
 
     CAddressBookData() : purpose("unknown") {}
 
     typedef std::map<std::string, std::string> StringMap;
     StringMap destdata;
 };
 
 struct CRecipient {
     CScript scriptPubKey;
     Amount nAmount;
     bool fSubtractFeeFromAmount;
 };
 
 typedef std::map<std::string, std::string> mapValue_t;
 
 static inline void ReadOrderPos(int64_t &nOrderPos, mapValue_t &mapValue) {
     if (!mapValue.count("n")) {
         // TODO: calculate elsewhere
         nOrderPos = -1;
         return;
     }
 
     nOrderPos = atoi64(mapValue["n"].c_str());
 }
 
 static inline void WriteOrderPos(const int64_t &nOrderPos,
                                  mapValue_t &mapValue) {
     if (nOrderPos == -1) {
         return;
     }
     mapValue["n"] = i64tostr(nOrderPos);
 }
 
 struct COutputEntry {
     CTxDestination destination;
     Amount amount;
     int vout;
 };
 
 /**
  * Legacy class used for deserializing vtxPrev for backwards compatibility.
  * vtxPrev was removed in commit 93a18a3650292afbb441a47d1fa1b94aeb0164e3,
  * but old wallet.dat files may still contain vtxPrev vectors of CMerkleTxs.
  * These need to get deserialized for field alignment when deserializing
  * a CWalletTx, but the deserialized values are discarded.
  */
 class CMerkleTx {
 public:
     template <typename Stream> void Unserialize(Stream &s) {
         CTransactionRef tx;
         BlockHash hashBlock;
         std::vector<uint256> vMerkleBranch;
         int nIndex = 0;
 
         s >> tx >> hashBlock >> vMerkleBranch >> nIndex;
     }
 };
 
 // Get the marginal bytes of spending the specified output
 int CalculateMaximumSignedInputSize(const CTxOut &txout, const CWallet *pwallet,
                                     bool use_max_sig = false);
 
 /**
  * A transaction with a bunch of additional info that only the owner cares
  * about. It includes any unrecorded transactions needed to link it back to the
  * block chain.
  */
 class CWalletTx {
 private:
     const CWallet *pwallet;
 
     /** Constant used in hashBlock to indicate tx has been abandoned */
     static const BlockHash ABANDON_HASH;
 
 public:
     /**
      * Key/value map with information about the transaction.
      *
      * The following keys can be read and written through the map and are
      * serialized in the wallet database:
      *
      *     "comment", "to"   - comment strings provided to sendtoaddress,
      *                         and sendmany wallet RPCs
      *     "replaces_txid"   - txid (as HexStr) of transaction replaced by
      *                         bumpfee on transaction created by bumpfee
      *     "replaced_by_txid" - txid (as HexStr) of transaction created by
      *                         bumpfee on transaction replaced by bumpfee
      *     "from", "message" - obsolete fields that could be set in UI prior to
      *                         2011 (removed in commit 4d9b223)
      *
      * The following keys are serialized in the wallet database, but shouldn't
      * be read or written through the map (they will be temporarily added and
      * removed from the map during serialization):
      *
      *     "fromaccount"     - serialized strFromAccount value
      *     "n"               - serialized nOrderPos value
      *     "timesmart"       - serialized nTimeSmart value
      *     "spent"           - serialized vfSpent value that existed prior to
      *                         2014 (removed in commit 93a18a3)
      */
     mapValue_t mapValue;
     std::vector<std::pair<std::string, std::string>> vOrderForm;
     unsigned int fTimeReceivedIsTxTime;
     //! time received by this node
     unsigned int nTimeReceived;
     /**
      * Stable timestamp that never changes, and reflects the order a transaction
      * was added to the wallet. Timestamp is based on the block time for a
      * transaction added as part of a block, or else the time when the
      * transaction was received if it wasn't part of a block, with the timestamp
      * adjusted in both cases so timestamp order matches the order transactions
      * were added to the wallet. More details can be found in
      * CWallet::ComputeTimeSmart().
      */
     unsigned int nTimeSmart;
     /**
      * From me flag is set to 1 for transactions that were created by the wallet
      * on this bitcoin node, and set to 0 for transactions that were created
      * externally and came in through the network or sendrawtransaction RPC.
      */
-    char fFromMe;
+    bool fFromMe;
     //! position in ordered transaction list
     int64_t nOrderPos;
     std::multimap<int64_t, CWalletTx *>::const_iterator m_it_wtxOrdered;
 
     // memory only
     enum AmountType {
         DEBIT,
         CREDIT,
         IMMATURE_CREDIT,
         AVAILABLE_CREDIT,
         AMOUNTTYPE_ENUM_ELEMENTS
     };
     Amount GetCachableAmount(AmountType type, const isminefilter &filter,
                              bool recalculate = false) const;
     mutable CachableAmount m_amounts[AMOUNTTYPE_ENUM_ELEMENTS];
     mutable bool fChangeCached;
     mutable bool fInMempool;
     mutable Amount nChangeCached;
 
     CWalletTx(const CWallet *pwalletIn, CTransactionRef arg)
         : tx(std::move(arg)), hashBlock(BlockHash()), nIndex(-1) {
         Init(pwalletIn);
     }
 
     void Init(const CWallet *pwalletIn) {
         pwallet = pwalletIn;
         mapValue.clear();
         vOrderForm.clear();
         fTimeReceivedIsTxTime = false;
         nTimeReceived = 0;
         nTimeSmart = 0;
         fFromMe = false;
         fChangeCached = false;
         fInMempool = false;
         nChangeCached = Amount::zero();
         nOrderPos = -1;
     }
 
     CTransactionRef tx;
     BlockHash hashBlock;
     /**
      * An nIndex == -1 means that hashBlock (in nonzero) refers to the earliest
      * block in the chain we know this or any in-wallet dependency conflicts
      * with. Older clients interpret nIndex == -1 as unconfirmed for backward
      * compatibility.
      */
     int nIndex;
 
     template <typename Stream> void Serialize(Stream &s) const {
         mapValue_t mapValueCopy = mapValue;
 
         mapValueCopy["fromaccount"] = "";
         WriteOrderPos(nOrderPos, mapValueCopy);
         if (nTimeSmart) {
             mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart);
         }
 
         //! Used to be vMerkleBranch
         std::vector<char> dummy_vector1;
         //! Used to be vtxPrev
         std::vector<char> dummy_vector2;
         //! Used to be fSpent
-        char dummy_char = false;
+        bool dummy_bool = false;
         s << tx << hashBlock << dummy_vector1 << nIndex << dummy_vector2
           << mapValueCopy << vOrderForm << fTimeReceivedIsTxTime
-          << nTimeReceived << fFromMe << dummy_char;
+          << nTimeReceived << fFromMe << dummy_bool;
     }
 
     template <typename Stream> void Unserialize(Stream &s) {
         Init(nullptr);
 
         //! Used to be vMerkleBranch
         std::vector<uint256> dummy_vector1;
         //! Used to be vtxPrev
         std::vector<CMerkleTx> dummy_vector2;
         //! Used to be fSpent
-        char dummy_char;
+        bool dummy_bool;
         s >> tx >> hashBlock >> dummy_vector1 >> nIndex >> dummy_vector2 >>
             mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >>
-            fFromMe >> dummy_char;
+            fFromMe >> dummy_bool;
 
         ReadOrderPos(nOrderPos, mapValue);
         nTimeSmart = mapValue.count("timesmart")
                          ? (unsigned int)atoi64(mapValue["timesmart"])
                          : 0;
 
         mapValue.erase("fromaccount");
         mapValue.erase("spent");
         mapValue.erase("n");
         mapValue.erase("timesmart");
     }
 
     void SetTx(CTransactionRef arg) { tx = std::move(arg); }
 
     //! make sure balances are recalculated
     void MarkDirty() {
         m_amounts[DEBIT].Reset();
         m_amounts[CREDIT].Reset();
         m_amounts[IMMATURE_CREDIT].Reset();
         m_amounts[AVAILABLE_CREDIT].Reset();
         fChangeCached = false;
     }
 
     void BindWallet(CWallet *pwalletIn) {
         pwallet = pwalletIn;
         MarkDirty();
     }
 
     //! filter decides which addresses will count towards the debit
     Amount GetDebit(const isminefilter &filter) const;
     Amount GetCredit(interfaces::Chain::Lock &locked_chain,
                      const isminefilter &filter) const;
     Amount GetImmatureCredit(interfaces::Chain::Lock &locked_chain,
                              bool fUseCache = true) const;
     // TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
     // annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The
     // annotation "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid
     // having to resolve the issue of member access into incomplete type
     // CWallet.
     Amount GetAvailableCredit(interfaces::Chain::Lock &locked_chain,
                               bool fUseCache = true,
                               const isminefilter &filter = ISMINE_SPENDABLE)
         const NO_THREAD_SAFETY_ANALYSIS;
     Amount GetImmatureWatchOnlyCredit(interfaces::Chain::Lock &locked_chain,
                                       const bool fUseCache = true) const;
     Amount GetChange() const;
 
     // Get the marginal bytes if spending the specified output from this
     // transaction
     int GetSpendSize(unsigned int out, bool use_max_sig = false) const {
         return CalculateMaximumSignedInputSize(tx->vout[out], pwallet,
                                                use_max_sig);
     }
 
     void GetAmounts(std::list<COutputEntry> &listReceived,
                     std::list<COutputEntry> &listSent, Amount &nFee,
                     const isminefilter &filter) const;
 
     bool IsFromMe(const isminefilter &filter) const {
         return GetDebit(filter) > Amount::zero();
     }
 
     // True if only scriptSigs are different
     bool IsEquivalentTo(const CWalletTx &tx) const;
 
     bool InMempool() const;
     bool IsTrusted(interfaces::Chain::Lock &locked_chain) const;
 
     int64_t GetTxTime() const;
 
     // Pass this transaction to node for mempool insertion and relay to peers if
     // flag set to true
     bool SubmitMemoryPoolAndRelay(std::string &err_string, bool relay);
 
     // TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
     // annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The annotation
     // "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid having to
     // resolve the issue of member access into incomplete type CWallet. Note
     // that we still have the runtime check "AssertLockHeld(pwallet->cs_wallet)"
     // in place.
     std::set<TxId> GetConflicts() const NO_THREAD_SAFETY_ANALYSIS;
 
     void SetMerkleBranch(const BlockHash &block_hash, int posInBlock);
 
     /**
      * Return depth of transaction in blockchain:
      * <0  : conflicts with a transaction this deep in the blockchain
      *  0  : in memory pool, waiting to be included in a block
      * >=1 : this many blocks deep in the main chain
      */
     int GetDepthInMainChain(interfaces::Chain::Lock &locked_chain) const;
     bool IsInMainChain(interfaces::Chain::Lock &locked_chain) const {
         return GetDepthInMainChain(locked_chain) > 0;
     }
 
     /**
      * @return number of blocks to maturity for this transaction:
      *  0 : is not a coinbase transaction, or is a mature coinbase transaction
      * >0 : is a coinbase transaction which matures in this many blocks
      */
     int GetBlocksToMaturity(interfaces::Chain::Lock &locked_chain) const;
     bool hashUnset() const {
         return (hashBlock.IsNull() || hashBlock == ABANDON_HASH);
     }
     bool isAbandoned() const { return (hashBlock == ABANDON_HASH); }
     void setAbandoned() { hashBlock = ABANDON_HASH; }
 
     TxId GetId() const { return tx->GetId(); }
     bool IsCoinBase() const { return tx->IsCoinBase(); }
     bool IsImmatureCoinBase(interfaces::Chain::Lock &locked_chain) const;
 };
 
 class COutput {
 public:
     const CWalletTx *tx;
     int i;
     int nDepth;
 
     /**
      * Pre-computed estimated size of this output as a fully-signed input in a
      * transaction. Can be -1 if it could not be calculated.
      */
     int nInputBytes;
 
     /** Whether we have the private keys to spend this output */
     bool fSpendable;
 
     /** Whether we know how to spend this output, ignoring the lack of keys */
     bool fSolvable;
 
     /**
      * Whether to use the maximum sized, 72 byte signature when calculating the
      * size of the input spend. This should only be set when watch-only outputs
      * are allowed.
      */
     bool use_max_sig;
 
     /**
      * Whether this output is considered safe to spend. Unconfirmed transactions
      * from outside keys are considered unsafe and will not be used to fund new
      * spending transactions.
      */
     bool fSafe;
 
     COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn,
             bool fSolvableIn, bool fSafeIn, bool use_max_sig_in = false) {
         tx = txIn;
         i = iIn;
         nDepth = nDepthIn;
         fSpendable = fSpendableIn;
         fSolvable = fSolvableIn;
         fSafe = fSafeIn;
         nInputBytes = -1;
         use_max_sig = use_max_sig_in;
         // If known and signable by the given wallet, compute nInputBytes
         // Failure will keep this value -1
         if (fSpendable && tx) {
             nInputBytes = tx->GetSpendSize(i, use_max_sig);
         }
     }
 
     std::string ToString() const;
 
     inline CInputCoin GetInputCoin() const {
         return CInputCoin(tx->tx, i, nInputBytes);
     }
 };
 
 struct CoinSelectionParams {
     bool use_bnb = true;
     size_t change_output_size = 0;
     size_t change_spend_size = 0;
     CFeeRate effective_fee = CFeeRate(Amount::zero());
     size_t tx_noinputs_size = 0;
 
     CoinSelectionParams(bool use_bnb_, size_t change_output_size_,
                         size_t change_spend_size_, CFeeRate effective_fee_,
                         size_t tx_noinputs_size_)
         : use_bnb(use_bnb_), change_output_size(change_output_size_),
           change_spend_size(change_spend_size_), effective_fee(effective_fee_),
           tx_noinputs_size(tx_noinputs_size_) {}
     CoinSelectionParams() {}
 };
 
 // forward declarations for ScanForWalletTransactions/RescanFromTime
 class WalletRescanReserver;
 
 /**
  * A CWallet is an extension of a keystore, which also maintains a set of
  * transactions and balances, and provides the ability to create new
  * transactions.
  */
 class CWallet final : public FillableSigningProvider,
                       public interfaces::Chain::Notifications {
 private:
     CKeyingMaterial vMasterKey GUARDED_BY(cs_KeyStore);
 
     //! if fUseCrypto is true, mapKeys must be empty
     //! if fUseCrypto is false, vMasterKey must be empty
     std::atomic<bool> fUseCrypto;
 
     //! keeps track of whether Unlock has run a thorough check before
     bool fDecryptionThoroughlyChecked;
 
     using CryptedKeyMap =
         std::map<CKeyID, std::pair<CPubKey, std::vector<uint8_t>>>;
     using WatchOnlySet = std::set<CScript>;
     using WatchKeyMap = std::map<CKeyID, CPubKey>;
 
     bool SetCrypted();
 
     //! will encrypt previously unencrypted keys
     bool EncryptKeys(CKeyingMaterial &vMasterKeyIn);
 
     bool Unlock(const CKeyingMaterial &vMasterKeyIn,
                 bool accept_no_keys = false);
     CryptedKeyMap mapCryptedKeys GUARDED_BY(cs_KeyStore);
     WatchOnlySet setWatchOnly GUARDED_BY(cs_KeyStore);
     WatchKeyMap mapWatchKeys GUARDED_BY(cs_KeyStore);
 
     bool AddCryptedKeyInner(const CPubKey &vchPubKey,
                             const std::vector<uint8_t> &vchCryptedSecret);
     bool AddKeyPubKeyInner(const CKey &key, const CPubKey &pubkey);
 
     std::atomic<bool> fAbortRescan{false};
     // controlled by WalletRescanReserver
     std::atomic<bool> fScanningWallet{false};
     std::atomic<int64_t> m_scanning_start{0};
     std::atomic<double> m_scanning_progress{0};
     std::mutex mutexScanning;
     friend class WalletRescanReserver;
 
     WalletBatch *encrypted_batch GUARDED_BY(cs_wallet) = nullptr;
 
     //! the current wallet version: clients below this version are not able to
     //! load the wallet
     int nWalletVersion GUARDED_BY(cs_wallet) = FEATURE_BASE;
 
     //! the maximum wallet format version: memory-only variable that specifies
     //! to what version this wallet may be upgraded
     int nWalletMaxVersion GUARDED_BY(cs_wallet) = FEATURE_BASE;
 
     int64_t nNextResend = 0;
     int64_t nLastResend = 0;
     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};
 
     /**
      * 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, TxId> TxSpends;
     TxSpends mapTxSpends GUARDED_BY(cs_wallet);
     void AddToSpends(const COutPoint &outpoint, const TxId &wtxid)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     void AddToSpends(const TxId &wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     /**
      * Add a transaction to the wallet, or update it. pIndex and posInBlock
      * should be set when the transaction was known to be included in a
      * block. When *pIndex == nullptr, 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 posInBlock signals or by checking mempool presence
      * when necessary.
      */
     bool AddToWalletIfInvolvingMe(const CTransactionRef &tx,
                                   const BlockHash &block_hash, int posInBlock,
                                   bool fUpdate)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     /**
      * Mark a transaction (and its in-wallet descendants) as conflicting with a
      * particular block.
      */
     void MarkConflicted(const BlockHash &hashBlock, const TxId &txid);
 
     /**
      * 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);
 
     /**
      * Used by
      * TransactionAddedToMemorypool/BlockConnected/Disconnected/ScanForWalletTransactions.
      * Should be called with non-zero block_hash and posInBlock if this is for a
      * transaction that is included in a block.
      */
     void SyncTransaction(const CTransactionRef &tx, const BlockHash &block_hash,
                          int posInBlock = 0, bool update_tx = true)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     /* the HD chain data model (external chain counters) */
     CHDChain hdChain;
 
     /* HD derive new child key (on internal or external chain) */
     void DeriveNewChildKey(WalletBatch &batch, CKeyMetadata &metadata,
                            CKey &secret, bool internal = false)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     std::set<int64_t> setInternalKeyPool GUARDED_BY(cs_wallet);
     std::set<int64_t> setExternalKeyPool GUARDED_BY(cs_wallet);
     std::set<int64_t> set_pre_split_keypool GUARDED_BY(cs_wallet);
     int64_t m_max_keypool_index GUARDED_BY(cs_wallet) = 0;
     std::map<CKeyID, int64_t> m_pool_key_to_index;
     std::atomic<uint64_t> m_wallet_flags{0};
 
     int64_t nTimeFirstKey GUARDED_BY(cs_wallet) = 0;
 
     /**
      * Private version of AddWatchOnly method which does not accept a timestamp,
      * and which will reset the wallet's nTimeFirstKey value to 1 if the watch
      * key did not previously have a timestamp associated with it. Because this
      * is an inherited virtual method, it is accessible despite being marked
      * private, but it is marked private anyway to encourage use of the other
      * AddWatchOnly which accepts a timestamp and sets nTimeFirstKey more
      * intelligently for more efficient rescans.
      */
     bool AddWatchOnly(const CScript &dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript &dest)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     bool AddWatchOnlyInMem(const CScript &dest);
 
     /** Add a KeyOriginInfo to the wallet */
     bool AddKeyOriginWithDB(WalletBatch &batch, const CPubKey &pubkey,
                             const KeyOriginInfo &info);
 
     //! Adds a key to the store, and saves it to disk.
     bool AddKeyPubKeyWithDB(WalletBatch &batch, const CKey &key,
                             const CPubKey &pubkey)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     //! Adds a watch-only address to the store, and saves it to disk.
     bool AddWatchOnlyWithDB(WalletBatch &batch, const CScript &dest,
                             int64_t create_time)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     void AddKeypoolPubkeyWithDB(const CPubKey &pubkey, const bool internal,
                                 WalletBatch &batch);
 
     bool SetAddressBookWithDB(WalletBatch &batch, const CTxDestination &address,
                               const std::string &strName,
                               const std::string &strPurpose);
 
     //! Adds a script to the store and saves it to disk
     bool AddCScriptWithDB(WalletBatch &batch, const CScript &script);
 
     //! Unsets a wallet flag and saves it to disk
     void UnsetWalletFlagWithDB(WalletBatch &batch, uint64_t flag);
 
     /** Interface for accessing chain state. */
     interfaces::Chain *m_chain;
 
     /**
      * Wallet location which includes wallet name (see WalletLocation).
      */
     WalletLocation m_location;
 
     /** Internal database handle. */
     std::unique_ptr<WalletDatabase> database;
 
     /**
      * 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.
      *
      * Note that this is *not* how far we've processed, we may need some rescan
      * to have seen all transactions in the chain, but is only used to track
      * live BlockConnected callbacks.
      */
     BlockHash m_last_block_processed GUARDED_BY(cs_wallet);
 
     //! Fetches a key from the keypool
     bool GetKeyFromPool(CPubKey &key, bool internal = false);
 
 public:
     const CChainParams &chainParams;
     /*
      * Main wallet lock.
      * This lock protects all the fields added by CWallet.
      */
     mutable RecursiveMutex cs_wallet;
 
     /**
      * Get database handle used by this wallet. Ideally this function would not
      * be necessary.
      */
     WalletDatabase &GetDBHandle() { return *database; }
 
     /**
      * Select a set of coins such that nValueRet >= nTargetValue and at least
      * all coins from coinControl are selected; Never select unconfirmed coins
      * if they are not ours.
      */
     bool SelectCoins(const std::vector<COutput> &vAvailableCoins,
                      const Amount nTargetValue,
                      std::set<CInputCoin> &setCoinsRet, Amount &nValueRet,
                      const CCoinControl &coin_control,
                      CoinSelectionParams &coin_selection_params,
                      bool &bnb_used) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     const WalletLocation &GetLocation() const { return m_location; }
 
     /**
      * Get a name for this wallet for logging/debugging purposes.
      */
     const std::string &GetName() const { return m_location.GetName(); }
 
     void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     void MarkPreSplitKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     // Map from Key ID to key metadata.
     std::map<CKeyID, CKeyMetadata> mapKeyMetadata GUARDED_BY(cs_wallet);
 
     // Map from Script ID to key metadata (for watch-only keys).
     std::map<CScriptID, CKeyMetadata> m_script_metadata GUARDED_BY(cs_wallet);
 
     typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
     MasterKeyMap mapMasterKeys;
     unsigned int nMasterKeyMaxID = 0;
 
     /** Construct wallet with specified name and database implementation. */
     CWallet(const CChainParams &chainParamsIn, interfaces::Chain *chain,
             const WalletLocation &location,
             std::unique_ptr<WalletDatabase> databaseIn)
         : fUseCrypto(false), fDecryptionThoroughlyChecked(false),
           m_chain(chain), m_location(location), database(std::move(databaseIn)),
           chainParams(chainParamsIn) {}
 
     ~CWallet() {
         // Should not have slots connected at this point.
         assert(NotifyUnload.empty());
         delete encrypted_batch;
         encrypted_batch = nullptr;
     }
 
     bool IsCrypted() const { return fUseCrypto; }
     bool IsLocked() const;
     bool Lock();
 
     std::map<TxId, 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>
         mapAddressBook GUARDED_BY(cs_wallet);
 
     std::set<COutPoint> setLockedCoins GUARDED_BY(cs_wallet);
 
     /** 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;
     }
 
     const CWalletTx *GetWalletTx(const TxId &txid) const;
 
     //! check whether we are allowed to upgrade (or already support) to the
     //! named feature
     bool CanSupportFeature(enum WalletFeature wf) const
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
         AssertLockHeld(cs_wallet);
         return nWalletMaxVersion >= wf;
     }
 
     /**
      * populate vCoins with vector of available COutputs.
      */
     void AvailableCoins(interfaces::Chain::Lock &locked_chain,
                         std::vector<COutput> &vCoins, bool fOnlySafe = true,
                         const CCoinControl *coinControl = nullptr,
                         const Amount nMinimumAmount = SATOSHI,
                         const Amount nMaximumAmount = MAX_MONEY,
                         const Amount nMinimumSumAmount = MAX_MONEY,
                         const uint64_t nMaximumCount = 0,
                         const int nMinDepth = 0,
                         const int nMaxDepth = 9999999) 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(interfaces::Chain::Lock &locked_chain) 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.
      */
     bool SelectCoinsMinConf(const Amount nTargetValue,
                             const CoinEligibilityFilter &eligibility_filter,
                             std::vector<OutputGroup> groups,
                             std::set<CInputCoin> &setCoinsRet,
                             Amount &nValueRet,
                             const CoinSelectionParams &coin_selection_params,
                             bool &bnb_used) const;
 
     bool IsSpent(interfaces::Chain::Lock &locked_chain,
                  const COutPoint &outpoint) const
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     // Whether this or any UTXO with the same CTxDestination has been spent.
     bool IsUsedDestination(const CTxDestination &dst) const;
     bool IsUsedDestination(const TxId &txid, unsigned int n) const;
     void SetUsedDestinationState(const TxId &hash, unsigned int n, bool used);
 
     std::vector<OutputGroup> GroupOutputs(const std::vector<COutput> &outputs,
                                           bool single_coin) const;
 
     bool IsLockedCoin(const COutPoint &outpoint) const
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     void LockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     void UnlockCoin(const COutPoint &output)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     void UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     void ListLockedCoins(std::vector<COutPoint> &vOutpts) const
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     /*
      * Rescan abort properties
      */
     void AbortRescan() { fAbortRescan = true; }
     bool IsAbortingRescan() { return fAbortRescan; }
     bool IsScanning() { return fScanningWallet; }
     int64_t ScanningDuration() const {
         return fScanningWallet ? GetTimeMillis() - m_scanning_start : 0;
     }
     double ScanningProgress() const {
         return fScanningWallet ? double(m_scanning_progress) : 0;
     }
 
     /**
      * keystore implementation
      * Generate a new key
      */
     CPubKey GenerateNewKey(WalletBatch &batch, bool internal = false)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     //! Adds a key to the store, and saves it to disk.
     bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) override
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     //! Adds a key to the store, without saving it to disk (used by LoadWallet)
     bool LoadKey(const CKey &key, const CPubKey &pubkey) {
         return AddKeyPubKeyInner(key, pubkey);
     }
     //! Load metadata (used by LoadWallet)
     void LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &metadata)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     void LoadScriptMetadata(const CScriptID &script_id,
                             const CKeyMetadata &metadata)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     //! Upgrade stored CKeyMetadata objects to store key origin info as
     //! KeyOriginInfo
     void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
         AssertLockHeld(cs_wallet);
         nWalletVersion = nVersion;
         nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion);
         return true;
     }
     void UpdateTimeFirstKey(int64_t nCreateTime)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     //! Adds an encrypted key to the store, and saves it to disk.
     bool AddCryptedKey(const CPubKey &vchPubKey,
                        const std::vector<uint8_t> &vchCryptedSecret);
     //! Adds an encrypted key to the store, without saving it to disk (used by
     //! LoadWallet)
     bool LoadCryptedKey(const CPubKey &vchPubKey,
                         const std::vector<uint8_t> &vchCryptedSecret);
     bool GetKey(const CKeyID &address, CKey &keyOut) const override;
     bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const override;
     bool HaveKey(const CKeyID &address) const override;
     std::set<CKeyID> GetKeys() const override;
     bool AddCScript(const CScript &redeemScript) override;
     bool LoadCScript(const CScript &redeemScript);
 
     //! Adds a destination data tuple to the store, and saves it to disk
     bool AddDestData(const CTxDestination &dest, const std::string &key,
                      const std::string &value)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     //! Erases a destination data tuple in the store and on disk
     bool EraseDestData(const CTxDestination &dest, const std::string &key)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     //! 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);
     //! Look up a destination data tuple in the store, return true if found
     //! false otherwise
     bool GetDestData(const CTxDestination &dest, const std::string &key,
                      std::string *value) const
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     //! Get all destination values matching a prefix.
     std::vector<std::string> GetDestValues(const std::string &prefix) const
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     //! Adds a watch-only address to the store, and saves it to disk.
     bool AddWatchOnly(const CScript &dest, int64_t nCreateTime)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     bool RemoveWatchOnly(const CScript &dest)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     //! Adds a watch-only address to the store, without saving it to disk (used
     //! by LoadWallet)
     bool LoadWatchOnly(const CScript &dest);
     //! Returns whether the watch-only script is in the wallet
     bool HaveWatchOnly(const CScript &dest) const;
     //! Returns whether there are any watch-only things in the wallet
     bool HaveWatchOnly() const;
     //! Fetches a pubkey from mapWatchKeys if it exists there
     bool GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const;
 
     //! 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 = 0;
 
     bool Unlock(const SecureString &strWalletPassphrase,
                 bool accept_no_keys = false);
     bool ChangeWalletPassphrase(const SecureString &strOldWalletPassphrase,
                                 const SecureString &strNewWalletPassphrase);
     bool EncryptWallet(const SecureString &strWalletPassphrase);
 
     void GetKeyBirthTimes(interfaces::Chain::Lock &locked_chain,
                           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();
     bool AddToWallet(const CWalletTx &wtxIn, bool fFlushOnClose = true);
     void LoadToWallet(const CWalletTx &wtxIn)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     void TransactionAddedToMempool(const CTransactionRef &tx) override;
     void
     BlockConnected(const CBlock &block,
                    const std::vector<CTransactionRef> &vtxConflicted) override;
     void BlockDisconnected(const CBlock &block) 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.
         BlockHash last_scanned_block;
         Optional<int> last_scanned_height;
 
         //! Hash 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.
         BlockHash last_failed_block;
     };
     ScanResult ScanForWalletTransactions(const BlockHash &first_block,
                                          const BlockHash &last_block,
                                          const WalletRescanReserver &reserver,
                                          bool fUpdate);
     void TransactionRemovedFromMempool(const CTransactionRef &ptx) override;
     void ReacceptWalletTransactions(interfaces::Chain::Lock &locked_chain)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     void ResendWalletTransactions();
     struct Balance {
         //! Trusted, at depth=GetBalance.min_depth or more
         Amount m_mine_trusted{Amount::zero()};
         //! Untrusted, but in mempool (pending)
         Amount m_mine_untrusted_pending{Amount::zero()};
         //! Immature coinbases in the main chain
         Amount m_mine_immature{Amount::zero()};
         Amount m_watchonly_trusted{Amount::zero()};
         Amount m_watchonly_untrusted_pending{Amount::zero()};
         Amount m_watchonly_immature{Amount::zero()};
     };
     Balance GetBalance(int min_depth = 0, bool avoid_reuse = true) const;
     Amount GetAvailableBalance(const CCoinControl *coinControl = nullptr) const;
 
     OutputType TransactionChangeType(OutputType change_type,
                                      const std::vector<CRecipient> &vecSend);
 
     /**
      * Insert additional inputs into the transaction by calling
      * CreateTransaction();
      */
     bool FundTransaction(CMutableTransaction &tx, Amount &nFeeRet,
                          int &nChangePosInOut, std::string &strFailReason,
                          bool lockUnspents,
                          const std::set<int> &setSubtractFeeFromOutputs,
                          CCoinControl coinControl);
     bool SignTransaction(CMutableTransaction &tx)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     /**
      * 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(interfaces::Chain::Lock &locked_chain,
                            const std::vector<CRecipient> &vecSend,
                            CTransactionRef &tx, Amount &nFeeRet,
                            int &nChangePosInOut, std::string &strFailReason,
                            const CCoinControl &coin_control, bool sign = true);
     bool CommitTransaction(
         CTransactionRef tx, mapValue_t mapValue,
         std::vector<std::pair<std::string, std::string>> orderForm,
         TxValidationState &state);
 
     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};
     bool m_spend_zero_conf_change{DEFAULT_SPEND_ZEROCONF_CHANGE};
     // will be defined via chainparams
     bool m_allow_fallback_fee{true};
     // Override with -mintxfee
     CFeeRate m_min_fee{DEFAULT_TRANSACTION_MINFEE_PER_KB};
     /**
      * 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};
     OutputType m_default_address_type{DEFAULT_ADDRESS_TYPE};
     OutputType m_default_change_type{DEFAULT_CHANGE_TYPE};
     /**
      * Absolute maximum transaction fee (in satoshis) used by default for the
      * wallet.
      */
     Amount m_default_max_tx_fee{DEFAULT_TRANSACTION_MAXFEE};
 
     bool NewKeyPool();
     size_t KeypoolCountExternalKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     bool TopUpKeyPool(unsigned int kpSize = 0);
 
     /**
      * Reserves a key from the keypool and sets nIndex to its index
      *
      * @param[out] nIndex the index of the key in keypool
      * @param[out] keypool the keypool the key was drawn from, which could be
      * the the pre-split pool if present, or the internal or external pool
      * @param fRequestedInternal true if the caller would like the key drawn
      *     from the internal keypool, false if external is preferred
      *
      * @return true if succeeded, false if failed due to empty keypool
      * @throws std::runtime_error if keypool read failed, key was invalid,
      *     was not found in the wallet, or was misclassified in the internal
      *     or external keypool
      */
     bool ReserveKeyFromKeyPool(int64_t &nIndex, CKeyPool &keypool,
                                bool fRequestedInternal);
     void KeepKey(int64_t nIndex);
     void ReturnKey(int64_t nIndex, bool fInternal, const CPubKey &pubkey);
     int64_t GetOldestKeyPoolTime();
     /**
      * Marks all keys in the keypool up to and including reserve_key as used.
      */
     void MarkReserveKeysAsUsed(int64_t keypool_id)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     const std::map<CKeyID, int64_t> &GetAllReserveKeys() const {
         return m_pool_key_to_index;
     }
 
     std::set<std::set<CTxDestination>> GetAddressGroupings()
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
     std::map<CTxDestination, Amount>
     GetAddressBalances(interfaces::Chain::Lock &locked_chain);
 
     std::set<CTxDestination> GetLabelAddresses(const std::string &label) const;
 
     bool GetNewDestination(const OutputType type, const std::string label,
                            CTxDestination &dest, std::string &error);
     bool GetNewChangeDestination(const OutputType type, CTxDestination &dest,
                                  std::string &error);
 
     isminetype IsMine(const CTxIn &txin) const;
     /**
      * Returns amount of debit if the input matches the filter, otherwise
      * returns 0
      */
     Amount GetDebit(const CTxIn &txin, const isminefilter &filter) const;
     isminetype IsMine(const CTxOut &txout) const;
     Amount GetCredit(const CTxOut &txout, const isminefilter &filter) const;
     bool IsChange(const CTxOut &txout) const;
     bool IsChange(const CScript &script) const;
     Amount GetChange(const CTxOut &txout) const;
     bool IsMine(const CTransaction &tx) const;
     /** should probably be renamed to IsRelevantToMe */
     bool IsFromMe(const CTransaction &tx) const;
     Amount 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;
     Amount GetCredit(const CTransaction &tx, const isminefilter &filter) const;
     Amount GetChange(const CTransaction &tx) const;
     void ChainStateFlushed(const CBlockLocator &loc) override;
 
     DBErrors LoadWallet(bool &fFirstRunRet);
     DBErrors ZapWalletTx(std::vector<CWalletTx> &vWtx);
     DBErrors ZapSelectTx(std::vector<TxId> &txIdsIn,
                          std::vector<TxId> &txIdsOut)
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     bool SetAddressBook(const CTxDestination &address,
                         const std::string &strName, const std::string &purpose);
 
     bool DelAddressBook(const CTxDestination &address);
 
     const std::string &GetLabelName(const CScript &scriptPubKey) const
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     unsigned int GetKeyPoolSize() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
         AssertLockHeld(cs_wallet);
         return setInternalKeyPool.size() + setExternalKeyPool.size();
     }
 
     //! signify that a particular wallet feature is now used. this may change
     //! nWalletVersion and nWalletMaxVersion if those are lower
     void SetMinVersion(enum WalletFeature, WalletBatch *batch_in = nullptr,
                        bool fExplicit = false);
 
     //! change which version we're allowed to upgrade to (note that this does
     //! not immediately imply upgrading to that format)
     bool SetMaxVersion(int nVersion);
 
     //! get the current wallet format (the oldest client version guaranteed to
     //! understand this wallet)
     int GetVersion() {
         LOCK(cs_wallet);
         return nWalletVersion;
     }
 
     //! Get wallet transactions that conflict with given transaction (spend same
     //! outputs)
     std::set<TxId> GetConflicts(const TxId &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 TxId &txid) const
         EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
 
     //! Flush wallet (bitdb flush)
     void Flush(bool shutdown = false);
 
     /** Wallet is about to be unloaded */
     boost::signals2::signal<void()> NotifyUnload;
 
     /**
      * Address book entry changed.
      * @note called with lock cs_wallet held.
      */
     boost::signals2::signal<void(CWallet *wallet, 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(CWallet *wallet, const TxId &txid,
                                  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;
 
     /**
      * 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 TxId &txid) const;
 
     /**
      * Mark a transaction (and it in-wallet descendants) as abandoned so its
      * inputs may be respent.
      */
     bool AbandonTransaction(interfaces::Chain::Lock &locked_chain,
                             const TxId &txid);
 
     //! Verify wallet naming and perform salvage on the wallet if required
     static bool Verify(const CChainParams &chainParams,
                        interfaces::Chain &chain, const WalletLocation &location,
                        bool salvage_wallet, std::string &error_string,
                        std::string &warning_string);
 
     /**
      * Initializes the wallet, returns a new CWallet instance or a null pointer
      * in case of an error.
      */
     static std::shared_ptr<CWallet> CreateWalletFromFile(
         const CChainParams &chainParams, interfaces::Chain &chain,
         const WalletLocation &location, uint64_t wallet_creation_flags = 0);
 
     /**
      * Wallet post-init setup
      * Gives the wallet a chance to register repetitive tasks and complete
      * post-init tasks
      */
     void postInitProcess();
 
     bool BackupWallet(const std::string &strDest);
 
     /* Set the HD chain model (chain child index counters) */
     void SetHDChain(const CHDChain &chain, bool memonly);
     const CHDChain &GetHDChain() const { return hdChain; }
 
     /* Returns true if HD is enabled */
     bool IsHDEnabled() const;
 
     /* Returns true if the wallet can generate new keys */
     bool CanGenerateKeys();
 
     /**
      * 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);
 
     /* Generates a new HD seed (will not be activated) */
     CPubKey GenerateNewSeed();
 
     /**
      * Derives a new HD seed (will not be activated)
      */
     CPubKey DeriveNewSeed(const CKey &key);
 
     /**
      * Set the current HD seed (will reset the chain child index counters)
      * Sets the seed's version based on the current wallet version (so the
      * caller must ensure the current wallet version is correct before calling
      * this function).
      */
     void SetHDSeed(const CPubKey &key);
 
     /**
      * 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() LOCKS_EXCLUDED(cs_main, cs_wallet);
 
     /**
      * Explicitly make the wallet learn the related scripts for outputs to the
      * given key. This is purely to make the wallet file compatible with older
      * software, as FillableSigningProvider automatically does this implicitly
      * for all keys now.
      */
     void LearnRelatedScripts(const CPubKey &key, OutputType);
 
     /**
      * Same as LearnRelatedScripts, but when the OutputType is not known (and
      * could be anything).
      */
     void LearnAllRelatedScripts(const CPubKey &key);
 
     /**
      * 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;
 
     /**
      * Overwrite all flags by the given uint64_t.
      * Returns false if unknown, non-tolerable flags are present.
      */
     bool SetWalletFlags(uint64_t overwriteFlags, bool memOnly);
 
     /**
      * Returns a bracketed wallet name for displaying in logs, will return
      * [default wallet] if the wallet has no name.
      */
     const std::string GetDisplayName() const {
         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...);
     };
 
     template <typename... Params>
     void WalletLogPrintfToBeContinued(std::string fmt,
                                       Params... parameters) const {
         LogPrintfToBeContinued(("%s " + fmt).c_str(), GetDisplayName(),
                                parameters...);
     };
 
     /**
      * Implement lookup of key origin information through wallet key metadata.
      */
     bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const override;
 };
 
 /**
  * Called periodically by the schedule thread. Prompts individual wallets to
  * resend their transactions. Actual rebroadcast schedule is managed by the
  * wallets themselves.
  */
 void MaybeResendWalletTxs();
 
 /** RAII object to check and reserve a wallet rescan */
 class WalletRescanReserver {
 private:
     CWallet *m_wallet;
     bool m_could_reserve;
 
 public:
     explicit WalletRescanReserver(CWallet *w)
         : m_wallet(w), m_could_reserve(false) {}
 
     bool reserve() {
         assert(!m_could_reserve);
         std::lock_guard<std::mutex> lock(m_wallet->mutexScanning);
         if (m_wallet->fScanningWallet) {
             return false;
         }
         m_wallet->m_scanning_start = GetTimeMillis();
         m_wallet->m_scanning_progress = 0;
         m_wallet->fScanningWallet = true;
         m_could_reserve = true;
         return true;
     }
 
     bool isReserved() const {
         return (m_could_reserve && m_wallet->fScanningWallet);
     }
 
     ~WalletRescanReserver() {
         std::lock_guard<std::mutex> lock(m_wallet->mutexScanning);
         if (m_could_reserve) {
             m_wallet->fScanningWallet = false;
         }
     }
 };
 
 // Calculate the size of the transaction assuming all signatures are max size
 // Use DummySignatureCreator, which inserts 71 byte signatures everywhere.
 // NOTE: this requires that all inputs must be in mapWallet (eg the tx should
 // be IsAllFromMe).
 int64_t CalculateMaximumSignedTxSize(const CTransaction &tx,
                                      const CWallet *wallet,
                                      bool use_max_sig = false)
     EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet);
 int64_t CalculateMaximumSignedTxSize(const CTransaction &tx,
                                      const CWallet *wallet,
                                      const std::vector<CTxOut> &txouts,
                                      bool use_max_sig = false);
 
 #endif // BITCOIN_WALLET_WALLET_H