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