Coverage Report

Created: 2026-09-21 19:49

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.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
    }
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.28k
    {
115
4.28k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
116
4.28k
        m_key_scratch << key;
117
4.28k
        m_value_scratch << value;
118
4.28k
        WriteImpl(m_key_scratch, m_value_scratch);
119
4.28k
    }
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
219
    {
115
219
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
116
219
        m_key_scratch << key;
117
219
        m_value_scratch << value;
118
219
        WriteImpl(m_key_scratch, m_value_scratch);
119
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
114
550
    {
115
550
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
116
550
        m_key_scratch << key;
117
550
        m_value_scratch << value;
118
550
        WriteImpl(m_key_scratch, m_value_scratch);
119
550
    }
void CDBBatch::Write<unsigned char, FlatFilePos>(unsigned char const&, FlatFilePos const&)
Line
Count
Source
114
179
    {
115
179
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
116
179
        m_key_scratch << key;
117
179
        m_value_scratch << value;
118
179
        WriteImpl(m_key_scratch, m_value_scratch);
119
179
    }
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.97k
    {
115
7.97k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
116
7.97k
        m_key_scratch << key;
117
7.97k
        m_value_scratch << value;
118
7.97k
        WriteImpl(m_key_scratch, m_value_scratch);
119
7.97k
    }
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.08k
    {
115
4.08k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
116
4.08k
        m_key_scratch << key;
117
4.08k
        m_value_scratch << value;
118
4.08k
        WriteImpl(m_key_scratch, m_value_scratch);
119
4.08k
    }
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
118
    {
115
118
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
116
118
        m_key_scratch << key;
117
118
        m_value_scratch << value;
118
118
        WriteImpl(m_key_scratch, m_value_scratch);
119
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
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
57
    {
115
57
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
116
57
        m_key_scratch << key;
117
57
        m_value_scratch << value;
118
57
        WriteImpl(m_key_scratch, m_value_scratch);
119
57
    }
void CDBBatch::Write<txindex::BlockHashKey, unsigned int>(txindex::BlockHashKey const&, unsigned int const&)
Line
Count
Source
114
4.13k
    {
115
4.13k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
116
4.13k
        m_key_scratch << key;
117
4.13k
        m_value_scratch << value;
118
4.13k
        WriteImpl(m_key_scratch, m_value_scratch);
119
4.13k
    }
void CDBBatch::Write<txindex::BlockSeqKey, uint256>(txindex::BlockSeqKey const&, uint256 const&)
Line
Count
Source
114
4.13k
    {
115
4.13k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
116
4.13k
        m_key_scratch << key;
117
4.13k
        m_value_scratch << value;
118
4.13k
        WriteImpl(m_key_scratch, m_value_scratch);
119
4.13k
    }
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.13k
    {
115
4.13k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
116
4.13k
        m_key_scratch << key;
117
4.13k
        m_value_scratch << value;
118
4.13k
        WriteImpl(m_key_scratch, m_value_scratch);
119
4.13k
    }
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.69k
    {
115
1.69k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
116
1.69k
        m_key_scratch << key;
117
1.69k
        m_value_scratch << value;
118
1.69k
        WriteImpl(m_key_scratch, m_value_scratch);
119
1.69k
    }
void CDBBatch::Write<unsigned char, int>(unsigned char const&, int const&)
Line
Count
Source
114
3.56k
    {
115
3.56k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
116
3.56k
        m_key_scratch << key;
117
3.56k
        m_value_scratch << value;
118
3.56k
        WriteImpl(m_key_scratch, m_value_scratch);
119
3.56k
    }
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.85k
    {
115
3.85k
        ScopedDataStreamUsage scoped_key{m_key_scratch}, scoped_value{m_value_scratch};
116
3.85k
        m_key_scratch << key;
117
3.85k
        m_value_scratch << value;
118
3.85k
        WriteImpl(m_key_scratch, m_value_scratch);
119
3.85k
    }
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
41.2k
    {
124
41.2k
        ScopedDataStreamUsage scoped_key{m_key_scratch};
125
41.2k
        m_key_scratch << key;
126
41.2k
        EraseImpl(m_key_scratch);
127
41.2k
    }
void CDBBatch::Erase<unsigned char>(unsigned char const&)
Line
Count
Source
123
7.71k
    {
124
7.71k
        ScopedDataStreamUsage scoped_key{m_key_scratch};
125
7.71k
        m_key_scratch << key;
126
7.71k
        EraseImpl(m_key_scratch);
127
7.71k
    }
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.4k
    {
124
33.4k
        ScopedDataStreamUsage scoped_key{m_key_scratch};
125
33.4k
        m_key_scratch << key;
126
33.4k
        EraseImpl(m_key_scratch);
127
33.4k
    }
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.78k
    template<typename K> void Seek(const K& key) {
160
4.78k
        ScopedDataStreamUsage scoped_scratch{m_scratch};
161
4.78k
        m_scratch << key;
162
4.78k
        SeekImpl(m_scratch);
163
4.78k
    }
void CDBIterator::Seek<unsigned char>(unsigned char const&)
Line
Count
Source
159
1.26k
    template<typename K> void Seek(const K& key) {
160
1.26k
        ScopedDataStreamUsage scoped_scratch{m_scratch};
161
1.26k
        m_scratch << key;
162
1.26k
        SeekImpl(m_scratch);
163
1.26k
    }
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.53k
    template<typename K> void Seek(const K& key) {
160
2.53k
        ScopedDataStreamUsage scoped_scratch{m_scratch};
161
2.53k
        m_scratch << key;
162
2.53k
        SeekImpl(m_scratch);
163
2.53k
    }
164
165
    void Next();
166
167
423k
    template<typename K> bool GetKey(K& key) {
168
423k
        try {
169
423k
            SpanReader ssKey{GetKeyImpl()};
170
423k
            ssKey >> key;
171
423k
        } catch (const std::exception&) {
172
783
            return false;
173
783
        }
174
423k
        return true;
175
423k
    }
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
326
    template<typename K> bool GetKey(K& key) {
168
326
        try {
169
326
            SpanReader ssKey{GetKeyImpl()};
170
326
            ssKey >> key;
171
326
        } catch (const std::exception&) {
172
0
            return false;
173
0
        }
174
326
        return true;
175
326
    }
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
30
    template<typename K> bool GetKey(K& key) {
168
30
        try {
169
30
            SpanReader ssKey{GetKeyImpl()};
170
30
            ssKey >> key;
171
30
        } catch (const std::exception&) {
172
0
            return false;
173
0
        }
174
30
        return true;
175
30
    }
bool CDBIterator::GetKey<std::pair<unsigned char, uint256>>(std::pair<unsigned char, uint256>&)
Line
Count
Source
167
144k
    template<typename K> bool GetKey(K& key) {
168
144k
        try {
169
144k
            SpanReader ssKey{GetKeyImpl()};
170
144k
            ssKey >> key;
171
144k
        } catch (const std::exception&) {
172
781
            return false;
173
781
        }
174
144k
        return true;
175
144k
    }
txdb.cpp:bool CDBIterator::GetKey<(anonymous namespace)::CoinEntry>((anonymous namespace)::CoinEntry&)
Line
Count
Source
167
275k
    template<typename K> bool GetKey(K& key) {
168
275k
        try {
169
275k
            SpanReader ssKey{GetKeyImpl()};
170
275k
            ssKey >> key;
171
275k
        } catch (const std::exception&) {
172
0
            return false;
173
0
        }
174
275k
        return true;
175
275k
    }
176
177
422k
    template<typename V> bool GetValue(V& value) {
178
422k
        try {
179
422k
            ScopedDataStreamUsage scoped_scratch{m_scratch};
180
422k
            m_scratch.write(GetValueImpl());
181
422k
            dbwrapper_private::GetObfuscation(parent)(m_scratch);
182
422k
            m_scratch >> value;
183
422k
        } catch (const std::exception&) {
184
2
            return false;
185
2
        }
186
422k
        return true;
187
422k
    }
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
144k
    template<typename V> bool GetValue(V& value) {
178
144k
        try {
179
144k
            ScopedDataStreamUsage scoped_scratch{m_scratch};
180
144k
            m_scratch.write(GetValueImpl());
181
144k
            dbwrapper_private::GetObfuscation(parent)(m_scratch);
182
144k
            m_scratch >> value;
183
144k
        } catch (const std::exception&) {
184
0
            return false;
185
0
        }
186
144k
        return true;
187
144k
    }
bool CDBIterator::GetValue<Coin>(Coin&)
Line
Count
Source
177
275k
    template<typename V> bool GetValue(V& value) {
178
275k
        try {
179
275k
            ScopedDataStreamUsage scoped_scratch{m_scratch};
180
275k
            m_scratch.write(GetValueImpl());
181
275k
            dbwrapper_private::GetObfuscation(parent)(m_scratch);
182
275k
            m_scratch >> value;
183
275k
        } catch (const std::exception&) {
184
0
            return false;
185
0
        }
186
275k
        return true;
187
275k
    }
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
10.8M
    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
5.34M
    {
251
5.34M
        DataStream ssKey{};
252
5.34M
        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
5.34M
        ssKey << key;
256
257
5.34M
        std::optional<std::string> strValue;
258
5.34M
        try {
259
5.34M
            strValue = ReadImpl(ssKey);
260
5.34M
            if (!strValue) {
261
5.24M
                return false; // not found
262
5.24M
            }
263
5.34M
        } catch (const std::exception& e) {
264
3
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
265
3
        }
266
267
98.0k
        try {
268
98.0k
            std::span ssValue{MakeWritableByteSpan(*strValue)};
269
98.0k
            m_obfuscation(ssValue);
270
98.0k
            SpanReader{ssValue} >> value;
271
98.0k
        } catch (const std::exception& e) {
272
4
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
273
4
        }
274
275
98.0k
        return true;
276
98.0k
    }
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.04k
    {
251
8.04k
        DataStream ssKey{};
252
8.04k
        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.04k
        ssKey << key;
256
257
8.04k
        std::optional<std::string> strValue;
258
8.04k
        try {
259
8.04k
            strValue = ReadImpl(ssKey);
260
8.04k
            if (!strValue) {
261
1.84k
                return false; // not found
262
1.84k
            }
263
8.04k
        } catch (const std::exception& e) {
264
2
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
265
2
        }
266
267
6.19k
        try {
268
6.19k
            std::span ssValue{MakeWritableByteSpan(*strValue)};
269
6.19k
            m_obfuscation(ssValue);
270
6.19k
            SpanReader{ssValue} >> value;
271
6.19k
        } catch (const std::exception& e) {
272
4
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
273
4
        }
274
275
6.18k
        return true;
276
6.19k
    }
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
163
    {
251
163
        DataStream ssKey{};
252
163
        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
163
        ssKey << key;
256
257
163
        std::optional<std::string> strValue;
258
163
        try {
259
163
            strValue = ReadImpl(ssKey);
260
163
            if (!strValue) {
261
80
                return false; // not found
262
80
            }
263
163
        } catch (const std::exception& e) {
264
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
265
0
        }
266
267
83
        try {
268
83
            std::span ssValue{MakeWritableByteSpan(*strValue)};
269
83
            m_obfuscation(ssValue);
270
83
            SpanReader{ssValue} >> value;
271
83
        } catch (const std::exception& e) {
272
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
273
0
        }
274
275
83
        return true;
276
83
    }
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.94k
    {
251
2.94k
        DataStream ssKey{};
252
2.94k
        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.94k
        ssKey << key;
256
257
2.94k
        std::optional<std::string> strValue;
258
2.94k
        try {
259
2.94k
            strValue = ReadImpl(ssKey);
260
2.94k
            if (!strValue) {
261
2.04k
                return false; // not found
262
2.04k
            }
263
2.94k
        } catch (const std::exception& e) {
264
1
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
265
1
        }
266
267
893
        try {
268
893
            std::span ssValue{MakeWritableByteSpan(*strValue)};
269
893
            m_obfuscation(ssValue);
270
893
            SpanReader{ssValue} >> value;
271
893
        } catch (const std::exception& e) {
272
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
273
0
        }
274
275
893
        return true;
276
893
    }
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
24
                return false; // not found
262
24
            }
263
53
        } catch (const std::exception& e) {
264
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
265
0
        }
266
267
29
        try {
268
29
            std::span ssValue{MakeWritableByteSpan(*strValue)};
269
29
            m_obfuscation(ssValue);
270
29
            SpanReader{ssValue} >> value;
271
29
        } catch (const std::exception& e) {
272
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
273
0
        }
274
275
29
        return true;
276
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
250
1.33k
    {
251
1.33k
        DataStream ssKey{};
252
1.33k
        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.33k
        ssKey << key;
256
257
1.33k
        std::optional<std::string> strValue;
258
1.33k
        try {
259
1.33k
            strValue = ReadImpl(ssKey);
260
1.33k
            if (!strValue) {
261
304
                return false; // not found
262
304
            }
263
1.33k
        } 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
20
                return false; // not found
262
20
            }
263
52
        } catch (const std::exception& e) {
264
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
265
0
        }
266
267
32
        try {
268
32
            std::span ssValue{MakeWritableByteSpan(*strValue)};
269
32
            m_obfuscation(ssValue);
270
32
            SpanReader{ssValue} >> value;
271
32
        } catch (const std::exception& e) {
272
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
273
0
        }
274
275
32
        return true;
276
32
    }
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
223
    {
251
223
        DataStream ssKey{};
252
223
        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
223
        ssKey << key;
256
257
223
        std::optional<std::string> strValue;
258
223
        try {
259
223
            strValue = ReadImpl(ssKey);
260
223
            if (!strValue) {
261
1
                return false; // not found
262
1
            }
263
223
        } catch (const std::exception& e) {
264
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
265
0
        }
266
267
222
        try {
268
222
            std::span ssValue{MakeWritableByteSpan(*strValue)};
269
222
            m_obfuscation(ssValue);
270
222
            SpanReader{ssValue} >> value;
271
222
        } catch (const std::exception& e) {
272
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
273
0
        }
274
275
222
        return true;
276
222
    }
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
25
                return false; // not found
262
25
            }
263
52
        } 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<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.13k
    {
251
4.13k
        DataStream ssKey{};
252
4.13k
        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.13k
        ssKey << key;
256
257
4.13k
        std::optional<std::string> strValue;
258
4.13k
        try {
259
4.13k
            strValue = ReadImpl(ssKey);
260
4.13k
            if (!strValue) {
261
20
                return false; // not found
262
20
            }
263
4.13k
        } catch (const std::exception& e) {
264
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
265
0
        }
266
267
4.11k
        try {
268
4.11k
            std::span ssValue{MakeWritableByteSpan(*strValue)};
269
4.11k
            m_obfuscation(ssValue);
270
4.11k
            SpanReader{ssValue} >> value;
271
4.11k
        } catch (const std::exception& e) {
272
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
273
0
        }
274
275
4.11k
        return true;
276
4.11k
    }
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.54k
    {
251
2.54k
        DataStream ssKey{};
252
2.54k
        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.54k
        ssKey << key;
256
257
2.54k
        std::optional<std::string> strValue;
258
2.54k
        try {
259
2.54k
            strValue = ReadImpl(ssKey);
260
2.54k
            if (!strValue) {
261
1.74k
                return false; // not found
262
1.74k
            }
263
2.54k
        } catch (const std::exception& e) {
264
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
265
0
        }
266
267
796
        try {
268
796
            std::span ssValue{MakeWritableByteSpan(*strValue)};
269
796
            m_obfuscation(ssValue);
270
796
            SpanReader{ssValue} >> value;
271
796
        } catch (const std::exception& e) {
272
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
273
0
        }
274
275
796
        return true;
276
796
    }
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
482
                return false; // not found
262
482
            }
263
1.26k
        } catch (const std::exception& e) {
264
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
265
0
        }
266
267
779
        try {
268
779
            std::span ssValue{MakeWritableByteSpan(*strValue)};
269
779
            m_obfuscation(ssValue);
270
779
            SpanReader{ssValue} >> value;
271
779
        } catch (const std::exception& e) {
272
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
273
0
        }
274
275
779
        return true;
276
779
    }
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.25k
                return false; // not found
262
1.25k
            }
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
5.31M
    {
251
5.31M
        DataStream ssKey{};
252
5.31M
        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
5.31M
        ssKey << key;
256
257
5.31M
        std::optional<std::string> strValue;
258
5.31M
        try {
259
5.31M
            strValue = ReadImpl(ssKey);
260
5.31M
            if (!strValue) {
261
5.23M
                return false; // not found
262
5.23M
            }
263
5.31M
        } catch (const std::exception& e) {
264
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DatabaseError, e.what()});
265
0
        }
266
267
83.5k
        try {
268
83.5k
            std::span ssValue{MakeWritableByteSpan(*strValue)};
269
83.5k
            m_obfuscation(ssValue);
270
83.5k
            SpanReader{ssValue} >> value;
271
83.5k
        } catch (const std::exception& e) {
272
0
            return util::Unexpected(ReadFailure{ReadFailure::Code::DeserializationError, e.what()});
273
0
        }
274
275
83.5k
        return true;
276
83.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
23.9k
    {
289
23.9k
        const ReadStatus res = TryRead(key,value);
290
23.9k
        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.03k
    {
289
8.03k
        const ReadStatus res = TryRead(key,value);
290
8.03k
        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
163
    {
289
163
        const ReadStatus res = TryRead(key,value);
290
163
        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.94k
    {
289
2.94k
        const ReadStatus res = TryRead(key,value);
290
2.94k
        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.33k
    {
289
1.33k
        const ReadStatus res = TryRead(key,value);
290
1.33k
        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
223
    {
289
223
        const ReadStatus res = TryRead(key,value);
290
223
        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.13k
    {
289
4.13k
        const ReadStatus res = TryRead(key,value);
290
4.13k
        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.54k
    {
289
2.54k
        const ReadStatus res = TryRead(key,value);
290
2.54k
        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.0k
    {
301
13.0k
        CDBBatch batch(*this);
302
13.0k
        batch.Write(key, value);
303
13.0k
        WriteBatch(batch, fSync);
304
13.0k
    }
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
550
    {
301
550
        CDBBatch batch(*this);
302
550
        batch.Write(key, value);
303
550
        WriteBatch(batch, fSync);
304
550
    }
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.97k
    {
301
7.97k
        CDBBatch batch(*this);
302
7.97k
        batch.Write(key, value);
303
7.97k
        WriteBatch(batch, fSync);
304
7.97k
    }
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.08k
    {
301
4.08k
        CDBBatch batch(*this);
302
4.08k
        batch.Write(key, value);
303
4.08k
        WriteBatch(batch, fSync);
304
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
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
5.98k
    {
309
5.98k
        DataStream ssKey{};
310
5.98k
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
311
5.98k
        ssKey << key;
312
5.98k
        return ExistsImpl(ssKey);
313
5.98k
    }
bool CDBWrapper::Exists<unsigned char>(unsigned char const&) const
Line
Count
Source
308
1.30k
    {
309
1.30k
        DataStream ssKey{};
310
1.30k
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
311
1.30k
        ssKey << key;
312
1.30k
        return ExistsImpl(ssKey);
313
1.30k
    }
bool CDBWrapper::Exists<txindex::BlockHashKey>(txindex::BlockHashKey const&) const
Line
Count
Source
308
4.63k
    {
309
4.63k
        DataStream ssKey{};
310
4.63k
        ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
311
4.63k
        ssKey << key;
312
4.63k
        return ExistsImpl(ssKey);
313
4.63k
    }
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