Branch data Line data Source code
1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : : // Copyright (c) 2009-present 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_DB_H
7 : : #define BITCOIN_WALLET_DB_H
8 : :
9 : : #include <clientversion.h>
10 : : #include <streams.h>
11 : : #include <support/allocators/secure.h>
12 : : #include <util/fs.h>
13 : :
14 : : #include <memory>
15 : : #include <optional>
16 : : #include <string>
17 : :
18 : : class ArgsManager;
19 : : struct bilingual_str;
20 : :
21 : : namespace wallet {
22 : : // BytePrefix compares equality with other byte spans that begin with the same prefix.
23 : : struct BytePrefix {
24 : : std::span<const std::byte> prefix;
25 : : };
26 : : bool operator<(BytePrefix a, std::span<const std::byte> b);
27 : : bool operator<(std::span<const std::byte> a, BytePrefix b);
28 : :
29 : : class DatabaseCursor
30 : : {
31 : : public:
32 [ # # ]: 363 : explicit DatabaseCursor() = default;
33 : 363 : virtual ~DatabaseCursor() = default;
34 : :
35 : : DatabaseCursor(const DatabaseCursor&) = delete;
36 : : DatabaseCursor& operator=(const DatabaseCursor&) = delete;
37 : :
38 : : enum class Status
39 : : {
40 : : FAIL,
41 : : MORE,
42 : : DONE,
43 : : };
44 : :
45 : 0 : virtual Status Next(DataStream& key, DataStream& value) { return Status::FAIL; }
46 : : };
47 : :
48 : : /** RAII class that provides access to a WalletDatabase */
49 : : class DatabaseBatch
50 : : {
51 : : private:
52 : : virtual bool ReadKey(DataStream&& key, DataStream& value) = 0;
53 : : virtual bool WriteKey(DataStream&& key, DataStream&& value, bool overwrite = true) = 0;
54 : : virtual bool EraseKey(DataStream&& key) = 0;
55 : : virtual bool HasKey(DataStream&& key) = 0;
56 : :
57 : : public:
58 [ + - ]: 20790 : explicit DatabaseBatch() = default;
59 : 20790 : virtual ~DatabaseBatch() = default;
60 : :
61 : : DatabaseBatch(const DatabaseBatch&) = delete;
62 : : DatabaseBatch& operator=(const DatabaseBatch&) = delete;
63 : :
64 : : virtual void Close() = 0;
65 : :
66 : : template <typename K, typename T>
67 : 122 : bool Read(const K& key, T& value)
68 : : {
69 [ + - ]: 122 : DataStream ssKey{};
70 [ + - ]: 122 : ssKey.reserve(1000);
71 : 122 : ssKey << key;
72 : :
73 : 122 : DataStream ssValue{};
74 [ + - + + ]: 122 : if (!ReadKey(std::move(ssKey), ssValue)) return false;
75 : : try {
76 : 122 : ssValue >> value;
77 : : return true;
78 [ - - ]: 0 : } catch (const std::exception&) {
79 : : return false;
80 : : }
81 : 122 : }
82 : :
83 : : template <typename K, typename T>
84 : 32576 : bool Write(const K& key, const T& value, bool fOverwrite = true)
85 : : {
86 [ + - ]: 32576 : DataStream ssKey{};
87 [ + - ]: 32576 : ssKey.reserve(1000);
88 : 32576 : ssKey << key;
89 : :
90 [ + - ]: 32576 : DataStream ssValue{};
91 [ + - ]: 32576 : ssValue.reserve(10000);
92 : 32576 : ssValue << value;
93 : :
94 [ + - ]: 32576 : return WriteKey(std::move(ssKey), std::move(ssValue), fOverwrite);
95 : 32576 : }
96 : :
97 : : template <typename K>
98 : 121 : bool Erase(const K& key)
99 : : {
100 [ + - ]: 121 : DataStream ssKey{};
101 [ + - ]: 121 : ssKey.reserve(1000);
102 : 121 : ssKey << key;
103 : :
104 [ + - ]: 121 : return EraseKey(std::move(ssKey));
105 : 121 : }
106 : :
107 : : template <typename K>
108 : 11 : bool Exists(const K& key)
109 : : {
110 [ + - ]: 11 : DataStream ssKey{};
111 [ + - ]: 11 : ssKey.reserve(1000);
112 : 11 : ssKey << key;
113 : :
114 [ + - ]: 11 : return HasKey(std::move(ssKey));
115 : 11 : }
116 : : virtual bool ErasePrefix(std::span<const std::byte> prefix) = 0;
117 : :
118 : : virtual std::unique_ptr<DatabaseCursor> GetNewCursor() = 0;
119 : : virtual std::unique_ptr<DatabaseCursor> GetNewPrefixCursor(std::span<const std::byte> prefix) = 0;
120 : : virtual bool TxnBegin() = 0;
121 : : virtual bool TxnCommit() = 0;
122 : : virtual bool TxnAbort() = 0;
123 : : virtual bool HasActiveTxn() = 0;
124 : : };
125 : :
126 : : /** An instance of this class represents one database.
127 : : **/
128 : : class WalletDatabase
129 : : {
130 : : public:
131 : : /** Create dummy DB handle */
132 [ + - ]: 124 : WalletDatabase() = default;
133 : 124 : virtual ~WalletDatabase() = default;
134 : :
135 : : /** Open the database if it is not already opened. */
136 : : virtual void Open() = 0;
137 : :
138 : : /** Rewrite the entire database on disk
139 : : */
140 : : virtual bool Rewrite() = 0;
141 : :
142 : : /** Back up the entire database to a file.
143 : : */
144 : : virtual bool Backup(const std::string& strDest) const = 0;
145 : :
146 : : /** Flush to the database file and close the database.
147 : : * Also close the environment if no other databases are open in it.
148 : : */
149 : : virtual void Close() = 0;
150 : :
151 : : /** Return path to main database file for logs and error messages. */
152 : : virtual std::string Filename() = 0;
153 : :
154 : : /** Return paths to all database created files */
155 : : virtual std::vector<fs::path> Files() = 0;
156 : :
157 : : virtual std::string Format() = 0;
158 : :
159 : : /** Make a DatabaseBatch connected to this database */
160 : : virtual std::unique_ptr<DatabaseBatch> MakeBatch() = 0;
161 : : };
162 : :
163 : : enum class DatabaseFormat {
164 : : SQLITE,
165 : : BERKELEY_RO,
166 : : };
167 : :
168 [ + - + - ]: 258 : struct DatabaseOptions {
[ + - ][ + -
+ - + - ]
[ # # # #
# # # # #
# ]
169 : : bool require_existing = false;
170 : : bool require_create = false;
171 : : std::optional<DatabaseFormat> require_format;
172 : : uint64_t create_flags = 0;
173 : : SecureString create_passphrase;
174 : :
175 : : // Specialized options. Not every option is supported by every backend.
176 : : bool verify = true; //!< Check data integrity on load.
177 : : bool use_unsafe_sync = false; //!< Disable file sync for faster performance.
178 : : };
179 : :
180 : : enum class DatabaseStatus {
181 : : SUCCESS,
182 : : FAILED_BAD_PATH,
183 : : FAILED_BAD_FORMAT,
184 : : FAILED_LEGACY_DISABLED,
185 : : FAILED_ALREADY_LOADED,
186 : : FAILED_ALREADY_EXISTS,
187 : : FAILED_NOT_FOUND,
188 : : FAILED_CREATE,
189 : : FAILED_LOAD,
190 : : FAILED_VERIFY,
191 : : FAILED_ENCRYPT,
192 : : FAILED_INVALID_BACKUP_FILE,
193 : : FAILED_NEW_UNNAMED,
194 : : };
195 : :
196 : : /** Recursively list database paths in directory. */
197 : : std::vector<std::pair<fs::path, std::string>> ListDatabases(const fs::path& path);
198 : :
199 : : void ReadDatabaseArgs(const ArgsManager& args, DatabaseOptions& options);
200 : : std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
201 : :
202 : : fs::path BDBDataFile(const fs::path& path);
203 : : fs::path SQLiteDataFile(const fs::path& path);
204 : : bool IsBDBFile(const fs::path& path);
205 : : bool IsSQLiteFile(const fs::path& path);
206 : : } // namespace wallet
207 : :
208 : : #endif // BITCOIN_WALLET_DB_H
|