Coverage Report

Created: 2026-10-07 13:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/tmp/bitcoin/src/dbwrapper.h
Line
Count
Source
1
// Copyright (c) 2012-present 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/byte_units.h>
13
#include <util/check.h>
14
#include <util/expected.h>
15
#include <util/fs.h>
16
#include <util/not_null.h>
17
#include <util/obfuscation.h>
18
19
#include <cstddef>
20
#include <cstdint>
21
#include <exception>
22
#include <memory>
23
#include <optional>
24
#include <span>
25
#include <stdexcept>
26
#include <string>
27
28
namespace leveldb {
29
class Env;
30
} // namespace leveldb
31
32
inline constexpr size_t DBWRAPPER_PREALLOC_KEY_SIZE = 64;
33
inline constexpr size_t DBWRAPPER_PREALLOC_VALUE_SIZE = 1024;
34
inline constexpr size_t DBWRAPPER_MAX_FILE_SIZE{32_MiB};
35
36
//! User-controlled performance and debug options.
37
struct DBOptions {
38
    //! Compact database on startup.
39
    bool force_compact = false;
40
};
41
42
//! Application-specific storage settings.
43
struct DBParams {
44
    //! Location in the filesystem where leveldb data will be stored.
45
    fs::path path;
46
    //! Configures various leveldb cache settings.
47
    uint64_t cache_bytes;
48
    //! If true, use leveldb's memory environment.
49
    bool memory_only = false;
50
    //! If true, remove all existing data.
51
    bool wipe_data = false;
52
    //! If true, store data obfuscated via simple XOR. If false, XOR with a
53
    //! zero'd byte array.
54
    bool obfuscate = false;
55
    //! If true, build a LevelDB bloom filter to accelerate point lookups.
56
    bool bloom_filter = true;
57
    //! Passed-through options.
58
    DBOptions options{};
59
    //! If non-null, use this as the leveldb::Env instead of the default.
60
    //! Caller retains ownership.
61
    leveldb::Env* testing_env = nullptr;
62
    //! Maximum LevelDB SST file size. Larger values reduce the frequency
63
    //! of compactions but increase their duration.
64
    size_t max_file_size = DBWRAPPER_MAX_FILE_SIZE;
65
};
66
67
class dbwrapper_error : public std::runtime_error
68
{
69
public:
70
14
    explicit dbwrapper_error(const std::string& msg) : std::runtime_error(msg) {}
71
};
72
73
class CDBWrapper;
74
75
/** These should be considered an implementation detail of the specific database.
76
 */
77
namespace dbwrapper_private {
78
79
/** Work around circular dependency, as well as for testing in dbwrapper_tests.
80
 * Database obfuscation should be considered an implementation detail of the
81
 * specific database.
82
 */
83
const Obfuscation& GetObfuscation(const CDBWrapper&);
84
}; // namespace dbwrapper_private
85
86
bool DestroyDB(const std::string& path_str);
87
88
/** Batch of changes queued to be written to a CDBWrapper */
89
class CDBBatch
90
{
91
    friend class CDBWrapper;
92
93
private:
94
    const CDBWrapper &parent;
95
96
    struct WriteBatchImpl;
97
    const std::unique_ptr<WriteBatchImpl> m_impl_batch;
98
99
    DataStream m_key_scratch{};
100
    DataStream m_value_scratch{};
101
102
    void WriteImpl(std::span<const std::byte> key, DataStream& value);
103
    void EraseImpl(std::span<const std::byte> key);
104
105
public:
106
    /**
107
     * @param[in] _parent   CDBWrapper that this batch is to be submitted to
108
     */
109
    explicit CDBBatch(const CDBWrapper& _parent);
110
    ~CDBBatch();
111
    void Clear();
112
113
    template <typename K, typename V>
114
    void Write(const K& key, const V& value)
115
452k
    {
116
452k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
452k
        m_key_scratch << key;
118
452k
        m_value_scratch << value;
119
452k
        WriteImpl(m_key_scratch, m_value_scratch);
120
452k
    }
void CDBBatch::Write<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, uint256>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, uint256 const&)
Line
Count
Source
115
8
    {
116
8
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
8
        m_key_scratch << key;
118
8
        m_value_scratch << value;
119
8
        WriteImpl(m_key_scratch, m_value_scratch);
120
8
    }
void CDBBatch::Write<unsigned char, unsigned int>(unsigned char const&, unsigned int const&)
Line
Count
Source
115
258
    {
116
258
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
258
        m_key_scratch << key;
118
258
        m_value_scratch << value;
119
258
        WriteImpl(m_key_scratch, m_value_scratch);
120
258
    }
void CDBBatch::Write<unsigned char, bool>(unsigned char const&, bool const&)
Line
Count
Source
115
2
    {
116
2
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
2
        m_key_scratch << key;
118
2
        m_value_scratch << value;
119
2
        WriteImpl(m_key_scratch, m_value_scratch);
120
2
    }
void CDBBatch::Write<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, bool>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, bool const&)
Line
Count
Source
115
2
    {
116
2
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
2
        m_key_scratch << key;
118
2
        m_value_scratch << value;
119
2
        WriteImpl(m_key_scratch, m_value_scratch);
120
2
    }
void CDBBatch::Write<unsigned char, uint256>(unsigned char const&, uint256 const&)
Line
Count
Source
115
3.96k
    {
116
3.96k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
3.96k
        m_key_scratch << key;
118
3.96k
        m_value_scratch << value;
119
3.96k
        WriteImpl(m_key_scratch, m_value_scratch);
120
3.96k
    }
void CDBBatch::Write<unsigned char, unsigned char>(unsigned char const&, unsigned char const&)
Line
Count
Source
115
19
    {
116
19
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
19
        m_key_scratch << key;
118
19
        m_value_scratch << value;
119
19
        WriteImpl(m_key_scratch, m_value_scratch);
120
19
    }
void CDBBatch::Write<dbwrapper_tests::StringContentsSerializer, unsigned int>(dbwrapper_tests::StringContentsSerializer const&, unsigned int const&)
Line
Count
Source
115
100
    {
116
100
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
100
        m_key_scratch << key;
118
100
        m_value_scratch << value;
119
100
        WriteImpl(m_key_scratch, m_value_scratch);
120
100
    }
void CDBBatch::Write<txindex::DBKey, std::array<std::byte, 0ul>>(txindex::DBKey const&, std::array<std::byte, 0ul> const&)
Line
Count
Source
115
4.38k
    {
116
4.38k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
4.38k
        m_key_scratch << key;
118
4.38k
        m_value_scratch << value;
119
4.38k
        WriteImpl(m_key_scratch, m_value_scratch);
120
4.38k
    }
void CDBBatch::Write<std::pair<unsigned char, uint256>, CDiskTxPos>(std::pair<unsigned char, uint256> const&, CDiskTxPos const&)
Line
Count
Source
115
2
    {
116
2
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
2
        m_key_scratch << key;
118
2
        m_value_scratch << value;
119
2
        WriteImpl(m_key_scratch, m_value_scratch);
120
2
    }
void CDBBatch::Write<unsigned char, CBlockLocator>(unsigned char const&, CBlockLocator const&)
Line
Count
Source
115
219
    {
116
219
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
219
        m_key_scratch << key;
118
219
        m_value_scratch << value;
119
219
        WriteImpl(m_key_scratch, m_value_scratch);
120
219
    }
void CDBBatch::Write<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, Obfuscation>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, Obfuscation const&)
Line
Count
Source
115
563
    {
116
563
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
563
        m_key_scratch << key;
118
563
        m_value_scratch << value;
119
563
        WriteImpl(m_key_scratch, m_value_scratch);
120
563
    }
void CDBBatch::Write<unsigned char, FlatFilePos>(unsigned char const&, FlatFilePos const&)
Line
Count
Source
115
178
    {
116
178
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
178
        m_key_scratch << key;
118
178
        m_value_scratch << value;
119
178
        WriteImpl(m_key_scratch, m_value_scratch);
120
178
    }
blockfilterindex.cpp:void CDBBatch::Write<index_util::DBHeightKey, std::pair<uint256, (anonymous namespace)::DBVal>>(index_util::DBHeightKey const&, std::pair<uint256, (anonymous namespace)::DBVal> const&)
Line
Count
Source
115
7.98k
    {
116
7.98k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
7.98k
        m_key_scratch << key;
118
7.98k
        m_value_scratch << value;
119
7.98k
        WriteImpl(m_key_scratch, m_value_scratch);
120
7.98k
    }
blockfilterindex.cpp:void CDBBatch::Write<index_util::DBHashKey, (anonymous namespace)::DBVal>(index_util::DBHashKey const&, (anonymous namespace)::DBVal const&)
Line
Count
Source
115
112
    {
116
112
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
112
        m_key_scratch << key;
118
112
        m_value_scratch << value;
119
112
        WriteImpl(m_key_scratch, m_value_scratch);
120
112
    }
coinstatsindex.cpp:void CDBBatch::Write<index_util::DBHeightKey, std::pair<uint256, (anonymous namespace)::DBVal>>(index_util::DBHeightKey const&, std::pair<uint256, (anonymous namespace)::DBVal> const&)
Line
Count
Source
115
4.08k
    {
116
4.08k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
4.08k
        m_key_scratch << key;
118
4.08k
        m_value_scratch << value;
119
4.08k
        WriteImpl(m_key_scratch, m_value_scratch);
120
4.08k
    }
coinstatsindex.cpp:void CDBBatch::Write<index_util::DBHashKey, (anonymous namespace)::DBVal>(index_util::DBHashKey const&, (anonymous namespace)::DBVal const&)
Line
Count
Source
115
121
    {
116
121
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
121
        m_key_scratch << key;
118
121
        m_value_scratch << value;
119
121
        WriteImpl(m_key_scratch, m_value_scratch);
120
121
    }
void CDBBatch::Write<unsigned char, MuHash3072>(unsigned char const&, MuHash3072 const&)
Line
Count
Source
115
118
    {
116
118
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
118
        m_key_scratch << key;
118
118
        m_value_scratch << value;
119
118
        WriteImpl(m_key_scratch, m_value_scratch);
120
118
    }
void CDBBatch::Write<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::pair<unsigned long, unsigned long>>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::pair<unsigned long, unsigned long> const&)
Line
Count
Source
115
22
    {
116
22
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
22
        m_key_scratch << key;
118
22
        m_value_scratch << value;
119
22
        WriteImpl(m_key_scratch, m_value_scratch);
120
22
    }
void CDBBatch::Write<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, CBlockLocator>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, CBlockLocator const&)
Line
Count
Source
115
55
    {
116
55
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
55
        m_key_scratch << key;
118
55
        m_value_scratch << value;
119
55
        WriteImpl(m_key_scratch, m_value_scratch);
120
55
    }
void CDBBatch::Write<txindex::BlockHashKey, unsigned int>(txindex::BlockHashKey const&, unsigned int const&)
Line
Count
Source
115
4.22k
    {
116
4.22k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
4.22k
        m_key_scratch << key;
118
4.22k
        m_value_scratch << value;
119
4.22k
        WriteImpl(m_key_scratch, m_value_scratch);
120
4.22k
    }
void CDBBatch::Write<txindex::BlockSeqKey, uint256>(txindex::BlockSeqKey const&, uint256 const&)
Line
Count
Source
115
4.22k
    {
116
4.22k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
4.22k
        m_key_scratch << key;
118
4.22k
        m_value_scratch << value;
119
4.22k
        WriteImpl(m_key_scratch, m_value_scratch);
120
4.22k
    }
void CDBBatch::Write<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, unsigned int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, unsigned int const&)
Line
Count
Source
115
4.22k
    {
116
4.22k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
4.22k
        m_key_scratch << key;
118
4.22k
        m_value_scratch << value;
119
4.22k
        WriteImpl(m_key_scratch, m_value_scratch);
120
4.22k
    }
void CDBBatch::Write<char [12], std::pair<unsigned long, unsigned long>>(char const (&) [12], std::pair<unsigned long, unsigned long> const&)
Line
Count
Source
115
9
    {
116
9
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
9
        m_key_scratch << key;
118
9
        m_value_scratch << value;
119
9
        WriteImpl(m_key_scratch, m_value_scratch);
120
9
    }
void CDBBatch::Write<DBKey, std::span<std::byte const, 18446744073709551615ul>>(DBKey const&, std::span<std::byte const, 18446744073709551615ul> const&)
Line
Count
Source
115
38
    {
116
38
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
38
        m_key_scratch << key;
118
38
        m_value_scratch << value;
119
38
        WriteImpl(m_key_scratch, m_value_scratch);
120
38
    }
void CDBBatch::Write<std::pair<unsigned char, int>, kernel::CBlockFileInfo>(std::pair<unsigned char, int> const&, kernel::CBlockFileInfo const&)
Line
Count
Source
115
1.72k
    {
116
1.72k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
1.72k
        m_key_scratch << key;
118
1.72k
        m_value_scratch << value;
119
1.72k
        WriteImpl(m_key_scratch, m_value_scratch);
120
1.72k
    }
void CDBBatch::Write<unsigned char, int>(unsigned char const&, int const&)
Line
Count
Source
115
3.64k
    {
116
3.64k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
3.64k
        m_key_scratch << key;
118
3.64k
        m_value_scratch << value;
119
3.64k
        WriteImpl(m_key_scratch, m_value_scratch);
120
3.64k
    }
void CDBBatch::Write<std::pair<unsigned char, uint256>, CDiskBlockIndex>(std::pair<unsigned char, uint256> const&, CDiskBlockIndex const&)
Line
Count
Source
115
117k
    {
116
117k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
117k
        m_key_scratch << key;
118
117k
        m_value_scratch << value;
119
117k
        WriteImpl(m_key_scratch, m_value_scratch);
120
117k
    }
void CDBBatch::Write<std::pair<unsigned char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, unsigned char>(std::pair<unsigned char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>> const&, unsigned char const&)
Line
Count
Source
115
8
    {
116
8
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
8
        m_key_scratch << key;
118
8
        m_value_scratch << value;
119
8
        WriteImpl(m_key_scratch, m_value_scratch);
120
8
    }
void CDBBatch::Write<unsigned char, std::vector<uint256, std::allocator<uint256>>>(unsigned char const&, std::vector<uint256, std::allocator<uint256>> const&)
Line
Count
Source
115
3.92k
    {
116
3.92k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
3.92k
        m_key_scratch << key;
118
3.92k
        m_value_scratch << value;
119
3.92k
        WriteImpl(m_key_scratch, m_value_scratch);
120
3.92k
    }
txdb.cpp:void CDBBatch::Write<(anonymous namespace)::CoinEntry, Coin>((anonymous namespace)::CoinEntry const&, Coin const&)
Line
Count
Source
115
290k
    {
116
290k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
117
290k
        m_key_scratch << key;
118
290k
        m_value_scratch << value;
119
290k
        WriteImpl(m_key_scratch, m_value_scratch);
120
290k
    }
121
122
    template <typename K>
123
    void Erase(const K& key)
124
41.0k
    {
125
41.0k
        ScopedDataStreamUsage scoped_key{m_key_scratch};
126
41.0k
        m_key_scratch << key;
127
41.0k
        EraseImpl(m_key_scratch);
128
41.0k
    }
void CDBBatch::Erase<unsigned char>(unsigned char const&)
Line
Count
Source
124
7.87k
    {
125
7.87k
        ScopedDataStreamUsage scoped_key{m_key_scratch};
126
7.87k
        m_key_scratch << key;
127
7.87k
        EraseImpl(m_key_scratch);
128
7.87k
    }
void CDBBatch::Erase<txindex::DBKey>(txindex::DBKey const&)
Line
Count
Source
124
2
    {
125
2
        ScopedDataStreamUsage scoped_key{m_key_scratch};
126
2
        m_key_scratch << key;
127
2
        EraseImpl(m_key_scratch);
128
2
    }
void CDBBatch::Erase<DBKey>(DBKey const&)
Line
Count
Source
124
6
    {
125
6
        ScopedDataStreamUsage scoped_key{m_key_scratch};
126
6
        m_key_scratch << key;
127
6
        EraseImpl(m_key_scratch);
128
6
    }
txdb.cpp:void CDBBatch::Erase<(anonymous namespace)::CoinEntry>((anonymous namespace)::CoinEntry const&)
Line
Count
Source
124
33.2k
    {
125
33.2k
        ScopedDataStreamUsage scoped_key{m_key_scratch};
126
33.2k
        m_key_scratch << key;
127
33.2k
        EraseImpl(m_key_scratch);
128
33.2k
    }
129
130
    size_t ApproximateSize() const;
131
};
132
133
class CDBIterator
134
{
135
public:
136
    struct IteratorImpl;
137
138
private:
139
    const CDBWrapper &parent;
140
    const std::unique_ptr<IteratorImpl> m_impl_iter;
141
    DataStream m_scratch{};
142
143
    void SeekImpl(std::span<const std::byte> key);
144
    std::span<const std::byte> GetKeyImpl() const;
145
    std::span<const std::byte> GetValueImpl() const;
146
147
public:
148
149
    /**
150
     * @param[in] _parent          Parent CDBWrapper instance.
151
     * @param[in] _piter           The original leveldb iterator.
152
     */
153
    CDBIterator(const CDBWrapper& _parent, std::unique_ptr<IteratorImpl> _piter);
154
    ~CDBIterator();
155
156
    bool Valid() const;
157
158
    void SeekToFirst();
159
160
4.89k
    template<typename K> void Seek(const K& key) {
161
4.89k
        ScopedDataStreamUsage scoped_scratch{m_scratch};
162
4.89k
        m_scratch << key;
163
4.89k
        SeekImpl(m_scratch);
164
4.89k
    }
void CDBIterator::Seek<unsigned char>(unsigned char const&)
Line
Count
Source
160
1.26k
    template<typename K> void Seek(const K& key) {
161
1.26k
        ScopedDataStreamUsage scoped_scratch{m_scratch};
162
1.26k
        m_scratch << key;
163
1.26k
        SeekImpl(m_scratch);
164
1.26k
    }
void CDBIterator::Seek<dbwrapper_tests::StringContentsSerializer>(dbwrapper_tests::StringContentsSerializer const&)
Line
Count
Source
160
2
    template<typename K> void Seek(const K& key) {
161
2
        ScopedDataStreamUsage scoped_scratch{m_scratch};
162
2
        m_scratch << key;
163
2
        SeekImpl(m_scratch);
164
2
    }
void CDBIterator::Seek<txindex::DBKey>(txindex::DBKey const&)
Line
Count
Source
160
265
    template<typename K> void Seek(const K& key) {
161
265
        ScopedDataStreamUsage scoped_scratch{m_scratch};
162
265
        m_scratch << key;
163
265
        SeekImpl(m_scratch);
164
265
    }
void CDBIterator::Seek<index_util::DBHeightKey>(index_util::DBHeightKey const&)
Line
Count
Source
160
681
    template<typename K> void Seek(const K& key) {
161
681
        ScopedDataStreamUsage scoped_scratch{m_scratch};
162
681
        m_scratch << key;
163
681
        SeekImpl(m_scratch);
164
681
    }
void CDBIterator::Seek<std::pair<unsigned char, unsigned long>>(std::pair<unsigned char, unsigned long> const&)
Line
Count
Source
160
36
    template<typename K> void Seek(const K& key) {
161
36
        ScopedDataStreamUsage scoped_scratch{m_scratch};
162
36
        m_scratch << key;
163
36
        SeekImpl(m_scratch);
164
36
    }
void CDBIterator::Seek<std::pair<unsigned char, uint256>>(std::pair<unsigned char, uint256> const&)
Line
Count
Source
160
2.64k
    template<typename K> void Seek(const K& key) {
161
2.64k
        ScopedDataStreamUsage scoped_scratch{m_scratch};
162
2.64k
        m_scratch << key;
163
2.64k
        SeekImpl(m_scratch);
164
2.64k
    }
165
166
    void Next();
167
168
429k
    template<typename K> bool GetKey(K& key) {
169
429k
        try {
170
429k
            SpanReader ssKey{GetKeyImpl()};
171
429k
            ssKey >> key;
172
429k
        } catch (const std::exception&) {
173
821
            return false;
174
821
        }
175
429k
        return true;
176
429k
    }
bool CDBIterator::GetKey<unsigned short>(unsigned short&)
Line
Count
Source
168
2
    template<typename K> bool GetKey(K& key) {
169
2
        try {
170
2
            SpanReader ssKey{GetKeyImpl()};
171
2
            ssKey >> key;
172
2
        } catch (const std::exception&) {
173
2
            return false;
174
2
        }
175
0
        return true;
176
2
    }
bool CDBIterator::GetKey<unsigned char>(unsigned char&)
Line
Count
Source
168
390
    template<typename K> bool GetKey(K& key) {
169
390
        try {
170
390
            SpanReader ssKey{GetKeyImpl()};
171
390
            ssKey >> key;
172
390
        } catch (const std::exception&) {
173
0
            return false;
174
0
        }
175
390
        return true;
176
390
    }
bool CDBIterator::GetKey<dbwrapper_tests::StringContentsSerializer>(dbwrapper_tests::StringContentsSerializer&)
Line
Count
Source
168
150
    template<typename K> bool GetKey(K& key) {
169
150
        try {
170
150
            SpanReader ssKey{GetKeyImpl()};
171
150
            ssKey >> key;
172
150
        } catch (const std::exception&) {
173
0
            return false;
174
0
        }
175
150
        return true;
176
150
    }
bool CDBIterator::GetKey<txindex::DBKey>(txindex::DBKey&)
Line
Count
Source
168
325
    template<typename K> bool GetKey(K& key) {
169
325
        try {
170
325
            SpanReader ssKey{GetKeyImpl()};
171
325
            ssKey >> key;
172
325
        } catch (const std::exception&) {
173
0
            return false;
174
0
        }
175
325
        return true;
176
325
    }
bool CDBIterator::GetKey<index_util::DBHeightKey>(index_util::DBHeightKey&)
Line
Count
Source
168
3.09k
    template<typename K> bool GetKey(K& key) {
169
3.09k
        try {
170
3.09k
            SpanReader ssKey{GetKeyImpl()};
171
3.09k
            ssKey >> key;
172
3.09k
        } catch (const std::exception&) {
173
0
            return false;
174
0
        }
175
3.09k
        return true;
176
3.09k
    }
bool CDBIterator::GetKey<DBKey>(DBKey&)
Line
Count
Source
168
27
    template<typename K> bool GetKey(K& key) {
169
27
        try {
170
27
            SpanReader ssKey{GetKeyImpl()};
171
27
            ssKey >> key;
172
27
        } catch (const std::exception&) {
173
0
            return false;
174
0
        }
175
27
        return true;
176
27
    }
bool CDBIterator::GetKey<std::pair<unsigned char, uint256>>(std::pair<unsigned char, uint256>&)
Line
Count
Source
168
152k
    template<typename K> bool GetKey(K& key) {
169
152k
        try {
170
152k
            SpanReader ssKey{GetKeyImpl()};
171
152k
            ssKey >> key;
172
152k
        } catch (const std::exception&) {
173
819
            return false;
174
819
        }
175
151k
        return true;
176
152k
    }
txdb.cpp:bool CDBIterator::GetKey<(anonymous namespace)::CoinEntry>((anonymous namespace)::CoinEntry&)
Line
Count
Source
168
273k
    template<typename K> bool GetKey(K& key) {
169
273k
        try {
170
273k
            SpanReader ssKey{GetKeyImpl()};
171
273k
            ssKey >> key;
172
273k
        } catch (const std::exception&) {
173
0
            return false;
174
0
        }
175
273k
        return true;
176
273k
    }
177
178
428k
    template<typename V> bool GetValue(V& value) {
179
428k
        try {
180
428k
            ScopedDataStreamUsage scoped_scratch{m_scratch};
181
428k
            m_scratch.write(GetValueImpl());
182
428k
            dbwrapper_private::GetObfuscation(parent)(m_scratch);
183
428k
            m_scratch >> value;
184
428k
        } catch (const std::exception&) {
185
2
            return false;
186
2
        }
187
428k
        return true;
188
428k
    }
bool CDBIterator::GetValue<std::pair<uint256, unsigned char>>(std::pair<uint256, unsigned char>&)
Line
Count
Source
178
2
    template<typename V> bool GetValue(V& value) {
179
2
        try {
180
2
            ScopedDataStreamUsage scoped_scratch{m_scratch};
181
2
            m_scratch.write(GetValueImpl());
182
2
            dbwrapper_private::GetObfuscation(parent)(m_scratch);
183
2
            m_scratch >> value;
184
2
        } catch (const std::exception&) {
185
2
            return false;
186
2
        }
187
0
        return true;
188
2
    }
bool CDBIterator::GetValue<uint256>(uint256&)
Line
Count
Source
178
8
    template<typename V> bool GetValue(V& value) {
179
8
        try {
180
8
            ScopedDataStreamUsage scoped_scratch{m_scratch};
181
8
            m_scratch.write(GetValueImpl());
182
8
            dbwrapper_private::GetObfuscation(parent)(m_scratch);
183
8
            m_scratch >> value;
184
8
        } catch (const std::exception&) {
185
0
            return false;
186
0
        }
187
8
        return true;
188
8
    }
bool CDBIterator::GetValue<unsigned int>(unsigned int&)
Line
Count
Source
178
342
    template<typename V> bool GetValue(V& value) {
179
342
        try {
180
342
            ScopedDataStreamUsage scoped_scratch{m_scratch};
181
342
            m_scratch.write(GetValueImpl());
182
342
            dbwrapper_private::GetObfuscation(parent)(m_scratch);
183
342
            m_scratch >> value;
184
342
        } catch (const std::exception&) {
185
0
            return false;
186
0
        }
187
342
        return true;
188
342
    }
blockfilterindex.cpp:bool CDBIterator::GetValue<std::pair<uint256, (anonymous namespace)::DBVal>>(std::pair<uint256, (anonymous namespace)::DBVal>&)
Line
Count
Source
178
2.97k
    template<typename V> bool GetValue(V& value) {
179
2.97k
        try {
180
2.97k
            ScopedDataStreamUsage scoped_scratch{m_scratch};
181
2.97k
            m_scratch.write(GetValueImpl());
182
2.97k
            dbwrapper_private::GetObfuscation(parent)(m_scratch);
183
2.97k
            m_scratch >> value;
184
2.97k
        } catch (const std::exception&) {
185
0
            return false;
186
0
        }
187
2.97k
        return true;
188
2.97k
    }
coinstatsindex.cpp:bool CDBIterator::GetValue<std::pair<uint256, (anonymous namespace)::DBVal>>(std::pair<uint256, (anonymous namespace)::DBVal>&)
Line
Count
Source
178
121
    template<typename V> bool GetValue(V& value) {
179
121
        try {
180
121
            ScopedDataStreamUsage scoped_scratch{m_scratch};
181
121
            m_scratch.write(GetValueImpl());
182
121
            dbwrapper_private::GetObfuscation(parent)(m_scratch);
183
121
            m_scratch >> value;
184
121
        } catch (const std::exception&) {
185
0
            return false;
186
0
        }
187
121
        return true;
188
121
    }
bool CDBIterator::GetValue<CDiskBlockIndex>(CDiskBlockIndex&)
Line
Count
Source
178
151k
    template<typename V> bool GetValue(V& value) {
179
151k
        try {
180
151k
            ScopedDataStreamUsage scoped_scratch{m_scratch};
181
151k
            m_scratch.write(GetValueImpl());
182
151k
            dbwrapper_private::GetObfuscation(parent)(m_scratch);
183
151k
            m_scratch >> value;
184
151k
        } catch (const std::exception&) {
185
0
            return false;
186
0
        }
187
151k
        return true;
188
151k
    }
bool CDBIterator::GetValue<Coin>(Coin&)
Line
Count
Source
178
273k
    template<typename V> bool GetValue(V& value) {
179
273k
        try {
180
273k
            ScopedDataStreamUsage scoped_scratch{m_scratch};
181
273k
            m_scratch.write(GetValueImpl());
182
273k
            dbwrapper_private::GetObfuscation(parent)(m_scratch);
183
273k
            m_scratch >> value;
184
273k
        } catch (const std::exception&) {
185
0
            return false;
186
0
        }
187
273k
        return true;
188
273k
    }
189
};
190
191
struct LevelDBContext;
192
193
class CDBWrapper
194
{
195
    friend const Obfuscation& dbwrapper_private::GetObfuscation(const CDBWrapper&);
196
private:
197
    //! holds all leveldb-specific fields of this class
198
    util::NotNullUniquePtr<LevelDBContext> m_db_context;
199
200
    //! the name of this database
201
    std::string m_name;
202
203
    //! optional XOR-obfuscation of the database
204
    Obfuscation m_obfuscation;
205
206
    //! obfuscation key storage key, null-prefixed to avoid collisions
207
    inline static const std::string OBFUSCATION_KEY{"\000obfuscate_key", 14}; // explicit size to avoid truncation at leading \0
208
209
    std::optional<std::string> ReadImpl(std::span<const std::byte> key) const;
210
    bool ExistsImpl(std::span<const std::byte> key) const;
211
    size_t EstimateSizeImpl(std::span<const std::byte> key1, std::span<const std::byte> key2) const;
212
11.0M
    auto& DBContext() const LIFETIMEBOUND { return *m_db_context; }
213
214
public:
215
    CDBWrapper(const DBParams& params);
216
    ~CDBWrapper();
217
218
    CDBWrapper(const CDBWrapper&) = delete;
219
    CDBWrapper& operator=(const CDBWrapper&) = delete;
220
221
    struct ReadFailure {
222
        enum class Code {
223
            DeserializationError,   //!< Key exists but value could not be deserialized.
224
            DatabaseError,          //!< Unexpected internal DB error.
225
        };
226
227
        Code status;
228
        std::string err_msg;
229
    };
230
231
    using ReadStatus = util::Expected<bool, ReadFailure>;
232
233
    /**
234
     * Read and deserialize a value from the database, with explicit error discrimination.
235
     *
236
     * Unlike Read(), this method distinguishes between a missing key, a deserialization
237
     * failure (DeserializationError), and an internal DB error (DatabaseError),
238
     * enabling callers to treat data corruption differently from an absent entry.
239
     *
240
     * @note Callers are expected to provide well-formed keys; key serialization
241
     *       is the only operation that may throw.
242
     *
243
     * @param[in]  key    The key to look up.
244
     * @param[out] value  Populated with the deserialized value when the returned
245
     *                    Expected holds true; indeterminate otherwise.
246
     * @return On success, true if the key was found (value populated) or false if
247
     *         the key was absent. On failure, a ReadFailure describing the error.
248
     */
249
    template <typename K, typename V>
250
    [[nodiscard]] ReadStatus TryRead(const K& key, V& value) const
251
5.44M
    {
252
5.44M
        DataStream ssKey{};
253
5.44M
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
5.44M
        ssKey << key;
257
258
5.44M
        std::optional<std::string> strValue;
259
5.44M
        try {
260
5.44M
            strValue = ReadImpl(ssKey);
261
5.44M
            if (!strValue) {
262
5.33M
                return false; // not found
263
5.33M
            }
264
5.44M
        } catch (const std::exception& e) {
265
3
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
3
        }
267
268
111k
        try {
269
111k
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
111k
            m_obfuscation(ssValue);
271
111k
            SpanReader{ssValue} >> value;
272
111k
        } catch (const std::exception& e) {
273
4
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
4
        }
275
276
111k
        return true;
277
111k
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, uint256>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, uint256&) const
Line
Count
Source
251
8
    {
252
8
        DataStream ssKey{};
253
8
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
8
        ssKey << key;
257
258
8
        std::optional<std::string> strValue;
259
8
        try {
260
8
            strValue = ReadImpl(ssKey);
261
8
            if (!strValue) {
262
0
                return false; // not found
263
0
            }
264
8
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
8
        try {
269
8
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
8
            m_obfuscation(ssValue);
271
8
            SpanReader{ssValue} >> value;
272
8
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
8
        return true;
277
8
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<unsigned char, unsigned int>(unsigned char const&, unsigned int&) const
Line
Count
Source
251
2
    {
252
2
        DataStream ssKey{};
253
2
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
2
        ssKey << key;
257
258
2
        std::optional<std::string> strValue;
259
2
        try {
260
2
            strValue = ReadImpl(ssKey);
261
2
            if (!strValue) {
262
0
                return false; // not found
263
0
            }
264
2
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
2
        try {
269
2
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
2
            m_obfuscation(ssValue);
271
2
            SpanReader{ssValue} >> value;
272
2
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
2
        return true;
277
2
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<unsigned char, bool>(unsigned char const&, bool&) const
Line
Count
Source
251
2
    {
252
2
        DataStream ssKey{};
253
2
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
2
        ssKey << key;
257
258
2
        std::optional<std::string> strValue;
259
2
        try {
260
2
            strValue = ReadImpl(ssKey);
261
2
            if (!strValue) {
262
0
                return false; // not found
263
0
            }
264
2
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
2
        try {
269
2
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
2
            m_obfuscation(ssValue);
271
2
            SpanReader{ssValue} >> value;
272
2
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
2
        return true;
277
2
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, bool>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, bool&) const
Line
Count
Source
251
2
    {
252
2
        DataStream ssKey{};
253
2
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
2
        ssKey << key;
257
258
2
        std::optional<std::string> strValue;
259
2
        try {
260
2
            strValue = ReadImpl(ssKey);
261
2
            if (!strValue) {
262
0
                return false; // not found
263
0
            }
264
2
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
2
        try {
269
2
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
2
            m_obfuscation(ssValue);
271
2
            SpanReader{ssValue} >> value;
272
2
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
2
        return true;
277
2
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<unsigned char, uint256>(unsigned char const&, uint256&) const
Line
Count
Source
251
8.23k
    {
252
8.23k
        DataStream ssKey{};
253
8.23k
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
8.23k
        ssKey << key;
257
258
8.23k
        std::optional<std::string> strValue;
259
8.23k
        try {
260
8.23k
            strValue = ReadImpl(ssKey);
261
8.23k
            if (!strValue) {
262
1.88k
                return false; // not found
263
1.88k
            }
264
8.23k
        } catch (const std::exception& e) {
265
2
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
2
        }
267
268
6.34k
        try {
269
6.34k
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
6.34k
            m_obfuscation(ssValue);
271
6.34k
            SpanReader{ssValue} >> value;
272
6.34k
        } catch (const std::exception& e) {
273
4
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
4
        }
275
276
6.33k
        return true;
277
6.34k
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::pair<unsigned long, unsigned long>>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::pair<unsigned long, unsigned long>&) const
Line
Count
Source
251
49
    {
252
49
        DataStream ssKey{};
253
49
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
49
        ssKey << key;
257
258
49
        std::optional<std::string> strValue;
259
49
        try {
260
49
            strValue = ReadImpl(ssKey);
261
49
            if (!strValue) {
262
22
                return false; // not found
263
22
            }
264
49
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
27
        try {
269
27
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
27
            m_obfuscation(ssValue);
271
27
            SpanReader{ssValue} >> value;
272
27
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
27
        return true;
277
27
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<unsigned char, CBlockLocator>(unsigned char const&, CBlockLocator&) const
Line
Count
Source
251
165
    {
252
165
        DataStream ssKey{};
253
165
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
165
        ssKey << key;
257
258
165
        std::optional<std::string> strValue;
259
165
        try {
260
165
            strValue = ReadImpl(ssKey);
261
165
            if (!strValue) {
262
83
                return false; // not found
263
83
            }
264
165
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
82
        try {
269
82
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
82
            m_obfuscation(ssValue);
271
82
            SpanReader{ssValue} >> value;
272
82
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
82
        return true;
277
82
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, Obfuscation>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, Obfuscation&) const
Line
Count
Source
251
3.04k
    {
252
3.04k
        DataStream ssKey{};
253
3.04k
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
3.04k
        ssKey << key;
257
258
3.04k
        std::optional<std::string> strValue;
259
3.04k
        try {
260
3.04k
            strValue = ReadImpl(ssKey);
261
3.04k
            if (!strValue) {
262
2.11k
                return false; // not found
263
2.11k
            }
264
3.04k
        } catch (const std::exception& e) {
265
1
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
1
        }
267
268
931
        try {
269
931
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
931
            m_obfuscation(ssValue);
271
931
            SpanReader{ssValue} >> value;
272
931
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
931
        return true;
277
931
    }
blockfilterindex.cpp:util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<index_util::DBHashKey, (anonymous namespace)::DBVal>(index_util::DBHashKey const&, (anonymous namespace)::DBVal&) const
Line
Count
Source
251
33
    {
252
33
        DataStream ssKey{};
253
33
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
33
        ssKey << key;
257
258
33
        std::optional<std::string> strValue;
259
33
        try {
260
33
            strValue = ReadImpl(ssKey);
261
33
            if (!strValue) {
262
0
                return false; // not found
263
0
            }
264
33
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
33
        try {
269
33
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
33
            m_obfuscation(ssValue);
271
33
            SpanReader{ssValue} >> value;
272
33
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
33
        return true;
277
33
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<unsigned char, FlatFilePos>(unsigned char const&, FlatFilePos&) const
Line
Count
Source
251
53
    {
252
53
        DataStream ssKey{};
253
53
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
53
        ssKey << key;
257
258
53
        std::optional<std::string> strValue;
259
53
        try {
260
53
            strValue = ReadImpl(ssKey);
261
53
            if (!strValue) {
262
24
                return false; // not found
263
24
            }
264
53
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
29
        try {
269
29
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
29
            m_obfuscation(ssValue);
271
29
            SpanReader{ssValue} >> value;
272
29
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
29
        return true;
277
29
    }
blockfilterindex.cpp:util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<index_util::DBHeightKey, std::pair<uint256, (anonymous namespace)::DBVal>>(index_util::DBHeightKey const&, std::pair<uint256, (anonymous namespace)::DBVal>&) const
Line
Count
Source
251
1.33k
    {
252
1.33k
        DataStream ssKey{};
253
1.33k
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
1.33k
        ssKey << key;
257
258
1.33k
        std::optional<std::string> strValue;
259
1.33k
        try {
260
1.33k
            strValue = ReadImpl(ssKey);
261
1.33k
            if (!strValue) {
262
304
                return false; // not found
263
304
            }
264
1.33k
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
1.02k
        try {
269
1.02k
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
1.02k
            m_obfuscation(ssValue);
271
1.02k
            SpanReader{ssValue} >> value;
272
1.02k
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
1.02k
        return true;
277
1.02k
    }
coinstatsindex.cpp:util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<index_util::DBHashKey, (anonymous namespace)::DBVal>(index_util::DBHashKey const&, (anonymous namespace)::DBVal&) const
Line
Count
Source
251
2
    {
252
2
        DataStream ssKey{};
253
2
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
2
        ssKey << key;
257
258
2
        std::optional<std::string> strValue;
259
2
        try {
260
2
            strValue = ReadImpl(ssKey);
261
2
            if (!strValue) {
262
0
                return false; // not found
263
0
            }
264
2
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
2
        try {
269
2
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
2
            m_obfuscation(ssValue);
271
2
            SpanReader{ssValue} >> value;
272
2
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
2
        return true;
277
2
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<unsigned char, MuHash3072>(unsigned char const&, MuHash3072&) const
Line
Count
Source
251
52
    {
252
52
        DataStream ssKey{};
253
52
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
52
        ssKey << key;
257
258
52
        std::optional<std::string> strValue;
259
52
        try {
260
52
            strValue = ReadImpl(ssKey);
261
52
            if (!strValue) {
262
21
                return false; // not found
263
21
            }
264
52
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
31
        try {
269
31
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
31
            m_obfuscation(ssValue);
271
31
            SpanReader{ssValue} >> value;
272
31
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
31
        return true;
277
31
    }
coinstatsindex.cpp:util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<index_util::DBHeightKey, std::pair<uint256, (anonymous namespace)::DBVal>>(index_util::DBHeightKey const&, std::pair<uint256, (anonymous namespace)::DBVal>&) const
Line
Count
Source
251
222
    {
252
222
        DataStream ssKey{};
253
222
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
222
        ssKey << key;
257
258
222
        std::optional<std::string> strValue;
259
222
        try {
260
222
            strValue = ReadImpl(ssKey);
261
222
            if (!strValue) {
262
1
                return false; // not found
263
1
            }
264
222
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
221
        try {
269
221
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
221
            m_obfuscation(ssValue);
271
221
            SpanReader{ssValue} >> value;
272
221
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
221
        return true;
277
221
    }
Unexecuted instantiation: coinstatsindex.cpp:util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<index_util::DBHashKey, std::pair<uint256, (anonymous namespace)::DBVal>>(index_util::DBHashKey const&, std::pair<uint256, (anonymous namespace)::DBVal>&) const
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, CBlockLocator>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, CBlockLocator&) const
Line
Count
Source
251
52
    {
252
52
        DataStream ssKey{};
253
52
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
52
        ssKey << key;
257
258
52
        std::optional<std::string> strValue;
259
52
        try {
260
52
            strValue = ReadImpl(ssKey);
261
52
            if (!strValue) {
262
27
                return false; // not found
263
27
            }
264
52
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
25
        try {
269
25
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
25
            m_obfuscation(ssValue);
271
25
            SpanReader{ssValue} >> value;
272
25
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
25
        return true;
277
25
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, unsigned int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, unsigned int&) const
Line
Count
Source
251
4.22k
    {
252
4.22k
        DataStream ssKey{};
253
4.22k
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
4.22k
        ssKey << key;
257
258
4.22k
        std::optional<std::string> strValue;
259
4.22k
        try {
260
4.22k
            strValue = ReadImpl(ssKey);
261
4.22k
            if (!strValue) {
262
20
                return false; // not found
263
20
            }
264
4.22k
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
4.20k
        try {
269
4.20k
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
4.20k
            m_obfuscation(ssValue);
271
4.20k
            SpanReader{ssValue} >> value;
272
4.20k
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
4.20k
        return true;
277
4.20k
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<txindex::BlockSeqKey, uint256>(txindex::BlockSeqKey const&, uint256&) const
Line
Count
Source
251
156
    {
252
156
        DataStream ssKey{};
253
156
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
156
        ssKey << key;
257
258
156
        std::optional<std::string> strValue;
259
156
        try {
260
156
            strValue = ReadImpl(ssKey);
261
156
            if (!strValue) {
262
0
                return false; // not found
263
0
            }
264
156
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
156
        try {
269
156
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
156
            m_obfuscation(ssValue);
271
156
            SpanReader{ssValue} >> value;
272
156
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
156
        return true;
277
156
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<std::pair<unsigned char, uint256>, CDiskTxPos>(std::pair<unsigned char, uint256> const&, CDiskTxPos&) const
Line
Count
Source
251
3
    {
252
3
        DataStream ssKey{};
253
3
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
3
        ssKey << key;
257
258
3
        std::optional<std::string> strValue;
259
3
        try {
260
3
            strValue = ReadImpl(ssKey);
261
3
            if (!strValue) {
262
0
                return false; // not found
263
0
            }
264
3
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
3
        try {
269
3
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
3
            m_obfuscation(ssValue);
271
3
            SpanReader{ssValue} >> value;
272
3
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
3
        return true;
277
3
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<char [12], std::pair<unsigned long, unsigned long>>(char const (&) [12], std::pair<unsigned long, unsigned long>&) const
Line
Count
Source
251
28
    {
252
28
        DataStream ssKey{};
253
28
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
28
        ssKey << key;
257
258
28
        std::optional<std::string> strValue;
259
28
        try {
260
28
            strValue = ReadImpl(ssKey);
261
28
            if (!strValue) {
262
9
                return false; // not found
263
9
            }
264
28
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
19
        try {
269
19
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
19
            m_obfuscation(ssValue);
271
19
            SpanReader{ssValue} >> value;
272
19
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
19
        return true;
277
19
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<std::pair<unsigned char, int>, kernel::CBlockFileInfo>(std::pair<unsigned char, int> const&, kernel::CBlockFileInfo&) const
Line
Count
Source
251
2.64k
    {
252
2.64k
        DataStream ssKey{};
253
2.64k
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
2.64k
        ssKey << key;
257
258
2.64k
        std::optional<std::string> strValue;
259
2.64k
        try {
260
2.64k
            strValue = ReadImpl(ssKey);
261
2.64k
            if (!strValue) {
262
1.80k
                return false; // not found
263
1.80k
            }
264
2.64k
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
834
        try {
269
834
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
834
            m_obfuscation(ssValue);
271
834
            SpanReader{ssValue} >> value;
272
834
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
834
        return true;
277
834
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<unsigned char, int>(unsigned char const&, int&) const
Line
Count
Source
251
1.31k
    {
252
1.31k
        DataStream ssKey{};
253
1.31k
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
1.31k
        ssKey << key;
257
258
1.31k
        std::optional<std::string> strValue;
259
1.31k
        try {
260
1.31k
            strValue = ReadImpl(ssKey);
261
1.31k
            if (!strValue) {
262
495
                return false; // not found
263
495
            }
264
1.31k
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
817
        try {
269
817
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
817
            m_obfuscation(ssValue);
271
817
            SpanReader{ssValue} >> value;
272
817
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
817
        return true;
277
817
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<std::pair<unsigned char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, unsigned char>(std::pair<unsigned char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>> const&, unsigned char&) const
Line
Count
Source
251
1.31k
    {
252
1.31k
        DataStream ssKey{};
253
1.31k
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
1.31k
        ssKey << key;
257
258
1.31k
        std::optional<std::string> strValue;
259
1.31k
        try {
260
1.31k
            strValue = ReadImpl(ssKey);
261
1.31k
            if (!strValue) {
262
1.30k
                return false; // not found
263
1.30k
            }
264
1.31k
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
2
        try {
269
2
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
2
            m_obfuscation(ssValue);
271
2
            SpanReader{ssValue} >> value;
272
2
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
2
        return true;
277
2
    }
txdb.cpp:util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<(anonymous namespace)::CoinEntry, Coin>((anonymous namespace)::CoinEntry const&, Coin&) const
Line
Count
Source
251
5.42M
    {
252
5.42M
        DataStream ssKey{};
253
5.42M
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
5.42M
        ssKey << key;
257
258
5.42M
        std::optional<std::string> strValue;
259
5.42M
        try {
260
5.42M
            strValue = ReadImpl(ssKey);
261
5.42M
            if (!strValue) {
262
5.32M
                return false; // not found
263
5.32M
            }
264
5.42M
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
96.4k
        try {
269
96.4k
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
96.4k
            m_obfuscation(ssValue);
271
96.4k
            SpanReader{ssValue} >> value;
272
96.4k
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
96.4k
        return true;
277
96.4k
    }
util::Expected<bool, CDBWrapper::ReadFailure> CDBWrapper::TryRead<unsigned char, std::vector<uint256, std::allocator<uint256>>>(unsigned char const&, std::vector<uint256, std::allocator<uint256>>&) const
Line
Count
Source
251
1.69k
    {
252
1.69k
        DataStream ssKey{};
253
1.69k
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
254
        // Key serialization is the only operation that may throw.
255
        // Callers are expected to provide well-formed keys.
256
1.69k
        ssKey << key;
257
258
1.69k
        std::optional<std::string> strValue;
259
1.69k
        try {
260
1.69k
            strValue = ReadImpl(ssKey);
261
1.69k
            if (!strValue) {
262
1.69k
                return false; // not found
263
1.69k
            }
264
1.69k
        } catch (const std::exception& e) {
265
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
266
0
        }
267
268
0
        try {
269
0
            std::span ssValue{MakeWritableByteSpan(*strValue)};
270
0
            m_obfuscation(ssValue);
271
0
            SpanReader{ssValue} >> value;
272
0
        } catch (const std::exception& e) {
273
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
274
0
        }
275
276
0
        return true;
277
0
    }
278
279
    /**
280
     * Wrapper around TryRead() that preserves the original Read() semantics:
281
     * returns true on success, false if the key is absent or deserialization
282
     * fails, and throws dbwrapper_error on an internal DB error.
283
     *
284
     * Prefer TryRead() when the caller needs to distinguish between a missing
285
     * key and a corrupt value.
286
     */
287
    template <typename K, typename V>
288
    bool Read(const K& key, V& value) const
289
24.6k
    {
290
24.6k
        const ReadStatus res = TryRead(key,value);
291
24.6k
        if (res.has_value()) return res.value();
292
4
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
2
            case ReadFailure::Code::DeserializationError: return false;
294
2
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
4
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
4
    }
bool CDBWrapper::Read<unsigned char, uint256>(unsigned char const&, uint256&) const
Line
Count
Source
289
8.22k
    {
290
8.22k
        const ReadStatus res = TryRead(key,value);
291
8.22k
        if (res.has_value()) return res.value();
292
3
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
2
            case ReadFailure::Code::DeserializationError: return false;
294
1
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
3
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
3
    }
bool CDBWrapper::Read<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, uint256>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, uint256&) const
Line
Count
Source
289
8
    {
290
8
        const ReadStatus res = TryRead(key,value);
291
8
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<unsigned char, unsigned int>(unsigned char const&, unsigned int&) const
Line
Count
Source
289
2
    {
290
2
        const ReadStatus res = TryRead(key,value);
291
2
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<unsigned char, bool>(unsigned char const&, bool&) const
Line
Count
Source
289
2
    {
290
2
        const ReadStatus res = TryRead(key,value);
291
2
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, bool>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, bool&) const
Line
Count
Source
289
2
    {
290
2
        const ReadStatus res = TryRead(key,value);
291
2
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::pair<unsigned long, unsigned long>>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::pair<unsigned long, unsigned long>&) const
Line
Count
Source
289
49
    {
290
49
        const ReadStatus res = TryRead(key,value);
291
49
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<unsigned char, CBlockLocator>(unsigned char const&, CBlockLocator&) const
Line
Count
Source
289
165
    {
290
165
        const ReadStatus res = TryRead(key,value);
291
165
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, Obfuscation>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, Obfuscation&) const
Line
Count
Source
289
3.04k
    {
290
3.04k
        const ReadStatus res = TryRead(key,value);
291
3.04k
        if (res.has_value()) return res.value();
292
1
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
1
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
1
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
1
    }
blockfilterindex.cpp:bool CDBWrapper::Read<index_util::DBHashKey, (anonymous namespace)::DBVal>(index_util::DBHashKey const&, (anonymous namespace)::DBVal&) const
Line
Count
Source
289
33
    {
290
33
        const ReadStatus res = TryRead(key,value);
291
33
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<unsigned char, FlatFilePos>(unsigned char const&, FlatFilePos&) const
Line
Count
Source
289
53
    {
290
53
        const ReadStatus res = TryRead(key,value);
291
53
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
blockfilterindex.cpp:bool CDBWrapper::Read<index_util::DBHeightKey, std::pair<uint256, (anonymous namespace)::DBVal>>(index_util::DBHeightKey const&, std::pair<uint256, (anonymous namespace)::DBVal>&) const
Line
Count
Source
289
1.33k
    {
290
1.33k
        const ReadStatus res = TryRead(key,value);
291
1.33k
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
coinstatsindex.cpp:bool CDBWrapper::Read<index_util::DBHashKey, (anonymous namespace)::DBVal>(index_util::DBHashKey const&, (anonymous namespace)::DBVal&) const
Line
Count
Source
289
2
    {
290
2
        const ReadStatus res = TryRead(key,value);
291
2
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<unsigned char, MuHash3072>(unsigned char const&, MuHash3072&) const
Line
Count
Source
289
52
    {
290
52
        const ReadStatus res = TryRead(key,value);
291
52
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
coinstatsindex.cpp:bool CDBWrapper::Read<index_util::DBHeightKey, std::pair<uint256, (anonymous namespace)::DBVal>>(index_util::DBHeightKey const&, std::pair<uint256, (anonymous namespace)::DBVal>&) const
Line
Count
Source
289
222
    {
290
222
        const ReadStatus res = TryRead(key,value);
291
222
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
Unexecuted instantiation: coinstatsindex.cpp:bool CDBWrapper::Read<index_util::DBHashKey, std::pair<uint256, (anonymous namespace)::DBVal>>(index_util::DBHashKey const&, std::pair<uint256, (anonymous namespace)::DBVal>&) const
bool CDBWrapper::Read<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, CBlockLocator>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, CBlockLocator&) const
Line
Count
Source
289
52
    {
290
52
        const ReadStatus res = TryRead(key,value);
291
52
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, unsigned int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, unsigned int&) const
Line
Count
Source
289
4.22k
    {
290
4.22k
        const ReadStatus res = TryRead(key,value);
291
4.22k
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<txindex::BlockSeqKey, uint256>(txindex::BlockSeqKey const&, uint256&) const
Line
Count
Source
289
156
    {
290
156
        const ReadStatus res = TryRead(key,value);
291
156
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<std::pair<unsigned char, uint256>, CDiskTxPos>(std::pair<unsigned char, uint256> const&, CDiskTxPos&) const
Line
Count
Source
289
3
    {
290
3
        const ReadStatus res = TryRead(key,value);
291
3
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<char [12], std::pair<unsigned long, unsigned long>>(char const (&) [12], std::pair<unsigned long, unsigned long>&) const
Line
Count
Source
289
28
    {
290
28
        const ReadStatus res = TryRead(key,value);
291
28
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<std::pair<unsigned char, int>, kernel::CBlockFileInfo>(std::pair<unsigned char, int> const&, kernel::CBlockFileInfo&) const
Line
Count
Source
289
2.64k
    {
290
2.64k
        const ReadStatus res = TryRead(key,value);
291
2.64k
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<unsigned char, int>(unsigned char const&, int&) const
Line
Count
Source
289
1.31k
    {
290
1.31k
        const ReadStatus res = TryRead(key,value);
291
1.31k
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<std::pair<unsigned char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, unsigned char>(std::pair<unsigned char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>> const&, unsigned char&) const
Line
Count
Source
289
1.31k
    {
290
1.31k
        const ReadStatus res = TryRead(key,value);
291
1.31k
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
bool CDBWrapper::Read<unsigned char, std::vector<uint256, std::allocator<uint256>>>(unsigned char const&, std::vector<uint256, std::allocator<uint256>>&) const
Line
Count
Source
289
1.69k
    {
290
1.69k
        const ReadStatus res = TryRead(key,value);
291
1.69k
        if (res.has_value()) return res.value();
292
0
        switch (const auto& [err_code, err_msg] = res.error(); err_code) {
293
0
            case ReadFailure::Code::DeserializationError: return false;
294
0
            case ReadFailure::Code::DatabaseError: throw dbwrapper_error(err_msg);
295
0
        } // no default case, so the compiler can warn about missing cases
296
0
        std::abort(); // unreachable
297
0
    }
298
299
    template <typename K, typename V>
300
    void Write(const K& key, const V& value, bool fSync = false)
301
13.0k
    {
302
13.0k
        CDBBatch batch(*this);
303
13.0k
        batch.Write(key, value);
304
13.0k
        WriteBatch(batch, fSync);
305
13.0k
    }
void CDBWrapper::Write<unsigned char, uint256>(unsigned char const&, uint256 const&, bool)
Line
Count
Source
301
33
    {
302
33
        CDBBatch batch(*this);
303
33
        batch.Write(key, value);
304
33
        WriteBatch(batch, fSync);
305
33
    }
void CDBWrapper::Write<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, uint256>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, uint256 const&, bool)
Line
Count
Source
301
8
    {
302
8
        CDBBatch batch(*this);
303
8
        batch.Write(key, value);
304
8
        WriteBatch(batch, fSync);
305
8
    }
void CDBWrapper::Write<unsigned char, unsigned int>(unsigned char const&, unsigned int const&, bool)
Line
Count
Source
301
258
    {
302
258
        CDBBatch batch(*this);
303
258
        batch.Write(key, value);
304
258
        WriteBatch(batch, fSync);
305
258
    }
void CDBWrapper::Write<unsigned char, bool>(unsigned char const&, bool const&, bool)
Line
Count
Source
301
2
    {
302
2
        CDBBatch batch(*this);
303
2
        batch.Write(key, value);
304
2
        WriteBatch(batch, fSync);
305
2
    }
void CDBWrapper::Write<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, bool>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, bool const&, bool)
Line
Count
Source
301
2
    {
302
2
        CDBBatch batch(*this);
303
2
        batch.Write(key, value);
304
2
        WriteBatch(batch, fSync);
305
2
    }
void CDBWrapper::Write<unsigned char, unsigned char>(unsigned char const&, unsigned char const&, bool)
Line
Count
Source
301
19
    {
302
19
        CDBBatch batch(*this);
303
19
        batch.Write(key, value);
304
19
        WriteBatch(batch, fSync);
305
19
    }
void CDBWrapper::Write<dbwrapper_tests::StringContentsSerializer, unsigned int>(dbwrapper_tests::StringContentsSerializer const&, unsigned int const&, bool)
Line
Count
Source
301
100
    {
302
100
        CDBBatch batch(*this);
303
100
        batch.Write(key, value);
304
100
        WriteBatch(batch, fSync);
305
100
    }
void CDBWrapper::Write<txindex::DBKey, std::array<std::byte, 0ul>>(txindex::DBKey const&, std::array<std::byte, 0ul> const&, bool)
Line
Count
Source
301
1
    {
302
1
        CDBBatch batch(*this);
303
1
        batch.Write(key, value);
304
1
        WriteBatch(batch, fSync);
305
1
    }
void CDBWrapper::Write<std::pair<unsigned char, uint256>, CDiskTxPos>(std::pair<unsigned char, uint256> const&, CDiskTxPos const&, bool)
Line
Count
Source
301
2
    {
302
2
        CDBBatch batch(*this);
303
2
        batch.Write(key, value);
304
2
        WriteBatch(batch, fSync);
305
2
    }
void CDBWrapper::Write<unsigned char, CBlockLocator>(unsigned char const&, CBlockLocator const&, bool)
Line
Count
Source
301
1
    {
302
1
        CDBBatch batch(*this);
303
1
        batch.Write(key, value);
304
1
        WriteBatch(batch, fSync);
305
1
    }
void CDBWrapper::Write<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, Obfuscation>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, Obfuscation const&, bool)
Line
Count
Source
301
563
    {
302
563
        CDBBatch batch(*this);
303
563
        batch.Write(key, value);
304
563
        WriteBatch(batch, fSync);
305
563
    }
blockfilterindex.cpp:void CDBWrapper::Write<index_util::DBHeightKey, std::pair<uint256, (anonymous namespace)::DBVal>>(index_util::DBHeightKey const&, std::pair<uint256, (anonymous namespace)::DBVal> const&, bool)
Line
Count
Source
301
7.98k
    {
302
7.98k
        CDBBatch batch(*this);
303
7.98k
        batch.Write(key, value);
304
7.98k
        WriteBatch(batch, fSync);
305
7.98k
    }
coinstatsindex.cpp:void CDBWrapper::Write<index_util::DBHeightKey, std::pair<uint256, (anonymous namespace)::DBVal>>(index_util::DBHeightKey const&, std::pair<uint256, (anonymous namespace)::DBVal> const&, bool)
Line
Count
Source
301
4.08k
    {
302
4.08k
        CDBBatch batch(*this);
303
4.08k
        batch.Write(key, value);
304
4.08k
        WriteBatch(batch, fSync);
305
4.08k
    }
void CDBWrapper::Write<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::pair<unsigned long, unsigned long>>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::pair<unsigned long, unsigned long> const&, bool)
Line
Count
Source
301
22
    {
302
22
        CDBBatch batch(*this);
303
22
        batch.Write(key, value);
304
22
        WriteBatch(batch, fSync);
305
22
    }
void CDBWrapper::Write<char [12], std::pair<unsigned long, unsigned long>>(char const (&) [12], std::pair<unsigned long, unsigned long> const&, bool)
Line
Count
Source
301
9
    {
302
9
        CDBBatch batch(*this);
303
9
        batch.Write(key, value);
304
9
        WriteBatch(batch, fSync);
305
9
    }
void CDBWrapper::Write<std::pair<unsigned char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, unsigned char>(std::pair<unsigned char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>> const&, unsigned char const&, bool)
Line
Count
Source
301
8
    {
302
8
        CDBBatch batch(*this);
303
8
        batch.Write(key, value);
304
8
        WriteBatch(batch, fSync);
305
8
    }
306
307
    template <typename K>
308
    bool Exists(const K& key) const
309
6.13k
    {
310
6.13k
        DataStream ssKey{};
311
6.13k
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
312
6.13k
        ssKey << key;
313
6.13k
        return ExistsImpl(ssKey);
314
6.13k
    }
bool CDBWrapper::Exists<unsigned char>(unsigned char const&) const
Line
Count
Source
309
1.35k
    {
310
1.35k
        DataStream ssKey{};
311
1.35k
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
312
1.35k
        ssKey << key;
313
1.35k
        return ExistsImpl(ssKey);
314
1.35k
    }
bool CDBWrapper::Exists<txindex::BlockHashKey>(txindex::BlockHashKey const&) const
Line
Count
Source
309
4.73k
    {
310
4.73k
        DataStream ssKey{};
311
4.73k
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
312
4.73k
        ssKey << key;
313
4.73k
        return ExistsImpl(ssKey);
314
4.73k
    }
txdb.cpp:bool CDBWrapper::Exists<(anonymous namespace)::CoinEntry>((anonymous namespace)::CoinEntry const&) const
Line
Count
Source
309
44
    {
310
44
        DataStream ssKey{};
311
44
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
312
44
        ssKey << key;
313
44
        return ExistsImpl(ssKey);
314
44
    }
315
316
    template <typename K>
317
    void Erase(const K& key, bool fSync = false)
318
16
    {
319
16
        CDBBatch batch(*this);
320
16
        batch.Erase(key);
321
16
        WriteBatch(batch, fSync);
322
16
    }
void CDBWrapper::Erase<txindex::DBKey>(txindex::DBKey const&, bool)
Line
Count
Source
318
2
    {
319
2
        CDBBatch batch(*this);
320
2
        batch.Erase(key);
321
2
        WriteBatch(batch, fSync);
322
2
    }
void CDBWrapper::Erase<unsigned char>(unsigned char const&, bool)
Line
Count
Source
318
14
    {
319
14
        CDBBatch batch(*this);
320
14
        batch.Erase(key);
321
14
        WriteBatch(batch, fSync);
322
14
    }
323
324
    void WriteBatch(CDBBatch& batch, bool fSync = false);
325
326
    //! Perform a blocking full compaction of the underlying LevelDB.
327
    void CompactFull();
328
329
    //! Return a LevelDB property value, if available.
330
    std::optional<std::string> GetProperty(const std::string& property) const;
331
332
    // Get an estimate of LevelDB memory usage (in bytes).
333
    size_t DynamicMemoryUsage() const;
334
335
    CDBIterator* NewIterator();
336
337
    /**
338
     * Return true if the database managed by this class contains no entries.
339
     */
340
    bool IsEmpty();
341
342
    //! Probe an unopened database for a key prefix. Return true if a database at
343
    //! path exists and contains at least 1 entry beginning with prefix; missing
344
    //! or empty databases return false, and database errors throw dbwrapper_error.
345
    static bool HasKeyStartingWith(const fs::path& path, uint8_t prefix);
346
347
    template<typename K>
348
    size_t EstimateSize(const K& key_begin, const K& key_end) const
349
102
    {
350
102
        DataStream ssKey1{}, ssKey2{};
351
102
        ssKey1.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
352
102
        ssKey2.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
353
102
        ssKey1 << key_begin;
354
102
        ssKey2 << key_end;
355
102
        return EstimateSizeImpl(ssKey1, ssKey2);
356
102
    }
357
};
358
359
#endif // BITCOIN_DBWRAPPER_H