fuzz coverage

Coverage Report

Created: 2025-08-28 15:26

/Users/eugenesiegel/btc/bitcoin/src/wallet/db.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_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 <atomic>
15
#include <memory>
16
#include <optional>
17
#include <string>
18
19
class ArgsManager;
20
struct bilingual_str;
21
22
namespace wallet {
23
// BytePrefix compares equality with other byte spans that begin with the same prefix.
24
struct BytePrefix {
25
    std::span<const std::byte> prefix;
26
};
27
bool operator<(BytePrefix a, std::span<const std::byte> b);
28
bool operator<(std::span<const std::byte> a, BytePrefix b);
29
30
class DatabaseCursor
31
{
32
public:
33
0
    explicit DatabaseCursor() = default;
34
0
    virtual ~DatabaseCursor() = default;
35
36
    DatabaseCursor(const DatabaseCursor&) = delete;
37
    DatabaseCursor& operator=(const DatabaseCursor&) = delete;
38
39
    enum class Status
40
    {
41
        FAIL,
42
        MORE,
43
        DONE,
44
    };
45
46
0
    virtual Status Next(DataStream& key, DataStream& value) { return Status::FAIL; }
47
};
48
49
/** RAII class that provides access to a WalletDatabase */
50
class DatabaseBatch
51
{
52
private:
53
    virtual bool ReadKey(DataStream&& key, DataStream& value) = 0;
54
    virtual bool WriteKey(DataStream&& key, DataStream&& value, bool overwrite = true) = 0;
55
    virtual bool EraseKey(DataStream&& key) = 0;
56
    virtual bool HasKey(DataStream&& key) = 0;
57
58
public:
59
0
    explicit DatabaseBatch() = default;
60
0
    virtual ~DatabaseBatch() = default;
61
62
    DatabaseBatch(const DatabaseBatch&) = delete;
63
    DatabaseBatch& operator=(const DatabaseBatch&) = delete;
64
65
    virtual void Flush() = 0;
66
    virtual void Close() = 0;
67
68
    template <typename K, typename T>
69
    bool Read(const K& key, T& value)
70
0
    {
71
0
        DataStream ssKey{};
72
0
        ssKey.reserve(1000);
73
0
        ssKey << key;
74
75
0
        DataStream ssValue{};
76
0
        if (!ReadKey(std::move(ssKey), ssValue)) return false;
77
0
        try {
78
0
            ssValue >> value;
79
0
            return true;
80
0
        } catch (const std::exception&) {
81
0
            return false;
82
0
        }
83
0
    }
Unexecuted instantiation: _ZN6wallet13DatabaseBatch4ReadINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEyEEbRKT_RT0_
Unexecuted instantiation: _ZN6wallet13DatabaseBatch4ReadINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE7CPubKeyEENS2_6vectorIhNS7_IhEEEEEEbRKT_RT0_
Unexecuted instantiation: _ZN6wallet13DatabaseBatch4ReadINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE13CBlockLocatorEEbRKT_RT0_
Unexecuted instantiation: _ZN6wallet13DatabaseBatch4ReadINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEExEENS_8CKeyPoolEEEbRKT_RT0_
Unexecuted instantiation: _ZN6wallet13DatabaseBatch4ReadINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEiEEbRKT_RT0_
84
85
    template <typename K, typename T>
86
    bool Write(const K& key, const T& value, bool fOverwrite = true)
87
0
    {
88
0
        DataStream ssKey{};
89
0
        ssKey.reserve(1000);
90
0
        ssKey << key;
91
92
0
        DataStream ssValue{};
93
0
        ssValue.reserve(10000);
94
0
        ssValue << value;
95
96
0
        return WriteKey(std::move(ssKey), std::move(ssValue), fOverwrite);
97
0
    }
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14spanIhLm18446744073709551615EEES4_EEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14spanIKSt4byteLm18446744073709551615EEES6_EEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEES9_EES9_EEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE22transaction_identifierILb0EEEENS_9CWalletTxEEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE7CPubKeyEENS_12CKeyMetadataEEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE7CPubKeyEENS3_INS2_6vectorIh16secure_allocatorIhEEE7uint256EEEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE7CPubKeyEENS3_INS2_6vectorIhNS7_IhEEEE7uint256EEEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEjEENS_10CMasterKeyEEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE7uint160EE7CScriptEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE7CScriptEENS_12CKeyMetadataEEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE7CScriptEEhEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE13CBlockLocatorEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEExEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEExEENS_8CKeyPoolEEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEhEE7uint256EEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS3_I7uint2567CPubKeyEEEENS3_INS2_6vectorIh16secure_allocatorIhEEESA_EEEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS3_I7uint2567CPubKeyEEEENS2_6vectorIhNS7_IhEEEEEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE7uint256EENS_16WalletDescriptorEEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS3_INS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE7uint256EENS3_IjjEEEENS2_6vectorIhNS7_IhEEEEEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS3_INS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE7uint256EEjEENS2_6vectorIhNS7_IhEEEEEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS3_I22transaction_identifierILb0EEjEEEEhEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEiEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS3_IS9_S9_EEEES9_EEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS_8CHDChainEEEbRKT_RKT0_b
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5WriteINSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEyEEbRKT_RKT0_b
98
99
    template <typename K>
100
    bool Erase(const K& key)
101
0
    {
102
0
        DataStream ssKey{};
103
0
        ssKey.reserve(1000);
104
0
        ssKey << key;
105
106
0
        return EraseKey(std::move(ssKey));
107
0
    }
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5EraseINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEES9_EEEEbRKT_
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5EraseINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE7uint256EEEEbRKT_
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5EraseINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE7CPubKeyEEEEbRKT_
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5EraseINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEjEEEEbRKT_
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5EraseINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE7CScriptEEEEbRKT_
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5EraseINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEExEEEEbRKT_
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5EraseINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEhEEEEbRKT_
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5EraseINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS3_I7uint2567CPubKeyEEEEEEbRKT_
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5EraseINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS3_I22transaction_identifierILb0EEjEEEEEEbRKT_
Unexecuted instantiation: _ZN6wallet13DatabaseBatch5EraseINSt3__14pairINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS3_IS9_S9_EEEEEEbRKT_
108
109
    template <typename K>
110
    bool Exists(const K& key)
111
    {
112
        DataStream ssKey{};
113
        ssKey.reserve(1000);
114
        ssKey << key;
115
116
        return HasKey(std::move(ssKey));
117
    }
118
    virtual bool ErasePrefix(std::span<const std::byte> prefix) = 0;
119
120
    virtual std::unique_ptr<DatabaseCursor> GetNewCursor() = 0;
121
    virtual std::unique_ptr<DatabaseCursor> GetNewPrefixCursor(std::span<const std::byte> prefix) = 0;
122
    virtual bool TxnBegin() = 0;
123
    virtual bool TxnCommit() = 0;
124
    virtual bool TxnAbort() = 0;
125
    virtual bool HasActiveTxn() = 0;
126
};
127
128
/** An instance of this class represents one database.
129
 **/
130
class WalletDatabase
131
{
132
public:
133
    /** Create dummy DB handle */
134
0
    WalletDatabase() : nUpdateCounter(0) {}
135
0
    virtual ~WalletDatabase() = default;
136
137
    /** Open the database if it is not already opened. */
138
    virtual void Open() = 0;
139
140
    //! Counts the number of active database users to be sure that the database is not closed while someone is using it
141
    std::atomic<int> m_refcount{0};
142
    /** Indicate the a new database user has began using the database. Increments m_refcount */
143
    virtual void AddRef() = 0;
144
    /** Indicate that database user has stopped using the database and that it could be flushed or closed. Decrement m_refcount */
145
    virtual void RemoveRef() = 0;
146
147
    /** Rewrite the entire database on disk, with the exception of key pszSkip if non-zero
148
     */
149
    virtual bool Rewrite(const char* pszSkip=nullptr) = 0;
150
151
    /** Back up the entire database to a file.
152
     */
153
    virtual bool Backup(const std::string& strDest) const = 0;
154
155
    /** Make sure all changes are flushed to database file.
156
     */
157
    virtual void Flush() = 0;
158
    /** Flush to the database file and close the database.
159
     *  Also close the environment if no other databases are open in it.
160
     */
161
    virtual void Close() = 0;
162
    /* flush the wallet passively (TRY_LOCK)
163
       ideal to be called periodically */
164
    virtual bool PeriodicFlush() = 0;
165
166
    virtual void IncrementUpdateCounter() = 0;
167
168
    virtual void ReloadDbEnv() = 0;
169
170
    /** Return path to main database file for logs and error messages. */
171
    virtual std::string Filename() = 0;
172
173
    virtual std::string Format() = 0;
174
175
    std::atomic<unsigned int> nUpdateCounter;
176
    unsigned int nLastSeen{0};
177
    unsigned int nLastFlushed{0};
178
    int64_t nLastWalletUpdate{0};
179
180
    /** Make a DatabaseBatch connected to this database */
181
    virtual std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) = 0;
182
};
183
184
enum class DatabaseFormat {
185
    SQLITE,
186
    BERKELEY_RO,
187
    BERKELEY_SWAP,
188
};
189
190
struct DatabaseOptions {
191
    bool require_existing = false;
192
    bool require_create = false;
193
    std::optional<DatabaseFormat> require_format;
194
    uint64_t create_flags = 0;
195
    SecureString create_passphrase;
196
197
    // Specialized options. Not every option is supported by every backend.
198
    bool verify = true;             //!< Check data integrity on load.
199
    bool use_unsafe_sync = false;   //!< Disable file sync for faster performance.
200
    bool use_shared_memory = false; //!< Let other processes access the database.
201
    int64_t max_log_mb = 100;       //!< Max log size to allow before consolidating.
202
};
203
204
enum class DatabaseStatus {
205
    SUCCESS,
206
    FAILED_BAD_PATH,
207
    FAILED_BAD_FORMAT,
208
    FAILED_ALREADY_LOADED,
209
    FAILED_ALREADY_EXISTS,
210
    FAILED_NOT_FOUND,
211
    FAILED_CREATE,
212
    FAILED_LOAD,
213
    FAILED_VERIFY,
214
    FAILED_ENCRYPT,
215
    FAILED_INVALID_BACKUP_FILE,
216
};
217
218
/** Recursively list database paths in directory. */
219
std::vector<std::pair<fs::path, std::string>> ListDatabases(const fs::path& path);
220
221
void ReadDatabaseArgs(const ArgsManager& args, DatabaseOptions& options);
222
std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
223
224
fs::path BDBDataFile(const fs::path& path);
225
fs::path SQLiteDataFile(const fs::path& path);
226
bool IsBDBFile(const fs::path& path);
227
bool IsSQLiteFile(const fs::path& path);
228
} // namespace wallet
229
230
#endif // BITCOIN_WALLET_DB_H