Coverage Report

Created: 2026-09-14 20:36

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