Coverage Report

Created: 2024-10-21 15:10

/root/bitcoin/src/dbwrapper.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2012-2022 The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5
#ifndef BITCOIN_DBWRAPPER_H
6
#define BITCOIN_DBWRAPPER_H
7
8
#include <attributes.h>
9
#include <serialize.h>
10
#include <span.h>
11
#include <streams.h>
12
#include <util/check.h>
13
#include <util/fs.h>
14
15
#include <cstddef>
16
#include <exception>
17
#include <memory>
18
#include <optional>
19
#include <stdexcept>
20
#include <string>
21
#include <vector>
22
23
static const size_t DBWRAPPER_PREALLOC_KEY_SIZE = 64;
24
static const size_t DBWRAPPER_PREALLOC_VALUE_SIZE = 1024;
25
26
//! User-controlled performance and debug options.
27
struct DBOptions {
28
    //! Compact database on startup.
29
    bool force_compact = false;
30
};
31
32
//! Application-specific storage settings.
33
struct DBParams {
34
    //! Location in the filesystem where leveldb data will be stored.
35
    fs::path path;
36
    //! Configures various leveldb cache settings.
37
    size_t cache_bytes;
38
    //! If true, use leveldb's memory environment.
39
    bool memory_only = false;
40
    //! If true, remove all existing data.
41
    bool wipe_data = false;
42
    //! If true, store data obfuscated via simple XOR. If false, XOR with a
43
    //! zero'd byte array.
44
    bool obfuscate = false;
45
    //! Passed-through options.
46
    DBOptions options{};
47
};
48
49
class dbwrapper_error : public std::runtime_error
50
{
51
public:
52
0
    explicit dbwrapper_error(const std::string& msg) : std::runtime_error(msg) {}
53
};
54
55
class CDBWrapper;
56
57
/** These should be considered an implementation detail of the specific database.
58
 */
59
namespace dbwrapper_private {
60
61
/** Work around circular dependency, as well as for testing in dbwrapper_tests.
62
 * Database obfuscation should be considered an implementation detail of the
63
 * specific database.
64
 */
65
const std::vector<unsigned char>& GetObfuscateKey(const CDBWrapper &w);
66
67
}; // namespace dbwrapper_private
68
69
bool DestroyDB(const std::string& path_str);
70
71
/** Batch of changes queued to be written to a CDBWrapper */
72
class CDBBatch
73
{
74
    friend class CDBWrapper;
75
76
private:
77
    const CDBWrapper &parent;
78
79
    struct WriteBatchImpl;
80
    const std::unique_ptr<WriteBatchImpl> m_impl_batch;
81
82
    DataStream ssKey{};
83
    DataStream ssValue{};
84
85
    size_t size_estimate{0};
86
87
    void WriteImpl(Span<const std::byte> key, DataStream& ssValue);
88
    void EraseImpl(Span<const std::byte> key);
89
90
public:
91
    /**
92
     * @param[in] _parent   CDBWrapper that this batch is to be submitted to
93
     */
94
    explicit CDBBatch(const CDBWrapper& _parent);
95
    ~CDBBatch();
96
    void Clear();
97
98
    template <typename K, typename V>
99
    void Write(const K& key, const V& value)
100
0
    {
101
0
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
102
0
        ssValue.reserve(DBWRAPPER_PREALLOC_VALUE_SIZE);
103
0
        ssKey << key;
104
0
        ssValue << value;
105
0
        WriteImpl(ssKey, ssValue);
106
0
        ssKey.clear();
107
0
        ssValue.clear();
108
0
    }
Unexecuted instantiation: _ZN8CDBBatch5WriteINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt6vectorIhSaIhEEEEvRKT_RKT0_
Unexecuted instantiation: _ZN8CDBBatch5WriteIhhEEvRKT_RKT0_
Unexecuted instantiation: _ZN8CDBBatch5WriteISt4pairIhiE14CBlockFileInfoEEvRKT_RKT0_
Unexecuted instantiation: _ZN8CDBBatch5WriteIhiEEvRKT_RKT0_
Unexecuted instantiation: _ZN8CDBBatch5WriteISt4pairIh7uint256E15CDiskBlockIndexEEvRKT_RKT0_
Unexecuted instantiation: _ZN8CDBBatch5WriteISt4pairIhNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEhEEvRKT_RKT0_
Unexecuted instantiation: _ZN8CDBBatch5WriteIhSt6vectorI7uint256SaIS2_EEEEvRKT_RKT0_
Unexecuted instantiation: txdb.cpp:_ZN8CDBBatch5WriteIN12_GLOBAL__N_19CoinEntryE4CoinEEvRKT_RKT0_
Unexecuted instantiation: _ZN8CDBBatch5WriteIh7uint256EEvRKT_RKT0_
Unexecuted instantiation: _ZN8CDBBatch5WriteIh13CBlockLocatorEEvRKT_RKT0_
Unexecuted instantiation: blockfilterindex.cpp:_ZN8CDBBatch5WriteIN12_GLOBAL__N_19DBHashKeyENS1_5DBValEEEvRKT_RKT0_
Unexecuted instantiation: _ZN8CDBBatch5WriteIh11FlatFilePosEEvRKT_RKT0_
Unexecuted instantiation: blockfilterindex.cpp:_ZN8CDBBatch5WriteIN12_GLOBAL__N_111DBHeightKeyESt4pairI7uint256NS1_5DBValEEEEvRKT_RKT0_
Unexecuted instantiation: coinstatsindex.cpp:_ZN8CDBBatch5WriteIN12_GLOBAL__N_19DBHashKeyENS1_5DBValEEEvRKT_RKT0_
Unexecuted instantiation: coinstatsindex.cpp:_ZN8CDBBatch5WriteIN12_GLOBAL__N_111DBHeightKeyESt4pairI7uint256NS1_5DBValEEEEvRKT_RKT0_
Unexecuted instantiation: _ZN8CDBBatch5WriteIh10MuHash3072EEvRKT_RKT0_
Unexecuted instantiation: _ZN8CDBBatch5WriteISt4pairIh7uint256E10CDiskTxPosEEvRKT_RKT0_
109
110
    template <typename K>
111
    void Erase(const K& key)
112
0
    {
113
0
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
114
0
        ssKey << key;
115
0
        EraseImpl(ssKey);
116
0
        ssKey.clear();
117
0
    }
Unexecuted instantiation: _ZN8CDBBatch5EraseIhEEvRKT_
Unexecuted instantiation: txdb.cpp:_ZN8CDBBatch5EraseIN12_GLOBAL__N_19CoinEntryEEEvRKT_
118
119
0
    size_t SizeEstimate() const { return size_estimate; }
120
};
121
122
class CDBIterator
123
{
124
public:
125
    struct IteratorImpl;
126
127
private:
128
    const CDBWrapper &parent;
129
    const std::unique_ptr<IteratorImpl> m_impl_iter;
130
131
    void SeekImpl(Span<const std::byte> key);
132
    Span<const std::byte> GetKeyImpl() const;
133
    Span<const std::byte> GetValueImpl() const;
134
135
public:
136
137
    /**
138
     * @param[in] _parent          Parent CDBWrapper instance.
139
     * @param[in] _piter           The original leveldb iterator.
140
     */
141
    CDBIterator(const CDBWrapper& _parent, std::unique_ptr<IteratorImpl> _piter);
142
    ~CDBIterator();
143
144
    bool Valid() const;
145
146
    void SeekToFirst();
147
148
0
    template<typename K> void Seek(const K& key) {
149
0
        DataStream ssKey{};
150
0
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
151
0
        ssKey << key;
152
0
        SeekImpl(ssKey);
153
0
    }
Unexecuted instantiation: _ZN11CDBIterator4SeekISt4pairIh7uint256EEEvRKT_
Unexecuted instantiation: _ZN11CDBIterator4SeekIhEEvRKT_
Unexecuted instantiation: blockfilterindex.cpp:_ZN11CDBIterator4SeekIN12_GLOBAL__N_111DBHeightKeyEEEvRKT_
Unexecuted instantiation: coinstatsindex.cpp:_ZN11CDBIterator4SeekIN12_GLOBAL__N_111DBHeightKeyEEEvRKT_
154
155
    void Next();
156
157
0
    template<typename K> bool GetKey(K& key) {
158
0
        try {
159
0
            DataStream ssKey{GetKeyImpl()};
160
0
            ssKey >> key;
161
0
        } catch (const std::exception&) {
162
0
            return false;
163
0
        }
164
0
        return true;
165
0
    }
Unexecuted instantiation: _ZN11CDBIterator6GetKeyISt4pairIh7uint256EEEbRT_
Unexecuted instantiation: txdb.cpp:_ZN11CDBIterator6GetKeyIN12_GLOBAL__N_19CoinEntryEEEbRT_
Unexecuted instantiation: blockfilterindex.cpp:_ZN11CDBIterator6GetKeyIN12_GLOBAL__N_111DBHeightKeyEEEbRT_
Unexecuted instantiation: coinstatsindex.cpp:_ZN11CDBIterator6GetKeyIN12_GLOBAL__N_111DBHeightKeyEEEbRT_
166
167
0
    template<typename V> bool GetValue(V& value) {
168
0
        try {
169
0
            DataStream ssValue{GetValueImpl()};
170
0
            ssValue.Xor(dbwrapper_private::GetObfuscateKey(parent));
171
0
            ssValue >> value;
172
0
        } catch (const std::exception&) {
173
0
            return false;
174
0
        }
175
0
        return true;
176
0
    }
Unexecuted instantiation: _ZN11CDBIterator8GetValueI15CDiskBlockIndexEEbRT_
Unexecuted instantiation: _ZN11CDBIterator8GetValueI4CoinEEbRT_
Unexecuted instantiation: blockfilterindex.cpp:_ZN11CDBIterator8GetValueISt4pairI7uint256N12_GLOBAL__N_15DBValEEEEbRT_
Unexecuted instantiation: coinstatsindex.cpp:_ZN11CDBIterator8GetValueISt4pairI7uint256N12_GLOBAL__N_15DBValEEEEbRT_
177
};
178
179
struct LevelDBContext;
180
181
class CDBWrapper
182
{
183
    friend const std::vector<unsigned char>& dbwrapper_private::GetObfuscateKey(const CDBWrapper &w);
184
private:
185
    //! holds all leveldb-specific fields of this class
186
    std::unique_ptr<LevelDBContext> m_db_context;
187
188
    //! the name of this database
189
    std::string m_name;
190
191
    //! a key used for optional XOR-obfuscation of the database
192
    std::vector<unsigned char> obfuscate_key;
193
194
    //! the key under which the obfuscation key is stored
195
    static const std::string OBFUSCATE_KEY_KEY;
196
197
    //! the length of the obfuscate key in number of bytes
198
    static const unsigned int OBFUSCATE_KEY_NUM_BYTES;
199
200
    std::vector<unsigned char> CreateObfuscateKey() const;
201
202
    //! path to filesystem storage
203
    const fs::path m_path;
204
205
    //! whether or not the database resides in memory
206
    bool m_is_memory;
207
208
    std::optional<std::string> ReadImpl(Span<const std::byte> key) const;
209
    bool ExistsImpl(Span<const std::byte> key) const;
210
    size_t EstimateSizeImpl(Span<const std::byte> key1, Span<const std::byte> key2) const;
211
0
    auto& DBContext() const LIFETIMEBOUND { return *Assert(m_db_context); }
212
213
public:
214
    CDBWrapper(const DBParams& params);
215
    ~CDBWrapper();
216
217
    CDBWrapper(const CDBWrapper&) = delete;
218
    CDBWrapper& operator=(const CDBWrapper&) = delete;
219
220
    template <typename K, typename V>
221
    bool Read(const K& key, V& value) const
222
0
    {
223
0
        DataStream ssKey{};
224
0
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
225
0
        ssKey << key;
226
0
        std::optional<std::string> strValue{ReadImpl(ssKey)};
227
0
        if (!strValue) {
228
0
            return false;
229
0
        }
230
0
        try {
231
0
            DataStream ssValue{MakeByteSpan(*strValue)};
232
0
            ssValue.Xor(obfuscate_key);
233
0
            ssValue >> value;
234
0
        } catch (const std::exception&) {
235
0
            return false;
236
0
        }
237
0
        return true;
238
0
    }
Unexecuted instantiation: _ZNK10CDBWrapper4ReadINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt6vectorIhSaIhEEEEbRKT_RT0_
Unexecuted instantiation: _ZNK10CDBWrapper4ReadISt4pairIhiE14CBlockFileInfoEEbRKT_RT0_
Unexecuted instantiation: _ZNK10CDBWrapper4ReadIhiEEbRKT_RT0_
Unexecuted instantiation: _ZNK10CDBWrapper4ReadISt4pairIhNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEhEEbRKT_RT0_
Unexecuted instantiation: txdb.cpp:_ZNK10CDBWrapper4ReadIN12_GLOBAL__N_19CoinEntryE4CoinEEbRKT_RT0_
Unexecuted instantiation: _ZNK10CDBWrapper4ReadIh7uint256EEbRKT_RT0_
Unexecuted instantiation: _ZNK10CDBWrapper4ReadIhSt6vectorI7uint256SaIS2_EEEEbRKT_RT0_
Unexecuted instantiation: _ZNK10CDBWrapper4ReadIh13CBlockLocatorEEbRKT_RT0_
Unexecuted instantiation: blockfilterindex.cpp:_ZNK10CDBWrapper4ReadIN12_GLOBAL__N_19DBHashKeyENS1_5DBValEEEbRKT_RT0_
Unexecuted instantiation: _ZNK10CDBWrapper4ReadIh11FlatFilePosEEbRKT_RT0_
Unexecuted instantiation: blockfilterindex.cpp:_ZNK10CDBWrapper4ReadIN12_GLOBAL__N_111DBHeightKeyESt4pairI7uint256NS1_5DBValEEEEbRKT_RT0_
Unexecuted instantiation: coinstatsindex.cpp:_ZNK10CDBWrapper4ReadIN12_GLOBAL__N_19DBHashKeyENS1_5DBValEEEbRKT_RT0_
Unexecuted instantiation: coinstatsindex.cpp:_ZNK10CDBWrapper4ReadIN12_GLOBAL__N_111DBHeightKeyESt4pairI7uint256NS1_5DBValEEEEbRKT_RT0_
Unexecuted instantiation: coinstatsindex.cpp:_ZNK10CDBWrapper4ReadIN12_GLOBAL__N_19DBHashKeyESt4pairI7uint256NS1_5DBValEEEEbRKT_RT0_
Unexecuted instantiation: _ZNK10CDBWrapper4ReadIh10MuHash3072EEbRKT_RT0_
Unexecuted instantiation: _ZNK10CDBWrapper4ReadISt4pairIh7uint256E10CDiskTxPosEEbRKT_RT0_
239
240
    template <typename K, typename V>
241
    bool Write(const K& key, const V& value, bool fSync = false)
242
0
    {
243
0
        CDBBatch batch(*this);
244
0
        batch.Write(key, value);
245
0
        return WriteBatch(batch, fSync);
246
0
    }
Unexecuted instantiation: _ZN10CDBWrapper5WriteINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt6vectorIhSaIhEEEEbRKT_RKT0_b
Unexecuted instantiation: _ZN10CDBWrapper5WriteIhhEEbRKT_RKT0_b
Unexecuted instantiation: _ZN10CDBWrapper5WriteISt4pairIhNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEhEEbRKT_RKT0_b
Unexecuted instantiation: blockfilterindex.cpp:_ZN10CDBWrapper5WriteIN12_GLOBAL__N_111DBHeightKeyESt4pairI7uint256NS1_5DBValEEEEbRKT_RKT0_b
Unexecuted instantiation: coinstatsindex.cpp:_ZN10CDBWrapper5WriteIN12_GLOBAL__N_111DBHeightKeyESt4pairI7uint256NS1_5DBValEEEEbRKT_RKT0_b
247
248
    //! @returns filesystem path to the on-disk data.
249
0
    std::optional<fs::path> StoragePath() {
250
0
        if (m_is_memory) {
251
0
            return {};
252
0
        }
253
0
        return m_path;
254
0
    }
255
256
    template <typename K>
257
    bool Exists(const K& key) const
258
0
    {
259
0
        DataStream ssKey{};
260
0
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
261
0
        ssKey << key;
262
0
        return ExistsImpl(ssKey);
263
0
    }
Unexecuted instantiation: _ZNK10CDBWrapper6ExistsIhEEbRKT_
Unexecuted instantiation: txdb.cpp:_ZNK10CDBWrapper6ExistsIN12_GLOBAL__N_19CoinEntryEEEbRKT_
264
265
    template <typename K>
266
    bool Erase(const K& key, bool fSync = false)
267
0
    {
268
0
        CDBBatch batch(*this);
269
0
        batch.Erase(key);
270
0
        return WriteBatch(batch, fSync);
271
0
    }
272
273
    bool WriteBatch(CDBBatch& batch, bool fSync = false);
274
275
    // Get an estimate of LevelDB memory usage (in bytes).
276
    size_t DynamicMemoryUsage() const;
277
278
    CDBIterator* NewIterator();
279
280
    /**
281
     * Return true if the database managed by this class contains no entries.
282
     */
283
    bool IsEmpty();
284
285
    template<typename K>
286
    size_t EstimateSize(const K& key_begin, const K& key_end) const
287
0
    {
288
0
        DataStream ssKey1{}, ssKey2{};
289
0
        ssKey1.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
290
0
        ssKey2.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
291
0
        ssKey1 << key_begin;
292
0
        ssKey2 << key_end;
293
0
        return EstimateSizeImpl(ssKey1, ssKey2);
294
0
    }
295
};
296
297
#endif // BITCOIN_DBWRAPPER_H