Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2020 The Bitcoin Core developers
# 3 : : // Distributed under the MIT software license, see the accompanying
# 4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 5 : :
# 6 : : #ifndef BITCOIN_WALLET_WALLETDB_H
# 7 : : #define BITCOIN_WALLET_WALLETDB_H
# 8 : :
# 9 : : #include <amount.h>
# 10 : : #include <script/sign.h>
# 11 : : #include <wallet/db.h>
# 12 : : #include <wallet/walletutil.h>
# 13 : : #include <key.h>
# 14 : :
# 15 : : #include <stdint.h>
# 16 : : #include <string>
# 17 : : #include <vector>
# 18 : :
# 19 : : /**
# 20 : : * Overview of wallet database classes:
# 21 : : *
# 22 : : * - WalletBatch is an abstract modifier object for the wallet database, and encapsulates a database
# 23 : : * batch update as well as methods to act on the database. It should be agnostic to the database implementation.
# 24 : : *
# 25 : : * The following classes are implementation specific:
# 26 : : * - BerkeleyEnvironment is an environment in which the database exists.
# 27 : : * - BerkeleyDatabase represents a wallet database.
# 28 : : * - BerkeleyBatch is a low-level database batch update.
# 29 : : */
# 30 : :
# 31 : : static const bool DEFAULT_FLUSHWALLET = true;
# 32 : :
# 33 : : struct CBlockLocator;
# 34 : : class CKeyPool;
# 35 : : class CMasterKey;
# 36 : : class CScript;
# 37 : : class CWallet;
# 38 : : class CWalletTx;
# 39 : : class uint160;
# 40 : : class uint256;
# 41 : :
# 42 : : /** Error statuses for the wallet database */
# 43 : : enum class DBErrors
# 44 : : {
# 45 : : LOAD_OK,
# 46 : : CORRUPT,
# 47 : : NONCRITICAL_ERROR,
# 48 : : TOO_NEW,
# 49 : : LOAD_FAIL,
# 50 : : NEED_REWRITE
# 51 : : };
# 52 : :
# 53 : : namespace DBKeys {
# 54 : : extern const std::string ACENTRY;
# 55 : : extern const std::string ACTIVEEXTERNALSPK;
# 56 : : extern const std::string ACTIVEINTERNALSPK;
# 57 : : extern const std::string BESTBLOCK;
# 58 : : extern const std::string BESTBLOCK_NOMERKLE;
# 59 : : extern const std::string CRYPTED_KEY;
# 60 : : extern const std::string CSCRIPT;
# 61 : : extern const std::string DEFAULTKEY;
# 62 : : extern const std::string DESTDATA;
# 63 : : extern const std::string FLAGS;
# 64 : : extern const std::string HDCHAIN;
# 65 : : extern const std::string KEY;
# 66 : : extern const std::string KEYMETA;
# 67 : : extern const std::string MASTER_KEY;
# 68 : : extern const std::string MINVERSION;
# 69 : : extern const std::string NAME;
# 70 : : extern const std::string OLD_KEY;
# 71 : : extern const std::string ORDERPOSNEXT;
# 72 : : extern const std::string POOL;
# 73 : : extern const std::string PURPOSE;
# 74 : : extern const std::string SETTINGS;
# 75 : : extern const std::string TX;
# 76 : : extern const std::string VERSION;
# 77 : : extern const std::string WALLETDESCRIPTOR;
# 78 : : extern const std::string WALLETDESCRIPTORCKEY;
# 79 : : extern const std::string WALLETDESCRIPTORKEY;
# 80 : : extern const std::string WATCHMETA;
# 81 : : extern const std::string WATCHS;
# 82 : : } // namespace DBKeys
# 83 : :
# 84 : : /* simple HD chain data model */
# 85 : : class CHDChain
# 86 : : {
# 87 : : public:
# 88 : : uint32_t nExternalChainCounter;
# 89 : : uint32_t nInternalChainCounter;
# 90 : : CKeyID seed_id; //!< seed hash160
# 91 : :
# 92 : : static const int VERSION_HD_BASE = 1;
# 93 : : static const int VERSION_HD_CHAIN_SPLIT = 2;
# 94 : : static const int CURRENT_VERSION = VERSION_HD_CHAIN_SPLIT;
# 95 : : int nVersion;
# 96 : :
# 97 : 11605 : CHDChain() { SetNull(); }
# 98 : :
# 99 : : SERIALIZE_METHODS(CHDChain, obj)
# 100 : 24725 : {
# 101 : 24725 : READWRITE(obj.nVersion, obj.nExternalChainCounter, obj.seed_id);
# 102 [ + - ][ + + ]: 24725 : if (obj.nVersion >= VERSION_HD_CHAIN_SPLIT) {
# 103 : 23724 : READWRITE(obj.nInternalChainCounter);
# 104 : 23724 : }
# 105 : 24725 : }
# 106 : :
# 107 : : void SetNull()
# 108 : 11605 : {
# 109 : 11605 : nVersion = CHDChain::CURRENT_VERSION;
# 110 : 11605 : nExternalChainCounter = 0;
# 111 : 11605 : nInternalChainCounter = 0;
# 112 : 11605 : seed_id.SetNull();
# 113 : 11605 : }
# 114 : :
# 115 : : bool operator==(const CHDChain& chain) const
# 116 : 0 : {
# 117 : 0 : return seed_id == chain.seed_id;
# 118 : 0 : }
# 119 : : };
# 120 : :
# 121 : : class CKeyMetadata
# 122 : : {
# 123 : : public:
# 124 : : static const int VERSION_BASIC=1;
# 125 : : static const int VERSION_WITH_HDDATA=10;
# 126 : : static const int VERSION_WITH_KEY_ORIGIN = 12;
# 127 : : static const int CURRENT_VERSION=VERSION_WITH_KEY_ORIGIN;
# 128 : : int nVersion;
# 129 : : int64_t nCreateTime; // 0 means unknown
# 130 : : std::string hdKeypath; //optional HD/bip32 keypath. Still used to determine whether a key is a seed. Also kept for backwards compatibility
# 131 : : CKeyID hd_seed_id; //id of the HD seed used to derive this key
# 132 : : KeyOriginInfo key_origin; // Key origin info with path and fingerprint
# 133 : : bool has_key_origin = false; //!< Whether the key_origin is useful
# 134 : :
# 135 : : CKeyMetadata()
# 136 : 813019 : {
# 137 : 813019 : SetNull();
# 138 : 813019 : }
# 139 : : explicit CKeyMetadata(int64_t nCreateTime_)
# 140 : 34365 : {
# 141 : 34365 : SetNull();
# 142 : 34365 : nCreateTime = nCreateTime_;
# 143 : 34365 : }
# 144 : :
# 145 : : SERIALIZE_METHODS(CKeyMetadata, obj)
# 146 : 39910 : {
# 147 : 39910 : READWRITE(obj.nVersion, obj.nCreateTime);
# 148 [ + - ][ + - ]: 39910 : if (obj.nVersion >= VERSION_WITH_HDDATA) {
# 149 : 39910 : READWRITE(obj.hdKeypath, obj.hd_seed_id);
# 150 : 39910 : }
# 151 [ + - ][ + - ]: 39910 : if (obj.nVersion >= VERSION_WITH_KEY_ORIGIN)
# 152 : 39910 : {
# 153 : 39910 : READWRITE(obj.key_origin);
# 154 : 39910 : READWRITE(obj.has_key_origin);
# 155 : 39910 : }
# 156 : 39910 : }
# 157 : :
# 158 : : void SetNull()
# 159 : 847384 : {
# 160 : 847384 : nVersion = CKeyMetadata::CURRENT_VERSION;
# 161 : 847384 : nCreateTime = 0;
# 162 : 847384 : hdKeypath.clear();
# 163 : 847384 : hd_seed_id.SetNull();
# 164 : 847384 : key_origin.clear();
# 165 : 847384 : has_key_origin = false;
# 166 : 847384 : }
# 167 : : };
# 168 : :
# 169 : : /** Access to the wallet database.
# 170 : : * Opens the database and provides read and write access to it. Each read and write is its own transaction.
# 171 : : * Multiple operation transactions can be started using TxnBegin() and committed using TxnCommit()
# 172 : : * Otherwise the transaction will be committed when the object goes out of scope.
# 173 : : * Optionally (on by default) it will flush to disk on close.
# 174 : : * Every 1000 writes will automatically trigger a flush to disk.
# 175 : : */
# 176 : : class WalletBatch
# 177 : : {
# 178 : : private:
# 179 : : template <typename K, typename T>
# 180 : : bool WriteIC(const K& key, const T& value, bool fOverwrite = true)
# 181 : 503358 : {
# 182 [ - + ][ - + ]: 503358 : if (!m_batch->Write(key, value, fOverwrite)) {
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ + + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ + + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# 183 : 8910 : return false;
# 184 : 8910 : }
# 185 : 494448 : m_database.IncrementUpdateCounter();
# 186 [ - + ][ - + ]: 494448 : if (m_database.nUpdateCounter % 1000 == 0) {
# [ + + ][ - + ]
# [ - + ][ + + ]
# [ + + ][ - + ]
# [ + + ][ + + ]
# [ - + ][ + + ]
# [ - + ][ - + ]
# [ - + ][ + + ]
# [ - + ][ + + ]
# [ + + ][ + + ]
# [ + + ][ + + ]
# 187 : 403 : m_batch->Flush();
# 188 : 403 : }
# 189 : 494448 : return true;
# 190 : 494448 : }
# 191 : :
# 192 : : template <typename K>
# 193 : : bool EraseIC(const K& key)
# 194 : 13395 : {
# 195 [ - + ][ - + ]: 13395 : if (!m_batch->Erase(key)) {
# [ - + ][ # # ]
# [ - + ][ # # ]
# [ - + ]
# 196 : 0 : return false;
# 197 : 0 : }
# 198 : 13395 : m_database.IncrementUpdateCounter();
# 199 [ - + ][ - + ]: 13395 : if (m_database.nUpdateCounter % 1000 == 0) {
# [ - + ][ + + ]
# [ # # ][ # # ]
# [ - + ]
# 200 : 10 : m_batch->Flush();
# 201 : 10 : }
# 202 : 13395 : return true;
# 203 : 13395 : }
# 204 : :
# 205 : : public:
# 206 : : explicit WalletBatch(WalletDatabase &database, bool _fFlushOnClose = true) :
# 207 : : m_batch(database.MakeBatch(_fFlushOnClose)),
# 208 : : m_database(database)
# 209 : 290052 : {
# 210 : 290052 : }
# 211 : : WalletBatch(const WalletBatch&) = delete;
# 212 : : WalletBatch& operator=(const WalletBatch&) = delete;
# 213 : :
# 214 : : bool WriteName(const std::string& strAddress, const std::string& strName);
# 215 : : bool EraseName(const std::string& strAddress);
# 216 : :
# 217 : : bool WritePurpose(const std::string& strAddress, const std::string& purpose);
# 218 : : bool ErasePurpose(const std::string& strAddress);
# 219 : :
# 220 : : bool WriteTx(const CWalletTx& wtx);
# 221 : : bool EraseTx(uint256 hash);
# 222 : :
# 223 : : bool WriteKeyMetadata(const CKeyMetadata& meta, const CPubKey& pubkey, const bool overwrite);
# 224 : : bool WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata &keyMeta);
# 225 : : bool WriteCryptedKey(const CPubKey& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, const CKeyMetadata &keyMeta);
# 226 : : bool WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey);
# 227 : :
# 228 : : bool WriteCScript(const uint160& hash, const CScript& redeemScript);
# 229 : :
# 230 : : bool WriteWatchOnly(const CScript &script, const CKeyMetadata &keymeta);
# 231 : : bool EraseWatchOnly(const CScript &script);
# 232 : :
# 233 : : bool WriteBestBlock(const CBlockLocator& locator);
# 234 : : bool ReadBestBlock(CBlockLocator& locator);
# 235 : :
# 236 : : bool WriteOrderPosNext(int64_t nOrderPosNext);
# 237 : :
# 238 : : bool ReadPool(int64_t nPool, CKeyPool& keypool);
# 239 : : bool WritePool(int64_t nPool, const CKeyPool& keypool);
# 240 : : bool ErasePool(int64_t nPool);
# 241 : :
# 242 : : bool WriteMinVersion(int nVersion);
# 243 : :
# 244 : : bool WriteDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const CPrivKey& privkey);
# 245 : : bool WriteCryptedDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const std::vector<unsigned char>& secret);
# 246 : : bool WriteDescriptor(const uint256& desc_id, const WalletDescriptor& descriptor);
# 247 : : bool WriteDescriptorDerivedCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index, uint32_t der_index);
# 248 : : bool WriteDescriptorParentCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index);
# 249 : :
# 250 : : /// Write destination data key,value tuple to database
# 251 : : bool WriteDestData(const std::string &address, const std::string &key, const std::string &value);
# 252 : : /// Erase destination data tuple from wallet database
# 253 : : bool EraseDestData(const std::string &address, const std::string &key);
# 254 : :
# 255 : : bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256& id, bool internal);
# 256 : :
# 257 : : DBErrors LoadWallet(CWallet* pwallet);
# 258 : : DBErrors FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWalletTx>& vWtx);
# 259 : : DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut);
# 260 : : /* Function to determine if a certain KV/key-type is a key (cryptographical key) type */
# 261 : : static bool IsKeyType(const std::string& strType);
# 262 : :
# 263 : : //! write the hdchain model (external chain child index counter)
# 264 : : bool WriteHDChain(const CHDChain& chain);
# 265 : :
# 266 : : bool WriteWalletFlags(const uint64_t flags);
# 267 : : //! Begin a new transaction
# 268 : : bool TxnBegin();
# 269 : : //! Commit current transaction
# 270 : : bool TxnCommit();
# 271 : : //! Abort current transaction
# 272 : : bool TxnAbort();
# 273 : : private:
# 274 : : std::unique_ptr<DatabaseBatch> m_batch;
# 275 : : WalletDatabase& m_database;
# 276 : : };
# 277 : :
# 278 : : //! Compacts BDB state so that wallet.dat is self-contained (if there are changes)
# 279 : : void MaybeCompactWalletDB();
# 280 : :
# 281 : : //! Callback for filtering key types to deserialize in ReadKeyValue
# 282 : : using KeyFilterFn = std::function<bool(const std::string&)>;
# 283 : :
# 284 : : //! Unserialize a given Key-Value pair and load it into the wallet
# 285 : : bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, std::string& strType, std::string& strErr, const KeyFilterFn& filter_fn = nullptr);
# 286 : :
# 287 : : /** Return object for accessing dummy database with no read/write capabilities. */
# 288 : : std::unique_ptr<WalletDatabase> CreateDummyWalletDatabase();
# 289 : :
# 290 : : /** Return object for accessing temporary in-memory database. */
# 291 : : std::unique_ptr<WalletDatabase> CreateMockWalletDatabase();
# 292 : :
# 293 : : #endif // BITCOIN_WALLET_WALLETDB_H
|