Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2021 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 <script/sign.h>
10 : #include <script/standard.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 : struct CBlockLocator;
20 : class CScript;
21 : class uint160;
22 : class uint256;
23 : namespace Governance {
24 : class Object;
25 : } // namespace Governance
26 :
27 : namespace wallet {
28 : class CHDChain;
29 : class CHDPubKey;
30 : class CKeyPool;
31 : class CMasterKey;
32 : class CWallet;
33 : class CWalletTx;
34 : struct WalletContext;
35 :
36 : /**
37 : * Overview of wallet database classes:
38 : *
39 : * - WalletBatch is an abstract modifier object for the wallet database, and encapsulates a database
40 : * batch update as well as methods to act on the database. It should be agnostic to the database implementation.
41 : *
42 : * The following classes are implementation specific:
43 : * - BerkeleyEnvironment is an environment in which the database exists.
44 : * - BerkeleyDatabase represents a wallet database.
45 : * - BerkeleyBatch is a low-level database batch update.
46 : */
47 :
48 : static const bool DEFAULT_FLUSHWALLET = true;
49 :
50 : /** Error statuses for the wallet database */
51 : enum class DBErrors
52 : {
53 : LOAD_OK,
54 : CORRUPT,
55 : NONCRITICAL_ERROR,
56 : TOO_NEW,
57 : EXTERNAL_SIGNER_SUPPORT_REQUIRED,
58 : LOAD_FAIL,
59 : NEED_REWRITE
60 : };
61 :
62 : namespace DBKeys {
63 : extern const std::string ACENTRY;
64 : extern const std::string ACTIVEEXTERNALSPK;
65 : extern const std::string ACTIVEINTERNALSPK;
66 : extern const std::string BESTBLOCK;
67 : extern const std::string BESTBLOCK_NOMERKLE;
68 : extern const std::string CRYPTED_HDCHAIN;
69 : extern const std::string CRYPTED_KEY;
70 : extern const std::string COINJOIN_SALT;
71 : extern const std::string CSCRIPT;
72 : extern const std::string DEFAULTKEY;
73 : extern const std::string DESTDATA;
74 : extern const std::string FLAGS;
75 : extern const std::string G_OBJECT;
76 : extern const std::string HDCHAIN;
77 : extern const std::string HDPUBKEY;
78 : extern const std::string KEY;
79 : extern const std::string KEYMETA;
80 : extern const std::string LOCKED_UTXO;
81 : extern const std::string MASTER_KEY;
82 : extern const std::string MINVERSION;
83 : extern const std::string NAME;
84 : extern const std::string OLD_KEY;
85 : extern const std::string ORDERPOSNEXT;
86 : extern const std::string POOL;
87 : extern const std::string PURPOSE;
88 : extern const std::string PRIVATESEND_SALT;
89 : extern const std::string SETTINGS;
90 : extern const std::string TX;
91 : extern const std::string VERSION;
92 : extern const std::string WALLETDESCRIPTOR;
93 : extern const std::string WALLETDESCRIPTORCKEY;
94 : extern const std::string WALLETDESCRIPTORKEY;
95 : extern const std::string WATCHMETA;
96 : extern const std::string WATCHS;
97 :
98 : // Keys in this set pertain only to the legacy wallet (LegacyScriptPubKeyMan) and are removed during migration from legacy to descriptors.
99 : extern const std::unordered_set<std::string> LEGACY_TYPES;
100 : } // namespace DBKeys
101 :
102 : class CKeyMetadata
103 : {
104 : public:
105 : static const int VERSION_BASIC=1;
106 : static const int VERSION_WITH_KEY_ORIGIN = 12;
107 : static const int CURRENT_VERSION=VERSION_WITH_KEY_ORIGIN;
108 : int nVersion;
109 : int64_t nCreateTime; // 0 means unknown
110 : KeyOriginInfo key_origin; // Key origin info with path and fingerprint
111 760593 : bool has_key_origin = false; //!< Whether the key_origin is useful
112 :
113 1401970 : CKeyMetadata()
114 700985 : {
115 700985 : SetNull();
116 1401970 : }
117 119216 : explicit CKeyMetadata(int64_t nCreateTime_)
118 59608 : {
119 59608 : SetNull();
120 59608 : nCreateTime = nCreateTime_;
121 119216 : }
122 :
123 227913 : SERIALIZE_METHODS(CKeyMetadata, obj)
124 : {
125 75971 : READWRITE(obj.nVersion, obj.nCreateTime);
126 75971 : if (obj.nVersion >= VERSION_WITH_KEY_ORIGIN) {
127 75971 : READWRITE(obj.key_origin, obj.has_key_origin);
128 75971 : }
129 75971 : }
130 :
131 760593 : void SetNull()
132 : {
133 760593 : nVersion = CKeyMetadata::CURRENT_VERSION;
134 760593 : nCreateTime = 0;
135 760593 : key_origin.clear();
136 760593 : has_key_origin = false;
137 760593 : }
138 : };
139 :
140 : /** Access to the wallet database.
141 : * Opens the database and provides read and write access to it. Each read and write is its own transaction.
142 : * Multiple operation transactions can be started using TxnBegin() and committed using TxnCommit()
143 : * Otherwise the transaction will be committed when the object goes out of scope.
144 : * Optionally (on by default) it will flush to disk on close.
145 : * Every 1000 writes will automatically trigger a flush to disk.
146 : */
147 : class WalletBatch
148 : {
149 : private:
150 : template <typename K, typename T>
151 567918 : bool WriteIC(const K& key, const T& value, bool fOverwrite = true)
152 : {
153 567918 : if (!m_batch->Write(key, value, fOverwrite)) {
154 3 : return false;
155 : }
156 567915 : m_database.IncrementUpdateCounter();
157 567915 : if (m_database.nUpdateCounter % 1000 == 0) {
158 307 : m_batch->Flush();
159 307 : }
160 567915 : return true;
161 567918 : }
162 :
163 : template <typename K>
164 23031 : bool EraseIC(const K& key)
165 : {
166 23031 : if (!m_batch->Erase(key)) {
167 0 : return false;
168 : }
169 23031 : m_database.IncrementUpdateCounter();
170 23031 : if (m_database.nUpdateCounter % 1000 == 0) {
171 9 : m_batch->Flush();
172 9 : }
173 23031 : return true;
174 23031 : }
175 :
176 : public:
177 900936 : explicit WalletBatch(WalletDatabase &database, bool _fFlushOnClose = true) :
178 450468 : m_batch(database.MakeBatch(_fFlushOnClose)),
179 450468 : m_database(database)
180 450468 : {
181 900936 : }
182 : WalletBatch(const WalletBatch&) = delete;
183 : WalletBatch& operator=(const WalletBatch&) = delete;
184 :
185 : bool WriteName(const std::string& strAddress, const std::string& strName);
186 : bool EraseName(const std::string& strAddress);
187 :
188 : bool WritePurpose(const std::string& strAddress, const std::string& purpose);
189 : bool ErasePurpose(const std::string& strAddress);
190 :
191 : bool WriteTx(const CWalletTx& wtx);
192 : bool EraseTx(uint256 hash);
193 :
194 : bool WriteKeyMetadata(const CKeyMetadata& meta, const CPubKey& pubkey, const bool overwrite);
195 : bool WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata &keyMeta);
196 : bool WriteCryptedKey(const CPubKey& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, const CKeyMetadata &keyMeta);
197 : bool WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey);
198 :
199 : bool WriteCScript(const uint160& hash, const CScript& redeemScript);
200 :
201 : bool WriteWatchOnly(const CScript &script, const CKeyMetadata &keymeta);
202 : bool EraseWatchOnly(const CScript &script);
203 :
204 : bool WriteBestBlock(const CBlockLocator& locator);
205 : bool ReadBestBlock(CBlockLocator& locator);
206 :
207 : bool WriteOrderPosNext(int64_t nOrderPosNext);
208 :
209 : bool ReadPool(int64_t nPool, CKeyPool& keypool);
210 : bool WritePool(int64_t nPool, const CKeyPool& keypool);
211 : bool ErasePool(int64_t nPool);
212 :
213 : bool WriteMinVersion(int nVersion);
214 :
215 : bool ReadCoinJoinSalt(uint256& salt, bool fLegacy = false);
216 : bool WriteCoinJoinSalt(const uint256& salt);
217 :
218 : /** Write a CGovernanceObject to the database */
219 : bool WriteGovernanceObject(const Governance::Object& obj);
220 :
221 : bool WriteDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const CPrivKey& privkey, const SecureString& mnemonic, const SecureString& mnemonic_passphrase);
222 : bool WriteCryptedDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const std::vector<unsigned char>& secret, const std::vector<unsigned char>& crypted_mnemonic, const std::vector<unsigned char>& crypted_mnemonic_passphrase);
223 : bool WriteDescriptor(const uint256& desc_id, const WalletDescriptor& descriptor);
224 : bool WriteDescriptorDerivedCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index, uint32_t der_index);
225 : bool WriteDescriptorParentCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index);
226 : bool WriteDescriptorLastHardenedCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index);
227 : bool WriteDescriptorCacheItems(const uint256& desc_id, const DescriptorCache& cache);
228 :
229 : bool WriteLockedUTXO(const COutPoint& output);
230 : bool EraseLockedUTXO(const COutPoint& output);
231 :
232 : bool WriteAddressPreviouslySpent(const CTxDestination& dest, bool previously_spent);
233 : bool WriteAddressReceiveRequest(const CTxDestination& dest, const std::string& id, const std::string& receive_request);
234 : bool EraseAddressReceiveRequest(const CTxDestination& dest, const std::string& id);
235 : bool EraseAddressData(const CTxDestination& dest);
236 :
237 : bool WriteActiveScriptPubKeyMan(const uint256& id, bool internal);
238 : bool EraseActiveScriptPubKeyMan(bool internal);
239 :
240 : DBErrors LoadWallet(CWallet* pwallet);
241 : DBErrors FindWalletTxHashes(std::vector<uint256>& tx_hashes);
242 : DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut);
243 : /* Function to determine if a certain KV/key-type is a key (cryptographical key) type */
244 : static bool IsKeyType(const std::string& strType);
245 :
246 : //! write the hdchain model (external chain child index counter)
247 : bool WriteHDChain(const CHDChain& chain);
248 : bool WriteHDPubKey(const CHDPubKey& hdPubKey, const CKeyMetadata& keyMeta);
249 :
250 : //! Delete records of the given types
251 : bool EraseRecords(const std::unordered_set<std::string>& types);
252 :
253 : bool WriteWalletFlags(const uint64_t flags);
254 : //! Begin a new transaction
255 : bool TxnBegin();
256 : //! Commit current transaction
257 : bool TxnCommit();
258 : //! Abort current transaction
259 : bool TxnAbort();
260 : private:
261 : std::unique_ptr<DatabaseBatch> m_batch;
262 : WalletDatabase& m_database;
263 : };
264 :
265 : //! Compacts BDB state so that wallet.dat is self-contained (if there are changes)
266 : void MaybeCompactWalletDB(WalletContext& context);
267 :
268 : //! Callback for filtering key types to deserialize in ReadKeyValue
269 : using KeyFilterFn = std::function<bool(const std::string&)>;
270 :
271 : //! Unserialize a given Key-Value pair and load it into the wallet
272 : bool ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, std::string& strType, std::string& strErr, const KeyFilterFn& filter_fn = nullptr);
273 :
274 : /** Return object for accessing dummy database with no read/write capabilities. */
275 : std::unique_ptr<WalletDatabase> CreateDummyWalletDatabase();
276 :
277 : /** Return object for accessing temporary in-memory database. */
278 : std::unique_ptr<WalletDatabase> CreateMockWalletDatabase(DatabaseOptions& options);
279 : std::unique_ptr<WalletDatabase> CreateMockWalletDatabase();
280 : } // namespace wallet
281 :
282 : #endif // BITCOIN_WALLET_WALLETDB_H
|