Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/wallet.h
Show First 20 Lines • Show All 144 Lines • ▼ Show 20 Lines | enum WalletFlags : uint64_t { | ||||
//! then improperly reinitializing it. | //! then improperly reinitializing it. | ||||
WALLET_FLAG_BLANK_WALLET = (1ULL << 33), | WALLET_FLAG_BLANK_WALLET = (1ULL << 33), | ||||
}; | }; | ||||
static constexpr uint64_t g_known_wallet_flags = | static constexpr uint64_t g_known_wallet_flags = | ||||
WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET | | WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET | | ||||
WALLET_FLAG_KEY_ORIGIN_METADATA; | WALLET_FLAG_KEY_ORIGIN_METADATA; | ||||
/** A key pool entry */ | /** | ||||
* 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 { | class CKeyPool { | ||||
public: | public: | ||||
//! The time at which the key was generated. Set in AddKeypoolPubKeyWithDB | |||||
int64_t nTime; | int64_t nTime; | ||||
//! The public key | |||||
CPubKey vchPubKey; | CPubKey vchPubKey; | ||||
// for change outputs | //! Whether this keypool entry is in the internal keypool (for change | ||||
//! outputs) | |||||
bool fInternal; | bool fInternal; | ||||
// For keys generated before keypool split upgrade | //! Whether this key was generated for a keypool before the wallet was | ||||
//! upgraded to HD-split | |||||
bool m_pre_split; | bool m_pre_split; | ||||
CKeyPool(); | CKeyPool(); | ||||
CKeyPool(const CPubKey &vchPubKeyIn, bool internalIn); | CKeyPool(const CPubKey &vchPubKeyIn, bool internalIn); | ||||
ADD_SERIALIZE_METHODS; | ADD_SERIALIZE_METHODS; | ||||
template <typename Stream, typename Operation> | template <typename Stream, typename Operation> | ||||
Show All 28 Lines | inline void SerializationOp(Stream &s, Operation ser_action) { | ||||
} | } | ||||
} else { | } else { | ||||
READWRITE(fInternal); | READWRITE(fInternal); | ||||
READWRITE(m_pre_split); | READWRITE(m_pre_split); | ||||
} | } | ||||
} | } | ||||
}; | }; | ||||
/** A key allocated from the key pool. */ | /** | ||||
* A wrapper to reserve a key from a wallet keypool | |||||
* | |||||
* CReserveKey is used to reserve a key from the keypool. It is passed around | |||||
* during the CreateTransaction/CommitTransaction procedure. | |||||
* | |||||
* Instantiating a CReserveKey does not reserve a keypool key. To do so, | |||||
* GetReservedKey() needs to be called on the object. Once a key has been | |||||
* reserved, call KeepKey() on the CReserveKey object to make sure it is not | |||||
* returned to the keypool. Call ReturnKey() to return the key to the keypool | |||||
* so it can be re-used (for example, if the key was used in a new transaction | |||||
* and that transaction was not completed and needed to be aborted). | |||||
* | |||||
* If a key is reserved and KeepKey() is not called, then the key will be | |||||
* returned to the keypool when the CReserveObject goes out of scope. | |||||
*/ | |||||
class CReserveKey final : public CReserveScript { | class CReserveKey final : public CReserveScript { | ||||
protected: | protected: | ||||
//! The wallet to reserve the keypool key from | |||||
CWallet *pwallet; | CWallet *pwallet; | ||||
//! The index of the key in the keypool | |||||
int64_t nIndex{-1}; | int64_t nIndex{-1}; | ||||
//! The public key | |||||
CPubKey vchPubKey; | CPubKey vchPubKey; | ||||
//! Whether this is from the internal (change output) keypool | |||||
bool fInternal{false}; | bool fInternal{false}; | ||||
public: | public: | ||||
//! Construct a CReserveKey object. This does NOT reserve a key from the | |||||
//! keypool yet | |||||
explicit CReserveKey(CWallet *pwalletIn) { pwallet = pwalletIn; } | explicit CReserveKey(CWallet *pwalletIn) { pwallet = pwalletIn; } | ||||
CReserveKey(const CReserveKey &) = delete; | CReserveKey(const CReserveKey &) = delete; | ||||
CReserveKey &operator=(const CReserveKey &) = delete; | CReserveKey &operator=(const CReserveKey &) = delete; | ||||
//! Destructor. If a key has been reserved and not KeepKey'ed, it will be | |||||
//! returned to the keypool | |||||
~CReserveKey() { ReturnKey(); } | ~CReserveKey() { ReturnKey(); } | ||||
void ReturnKey(); | //! Reserve a key from the keypool | ||||
bool GetReservedKey(CPubKey &pubkey, bool internal = false); | bool GetReservedKey(CPubKey &pubkey, bool internal = false); | ||||
//! Return a key to the keypool | |||||
void ReturnKey(); | |||||
//! Keep the key. Do not return it to the keypool when this object goes out | |||||
//! of scope | |||||
void KeepKey(); | void KeepKey(); | ||||
void KeepScript() override { KeepKey(); } | void KeepScript() override { KeepKey(); } | ||||
}; | }; | ||||
/** Address book data */ | /** Address book data */ | ||||
class CAddressBookData { | class CAddressBookData { | ||||
public: | public: | ||||
std::string name; | std::string name; | ||||
▲ Show 20 Lines • Show All 1,296 Lines • Show Last 20 Lines |