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 CHDChain()97 CHDChain() { SetNull(); } 98 SERIALIZE_METHODS(CHDChain,obj)99 SERIALIZE_METHODS(CHDChain, obj) 100 { 101 READWRITE(obj.nVersion, obj.nExternalChainCounter, obj.seed_id); 102 if (obj.nVersion >= VERSION_HD_CHAIN_SPLIT) { 103 READWRITE(obj.nInternalChainCounter); 104 } 105 } 106 SetNull()107 void SetNull() 108 { 109 nVersion = CHDChain::CURRENT_VERSION; 110 nExternalChainCounter = 0; 111 nInternalChainCounter = 0; 112 seed_id.SetNull(); 113 } 114 115 bool operator==(const CHDChain& chain) const 116 { 117 return seed_id == chain.seed_id; 118 } 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 CKeyMetadata()135 CKeyMetadata() 136 { 137 SetNull(); 138 } CKeyMetadata(int64_t nCreateTime_)139 explicit CKeyMetadata(int64_t nCreateTime_) 140 { 141 SetNull(); 142 nCreateTime = nCreateTime_; 143 } 144 SERIALIZE_METHODS(CKeyMetadata,obj)145 SERIALIZE_METHODS(CKeyMetadata, obj) 146 { 147 READWRITE(obj.nVersion, obj.nCreateTime); 148 if (obj.nVersion >= VERSION_WITH_HDDATA) { 149 READWRITE(obj.hdKeypath, obj.hd_seed_id); 150 } 151 if (obj.nVersion >= VERSION_WITH_KEY_ORIGIN) 152 { 153 READWRITE(obj.key_origin); 154 READWRITE(obj.has_key_origin); 155 } 156 } 157 SetNull()158 void SetNull() 159 { 160 nVersion = CKeyMetadata::CURRENT_VERSION; 161 nCreateTime = 0; 162 hdKeypath.clear(); 163 hd_seed_id.SetNull(); 164 key_origin.clear(); 165 has_key_origin = false; 166 } 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 { 182 if (!m_batch->Write(key, value, fOverwrite)) { 183 return false; 184 } 185 m_database.IncrementUpdateCounter(); 186 if (m_database.nUpdateCounter % 1000 == 0) { 187 m_batch->Flush(); 188 } 189 return true; 190 } 191 192 template <typename K> EraseIC(const K & key)193 bool EraseIC(const K& key) 194 { 195 if (!m_batch->Erase(key)) { 196 return false; 197 } 198 m_database.IncrementUpdateCounter(); 199 if (m_database.nUpdateCounter % 1000 == 0) { 200 m_batch->Flush(); 201 } 202 return true; 203 } 204 205 public: 206 explicit WalletBatch(WalletDatabase &database, bool _fFlushOnClose = true) : 207 m_batch(database.MakeBatch(_fFlushOnClose)), 208 m_database(database) 209 { 210 } 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 bool WriteDescriptorLastHardenedCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index); 250 bool WriteDescriptorCacheItems(const uint256& desc_id, const DescriptorCache& cache); 251 252 /// Write destination data key,value tuple to database 253 bool WriteDestData(const std::string &address, const std::string &key, const std::string &value); 254 /// Erase destination data tuple from wallet database 255 bool EraseDestData(const std::string &address, const std::string &key); 256 257 bool WriteActiveScriptPubKeyMan(uint8_t type, const uint256& id, bool internal); 258 bool EraseActiveScriptPubKeyMan(uint8_t type, bool internal); 259 260 DBErrors LoadWallet(CWallet* pwallet); 261 DBErrors FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWalletTx>& vWtx); 262 DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut); 263 /* Function to determine if a certain KV/key-type is a key (cryptographical key) type */ 264 static bool IsKeyType(const std::string& strType); 265 266 //! write the hdchain model (external chain child index counter) 267 bool WriteHDChain(const CHDChain& chain); 268 269 bool WriteWalletFlags(const uint64_t flags); 270 //! Begin a new transaction 271 bool TxnBegin(); 272 //! Commit current transaction 273 bool TxnCommit(); 274 //! Abort current transaction 275 bool TxnAbort(); 276 private: 277 std::unique_ptr<DatabaseBatch> m_batch; 278 WalletDatabase& m_database; 279 }; 280 281 //! Compacts BDB state so that wallet.dat is self-contained (if there are changes) 282 void MaybeCompactWalletDB(); 283 284 //! Callback for filtering key types to deserialize in ReadKeyValue 285 using KeyFilterFn = std::function<bool(const std::string&)>; 286 287 //! Unserialize a given Key-Value pair and load it into the wallet 288 bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, std::string& strType, std::string& strErr, const KeyFilterFn& filter_fn = nullptr); 289 290 /** Return object for accessing dummy database with no read/write capabilities. */ 291 std::unique_ptr<WalletDatabase> CreateDummyWalletDatabase(); 292 293 /** Return object for accessing temporary in-memory database. */ 294 std::unique_ptr<WalletDatabase> CreateMockWalletDatabase(); 295 296 #endif // BITCOIN_WALLET_WALLETDB_H 297