fuzz coverage

Coverage Report

Created: 2025-08-28 15:26

/Users/eugenesiegel/btc/bitcoin/src/wallet/bdb.h
Line
Count
Source (jump to first uncovered line)
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_BDB_H
7
#define BITCOIN_WALLET_BDB_H
8
9
#include <clientversion.h>
10
#include <common/system.h>
11
#include <serialize.h>
12
#include <streams.h>
13
#include <util/fs.h>
14
#include <wallet/db.h>
15
16
#include <atomic>
17
#include <condition_variable>
18
#include <map>
19
#include <memory>
20
#include <string>
21
#include <unordered_map>
22
#include <vector>
23
24
struct bilingual_str;
25
26
class DbEnv;
27
class DbTxn;
28
class Db;
29
class Dbc;
30
31
// This constant was introduced in BDB 4.0.14 and has never changed, but there
32
// is a belt-and-suspenders check in the cpp file just in case.
33
#define BDB_DB_FILE_ID_LEN 20 /* Unique file ID length. */
34
35
namespace wallet {
36
37
struct WalletDatabaseFileId {
38
    uint8_t value[BDB_DB_FILE_ID_LEN];
39
    bool operator==(const WalletDatabaseFileId& rhs) const;
40
};
41
42
class BerkeleyDatabase;
43
44
class BerkeleyEnvironment
45
{
46
private:
47
    bool fDbEnvInit;
48
    bool fMockDb;
49
    // Don't change into fs::path, as that can result in
50
    // shutdown problems/crashes caused by a static initialized internal pointer.
51
    std::string strPath;
52
53
public:
54
    std::unique_ptr<DbEnv> dbenv;
55
    std::map<fs::path, std::reference_wrapper<BerkeleyDatabase>> m_databases;
56
    std::unordered_map<std::string, WalletDatabaseFileId> m_fileids;
57
    std::condition_variable_any m_db_in_use;
58
    bool m_use_shared_memory;
59
60
    explicit BerkeleyEnvironment(const fs::path& env_directory, bool use_shared_memory);
61
    BerkeleyEnvironment();
62
    ~BerkeleyEnvironment();
63
    void Reset();
64
65
0
    bool IsMock() const { return fMockDb; }
66
0
    bool IsInitialized() const { return fDbEnvInit; }
67
0
    fs::path Directory() const { return fs::PathFromString(strPath); }
68
69
    bool Open(bilingual_str& error);
70
    void Close();
71
    void Flush(bool fShutdown);
72
    void CheckpointLSN(const std::string& strFile);
73
74
    void CloseDb(const fs::path& filename);
75
    void ReloadDbEnv();
76
77
    DbTxn* TxnBegin(int flags);
78
};
79
80
/** Get BerkeleyEnvironment given a directory path. */
81
std::shared_ptr<BerkeleyEnvironment> GetBerkeleyEnv(const fs::path& env_directory, bool use_shared_memory);
82
83
class BerkeleyBatch;
84
85
/** An instance of this class represents one database.
86
 * For BerkeleyDB this is just a (env, strFile) tuple.
87
 **/
88
class BerkeleyDatabase : public WalletDatabase
89
{
90
public:
91
    BerkeleyDatabase() = delete;
92
93
    /** Create DB handle to real database */
94
    BerkeleyDatabase(std::shared_ptr<BerkeleyEnvironment> env, fs::path filename, const DatabaseOptions& options);
95
96
    ~BerkeleyDatabase() override;
97
98
    /** Open the database if it is not already opened. */
99
    void Open() override;
100
101
    /** Rewrite the entire database on disk, with the exception of key pszSkip if non-zero
102
     */
103
    bool Rewrite(const char* pszSkip=nullptr) override;
104
105
    /** Indicate that a new database user has begun using the database. */
106
    void AddRef() override;
107
    /** Indicate that database user has stopped using the database and that it could be flushed or closed. */
108
    void RemoveRef() override;
109
110
    /** Back up the entire database to a file.
111
     */
112
    bool Backup(const std::string& strDest) const override;
113
114
    /** Make sure all changes are flushed to database file.
115
     */
116
    void Flush() override;
117
    /** Flush to the database file and close the database.
118
     *  Also close the environment if no other databases are open in it.
119
     */
120
    void Close() override;
121
    /* flush the wallet passively (TRY_LOCK)
122
       ideal to be called periodically */
123
    bool PeriodicFlush() override;
124
125
    void IncrementUpdateCounter() override;
126
127
    void ReloadDbEnv() override;
128
129
    /** Verifies the environment and database file */
130
    bool Verify(bilingual_str& error);
131
132
    /** Return path to main database filename */
133
0
    std::string Filename() override { return fs::PathToString(env->Directory() / m_filename); }
134
135
0
    std::string Format() override { return "bdb"; }
136
    /**
137
     * Pointer to shared database environment.
138
     *
139
     * Normally there is only one BerkeleyDatabase object per
140
     * BerkeleyEnvivonment, but in the special, backwards compatible case where
141
     * multiple wallet BDB data files are loaded from the same directory, this
142
     * will point to a shared instance that gets freed when the last data file
143
     * is closed.
144
     */
145
    std::shared_ptr<BerkeleyEnvironment> env;
146
147
    /** Database pointer. This is initialized lazily and reset during flushes, so it can be null. */
148
    std::unique_ptr<Db> m_db;
149
150
    // Whether to byteswap
151
    bool m_byteswap;
152
153
    fs::path m_filename;
154
    int64_t m_max_log_mb;
155
156
    /** Make a BerkeleyBatch connected to this database */
157
    std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override;
158
};
159
160
class BerkeleyCursor : public DatabaseCursor
161
{
162
private:
163
    Dbc* m_cursor;
164
    std::vector<std::byte> m_key_prefix;
165
    bool m_first{true};
166
167
public:
168
    // Constructor for cursor for records matching the prefix
169
    // To match all records, an empty prefix may be provided.
170
    explicit BerkeleyCursor(BerkeleyDatabase& database, const BerkeleyBatch& batch, std::span<const std::byte> prefix = {});
171
    ~BerkeleyCursor() override;
172
173
    Status Next(DataStream& key, DataStream& value) override;
174
0
    Dbc* dbc() const { return m_cursor; }
175
};
176
177
/** RAII class that provides access to a Berkeley database */
178
class BerkeleyBatch : public DatabaseBatch
179
{
180
private:
181
    bool ReadKey(DataStream&& key, DataStream& value) override;
182
    bool WriteKey(DataStream&& key, DataStream&& value, bool overwrite = true) override;
183
    bool EraseKey(DataStream&& key) override;
184
    bool HasKey(DataStream&& key) override;
185
    bool ErasePrefix(std::span<const std::byte> prefix) override;
186
187
protected:
188
    Db* pdb{nullptr};
189
    std::string strFile;
190
    DbTxn* activeTxn{nullptr};
191
    bool fReadOnly;
192
    bool fFlushOnClose;
193
    BerkeleyEnvironment *env;
194
    BerkeleyDatabase& m_database;
195
196
public:
197
    explicit BerkeleyBatch(BerkeleyDatabase& database, const bool fReadOnly, bool fFlushOnCloseIn=true);
198
    ~BerkeleyBatch() override;
199
200
    BerkeleyBatch(const BerkeleyBatch&) = delete;
201
    BerkeleyBatch& operator=(const BerkeleyBatch&) = delete;
202
203
    void Flush() override;
204
    void Close() override;
205
206
    std::unique_ptr<DatabaseCursor> GetNewCursor() override;
207
    std::unique_ptr<DatabaseCursor> GetNewPrefixCursor(std::span<const std::byte> prefix) override;
208
    bool TxnBegin() override;
209
    bool TxnCommit() override;
210
    bool TxnAbort() override;
211
0
    bool HasActiveTxn() override { return activeTxn != nullptr; }
212
0
    DbTxn* txn() const { return activeTxn; }
213
};
214
215
std::string BerkeleyDatabaseVersion();
216
217
/** Perform sanity check of runtime BDB version versus linked BDB version.
218
 */
219
bool BerkeleyDatabaseSanityCheck();
220
221
//! Return object giving access to Berkeley database at specified path.
222
std::unique_ptr<BerkeleyDatabase> MakeBerkeleyDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
223
} // namespace wallet
224
225
#endif // BITCOIN_WALLET_BDB_H