fuzz coverage

Coverage Report

Created: 2025-10-29 15:27

/Users/eugenesiegel/btc/bitcoin/src/wallet/sqlite.cpp
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2020-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
#include <bitcoin-build-config.h> // IWYU pragma: keep
6
7
#include <wallet/sqlite.h>
8
9
#include <chainparams.h>
10
#include <crypto/common.h>
11
#include <logging.h>
12
#include <sync.h>
13
#include <util/check.h>
14
#include <util/fs_helpers.h>
15
#include <util/strencodings.h>
16
#include <util/translation.h>
17
#include <wallet/db.h>
18
19
#include <sqlite3.h>
20
21
#include <cstdint>
22
#include <optional>
23
#include <utility>
24
#include <vector>
25
26
namespace wallet {
27
static constexpr int32_t WALLET_SCHEMA_VERSION = 0;
28
29
static std::span<const std::byte> SpanFromBlob(sqlite3_stmt* stmt, int col)
30
0
{
31
0
    return {reinterpret_cast<const std::byte*>(sqlite3_column_blob(stmt, col)),
32
0
            static_cast<size_t>(sqlite3_column_bytes(stmt, col))};
33
0
}
34
35
static void ErrorLogCallback(void* arg, int code, const char* msg)
36
0
{
37
    // From sqlite3_config() documentation for the SQLITE_CONFIG_LOG option:
38
    // "The void pointer that is the second argument to SQLITE_CONFIG_LOG is passed through as
39
    // the first parameter to the application-defined logger function whenever that function is
40
    // invoked."
41
    // Assert that this is the case:
42
0
    assert(arg == nullptr);
43
0
    LogPrintf("SQLite Error. Code: %d. Message: %s\n", code, msg);
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
44
0
}
45
46
static int TraceSqlCallback(unsigned code, void* context, void* param1, void* param2)
47
0
{
48
0
    auto* db = static_cast<SQLiteDatabase*>(context);
49
0
    if (code == SQLITE_TRACE_STMT) {
50
0
        auto* stmt = static_cast<sqlite3_stmt*>(param1);
51
        // To be conservative and avoid leaking potentially secret information
52
        // in the log file, only expand statements that query the database, not
53
        // statements that update the database.
54
0
        char* expanded{sqlite3_stmt_readonly(stmt) ? sqlite3_expanded_sql(stmt) : nullptr};
55
0
        LogTrace(BCLog::WALLETDB, "[%s] SQLite Statement: %s\n", db->Filename(), expanded ? expanded : sqlite3_sql(stmt));
Line
Count
Source
382
0
#define LogTrace(category, ...) LogPrintLevel(category, BCLog::Level::Trace, __VA_ARGS__)
Line
Count
Source
373
0
    do {                                                              \
374
0
        if (LogAcceptCategory((category), (level))) {                 \
375
0
            bool rate_limit{level >= BCLog::Level::Info};             \
376
0
            LogPrintLevel_(category, level, rate_limit, __VA_ARGS__); \
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
377
0
        }                                                             \
378
0
    } while (0)
56
0
        if (expanded) sqlite3_free(expanded);
57
0
    }
58
0
    return SQLITE_OK;
59
0
}
60
61
static bool BindBlobToStatement(sqlite3_stmt* stmt,
62
                                int index,
63
                                std::span<const std::byte> blob,
64
                                const std::string& description)
65
0
{
66
    // Pass a pointer to the empty string "" below instead of passing the
67
    // blob.data() pointer if the blob.data() pointer is null. Passing a null
68
    // data pointer to bind_blob would cause sqlite to bind the SQL NULL value
69
    // instead of the empty blob value X'', which would mess up SQL comparisons.
70
0
    int res = sqlite3_bind_blob(stmt, index, blob.data() ? static_cast<const void*>(blob.data()) : "", blob.size(), SQLITE_STATIC);
71
0
    if (res != SQLITE_OK) {
72
0
        LogPrintf("Unable to bind %s to statement: %s\n", description, sqlite3_errstr(res));
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
73
0
        sqlite3_clear_bindings(stmt);
74
0
        sqlite3_reset(stmt);
75
0
        return false;
76
0
    }
77
78
0
    return true;
79
0
}
80
81
static std::optional<int> ReadPragmaInteger(sqlite3* db, const std::string& key, const std::string& description, bilingual_str& error)
82
0
{
83
0
    std::string stmt_text = strprintf("PRAGMA %s", key);
Line
Count
Source
1172
0
#define strprintf tfm::format
84
0
    sqlite3_stmt* pragma_read_stmt{nullptr};
85
0
    int ret = sqlite3_prepare_v2(db, stmt_text.c_str(), -1, &pragma_read_stmt, nullptr);
86
0
    if (ret != SQLITE_OK) {
87
0
        sqlite3_finalize(pragma_read_stmt);
88
0
        error = Untranslated(strprintf("SQLiteDatabase: Failed to prepare the statement to fetch %s: %s", description, sqlite3_errstr(ret)));
Line
Count
Source
1172
0
#define strprintf tfm::format
89
0
        return std::nullopt;
90
0
    }
91
0
    ret = sqlite3_step(pragma_read_stmt);
92
0
    if (ret != SQLITE_ROW) {
93
0
        sqlite3_finalize(pragma_read_stmt);
94
0
        error = Untranslated(strprintf("SQLiteDatabase: Failed to fetch %s: %s", description, sqlite3_errstr(ret)));
Line
Count
Source
1172
0
#define strprintf tfm::format
95
0
        return std::nullopt;
96
0
    }
97
0
    int result = sqlite3_column_int(pragma_read_stmt, 0);
98
0
    sqlite3_finalize(pragma_read_stmt);
99
0
    return result;
100
0
}
101
102
static void SetPragma(sqlite3* db, const std::string& key, const std::string& value, const std::string& err_msg)
103
0
{
104
0
    std::string stmt_text = strprintf("PRAGMA %s = %s", key, value);
Line
Count
Source
1172
0
#define strprintf tfm::format
105
0
    int ret = sqlite3_exec(db, stmt_text.c_str(), nullptr, nullptr, nullptr);
106
0
    if (ret != SQLITE_OK) {
107
0
        throw std::runtime_error(strprintf("SQLiteDatabase: %s: %s\n", err_msg, sqlite3_errstr(ret)));
Line
Count
Source
1172
0
#define strprintf tfm::format
108
0
    }
109
0
}
110
111
Mutex SQLiteDatabase::g_sqlite_mutex;
112
int SQLiteDatabase::g_sqlite_count = 0;
113
114
SQLiteDatabase::SQLiteDatabase(const fs::path& dir_path, const fs::path& file_path, const DatabaseOptions& options, bool mock)
115
0
    : WalletDatabase(), m_mock(mock), m_dir_path(dir_path), m_file_path(fs::PathToString(file_path)), m_write_semaphore(1), m_use_unsafe_sync(options.use_unsafe_sync)
116
0
{
117
0
    {
118
0
        LOCK(g_sqlite_mutex);
Line
Count
Source
259
0
#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
119
0
        if (++g_sqlite_count == 1) {
120
            // Setup logging
121
0
            int ret = sqlite3_config(SQLITE_CONFIG_LOG, ErrorLogCallback, nullptr);
122
0
            if (ret != SQLITE_OK) {
123
0
                throw std::runtime_error(strprintf("SQLiteDatabase: Failed to setup error log: %s\n", sqlite3_errstr(ret)));
Line
Count
Source
1172
0
#define strprintf tfm::format
124
0
            }
125
            // Force serialized threading mode
126
0
            ret = sqlite3_config(SQLITE_CONFIG_SERIALIZED);
127
0
            if (ret != SQLITE_OK) {
128
0
                throw std::runtime_error(strprintf("SQLiteDatabase: Failed to configure serialized threading mode: %s\n", sqlite3_errstr(ret)));
Line
Count
Source
1172
0
#define strprintf tfm::format
129
0
            }
130
0
        }
131
0
        int ret = sqlite3_initialize(); // This is a no-op if sqlite3 is already initialized
132
0
        if (ret != SQLITE_OK) {
133
0
            throw std::runtime_error(strprintf("SQLiteDatabase: Failed to initialize SQLite: %s\n", sqlite3_errstr(ret)));
Line
Count
Source
1172
0
#define strprintf tfm::format
134
0
        }
135
0
    }
136
137
0
    try {
138
0
        Open();
139
0
    } catch (const std::runtime_error&) {
140
        // If open fails, cleanup this object and rethrow the exception
141
0
        Cleanup();
142
0
        throw;
143
0
    }
144
0
}
145
146
void SQLiteBatch::SetupSQLStatements()
147
0
{
148
0
    const std::vector<std::pair<sqlite3_stmt**, const char*>> statements{
149
0
        {&m_read_stmt, "SELECT value FROM main WHERE key = ?"},
150
0
        {&m_insert_stmt, "INSERT INTO main VALUES(?, ?)"},
151
0
        {&m_overwrite_stmt, "INSERT or REPLACE into main values(?, ?)"},
152
0
        {&m_delete_stmt, "DELETE FROM main WHERE key = ?"},
153
0
        {&m_delete_prefix_stmt, "DELETE FROM main WHERE instr(key, ?) = 1"},
154
0
    };
155
156
0
    for (const auto& [stmt_prepared, stmt_text] : statements) {
157
0
        if (*stmt_prepared == nullptr) {
158
0
            int res = sqlite3_prepare_v2(m_database.m_db, stmt_text, -1, stmt_prepared, nullptr);
159
0
            if (res != SQLITE_OK) {
160
0
                throw std::runtime_error(strprintf(
Line
Count
Source
1172
0
#define strprintf tfm::format
161
0
                    "SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
162
0
            }
163
0
        }
164
0
    }
165
0
}
166
167
SQLiteDatabase::~SQLiteDatabase()
168
0
{
169
0
    Cleanup();
170
0
}
171
172
void SQLiteDatabase::Cleanup() noexcept
173
0
{
174
0
    AssertLockNotHeld(g_sqlite_mutex);
Line
Count
Source
142
0
#define AssertLockNotHeld(cs) AssertLockNotHeldInline(#cs, __FILE__, __LINE__, &cs)
175
176
0
    Close();
177
178
0
    LOCK(g_sqlite_mutex);
Line
Count
Source
259
0
#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
Line
Count
Source
11
0
#define UNIQUE_NAME(name) PASTE2(name, __COUNTER__)
Line
Count
Source
9
0
#define PASTE2(x, y) PASTE(x, y)
Line
Count
Source
8
0
#define PASTE(x, y) x ## y
179
0
    if (--g_sqlite_count == 0) {
180
0
        int ret = sqlite3_shutdown();
181
0
        if (ret != SQLITE_OK) {
182
0
            LogPrintf("SQLiteDatabase: Failed to shutdown SQLite: %s\n", sqlite3_errstr(ret));
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
183
0
        }
184
0
    }
185
0
}
186
187
bool SQLiteDatabase::Verify(bilingual_str& error)
188
0
{
189
0
    assert(m_db);
190
191
    // Check the application ID matches our network magic
192
0
    auto read_result = ReadPragmaInteger(m_db, "application_id", "the application id", error);
193
0
    if (!read_result.has_value()) return false;
194
0
    uint32_t app_id = static_cast<uint32_t>(read_result.value());
195
0
    uint32_t net_magic = ReadBE32(Params().MessageStart().data());
196
0
    if (app_id != net_magic) {
197
0
        error = strprintf(_("SQLiteDatabase: Unexpected application id. Expected %u, got %u"), net_magic, app_id);
Line
Count
Source
1172
0
#define strprintf tfm::format
198
0
        return false;
199
0
    }
200
201
    // Check our schema version
202
0
    read_result = ReadPragmaInteger(m_db, "user_version", "sqlite wallet schema version", error);
203
0
    if (!read_result.has_value()) return false;
204
0
    int32_t user_ver = read_result.value();
205
0
    if (user_ver != WALLET_SCHEMA_VERSION) {
206
0
        error = strprintf(_("SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported"), user_ver, WALLET_SCHEMA_VERSION);
Line
Count
Source
1172
0
#define strprintf tfm::format
207
0
        return false;
208
0
    }
209
210
0
    sqlite3_stmt* stmt{nullptr};
211
0
    int ret = sqlite3_prepare_v2(m_db, "PRAGMA integrity_check", -1, &stmt, nullptr);
212
0
    if (ret != SQLITE_OK) {
213
0
        sqlite3_finalize(stmt);
214
0
        error = strprintf(_("SQLiteDatabase: Failed to prepare statement to verify database: %s"), sqlite3_errstr(ret));
Line
Count
Source
1172
0
#define strprintf tfm::format
215
0
        return false;
216
0
    }
217
0
    while (true) {
218
0
        ret = sqlite3_step(stmt);
219
0
        if (ret == SQLITE_DONE) {
220
0
            break;
221
0
        }
222
0
        if (ret != SQLITE_ROW) {
223
0
            error = strprintf(_("SQLiteDatabase: Failed to execute statement to verify database: %s"), sqlite3_errstr(ret));
Line
Count
Source
1172
0
#define strprintf tfm::format
224
0
            break;
225
0
        }
226
0
        const char* msg = (const char*)sqlite3_column_text(stmt, 0);
227
0
        if (!msg) {
228
0
            error = strprintf(_("SQLiteDatabase: Failed to read database verification error: %s"), sqlite3_errstr(ret));
Line
Count
Source
1172
0
#define strprintf tfm::format
229
0
            break;
230
0
        }
231
0
        std::string str_msg(msg);
232
0
        if (str_msg == "ok") {
233
0
            continue;
234
0
        }
235
0
        if (error.empty()) {
236
0
            error = _("Failed to verify database") + Untranslated("\n");
237
0
        }
238
0
        error += Untranslated(strprintf("%s\n", str_msg));
Line
Count
Source
1172
0
#define strprintf tfm::format
239
0
    }
240
0
    sqlite3_finalize(stmt);
241
0
    return error.empty();
242
0
}
243
244
void SQLiteDatabase::Open()
245
0
{
246
0
    int flags = SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
247
0
    if (m_mock) {
248
0
        flags |= SQLITE_OPEN_MEMORY; // In memory database for mock db
249
0
    }
250
251
0
    if (m_db == nullptr) {
252
0
        if (!m_mock) {
253
0
            TryCreateDirectories(m_dir_path);
254
0
        }
255
0
        int ret = sqlite3_open_v2(m_file_path.c_str(), &m_db, flags, nullptr);
256
0
        if (ret != SQLITE_OK) {
257
0
            throw std::runtime_error(strprintf("SQLiteDatabase: Failed to open database: %s\n", sqlite3_errstr(ret)));
Line
Count
Source
1172
0
#define strprintf tfm::format
258
0
        }
259
0
        ret = sqlite3_extended_result_codes(m_db, 1);
260
0
        if (ret != SQLITE_OK) {
261
0
            throw std::runtime_error(strprintf("SQLiteDatabase: Failed to enable extended result codes: %s\n", sqlite3_errstr(ret)));
Line
Count
Source
1172
0
#define strprintf tfm::format
262
0
        }
263
        // Trace SQL statements if tracing is enabled with -debug=walletdb -loglevel=walletdb:trace
264
0
        if (LogAcceptCategory(BCLog::WALLETDB, BCLog::Level::Trace)) {
265
0
           ret = sqlite3_trace_v2(m_db, SQLITE_TRACE_STMT, TraceSqlCallback, this);
266
0
           if (ret != SQLITE_OK) {
267
0
               LogPrintf("Failed to enable SQL tracing for %s\n", Filename());
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
268
0
           }
269
0
        }
270
0
    }
271
272
0
    if (sqlite3_db_readonly(m_db, "main") != 0) {
273
0
        throw std::runtime_error("SQLiteDatabase: Database opened in readonly mode but read-write permissions are needed");
274
0
    }
275
276
    // Acquire an exclusive lock on the database
277
    // First change the locking mode to exclusive
278
0
    SetPragma(m_db, "locking_mode", "exclusive", "Unable to change database locking mode to exclusive");
279
    // Now begin a transaction to acquire the exclusive lock. This lock won't be released until we close because of the exclusive locking mode.
280
0
    int ret = sqlite3_exec(m_db, "BEGIN EXCLUSIVE TRANSACTION", nullptr, nullptr, nullptr);
281
0
    if (ret != SQLITE_OK) {
282
0
        throw std::runtime_error("SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another instance of " CLIENT_NAME "?\n");
283
0
    }
284
0
    ret = sqlite3_exec(m_db, "COMMIT", nullptr, nullptr, nullptr);
285
0
    if (ret != SQLITE_OK) {
286
0
        throw std::runtime_error(strprintf("SQLiteDatabase: Unable to end exclusive lock transaction: %s\n", sqlite3_errstr(ret)));
Line
Count
Source
1172
0
#define strprintf tfm::format
287
0
    }
288
289
    // Enable fullfsync for the platforms that use it
290
0
    SetPragma(m_db, "fullfsync", "true", "Failed to enable fullfsync");
291
292
0
    if (m_use_unsafe_sync) {
293
        // Use normal synchronous mode for the journal
294
0
        LogPrintf("WARNING SQLite is configured to not wait for data to be flushed to disk. Data loss and corruption may occur.\n");
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
295
0
        SetPragma(m_db, "synchronous", "OFF", "Failed to set synchronous mode to OFF");
296
0
    }
297
298
    // Make the table for our key-value pairs
299
    // First check that the main table exists
300
0
    sqlite3_stmt* check_main_stmt{nullptr};
301
0
    ret = sqlite3_prepare_v2(m_db, "SELECT name FROM sqlite_master WHERE type='table' AND name='main'", -1, &check_main_stmt, nullptr);
302
0
    if (ret != SQLITE_OK) {
303
0
        throw std::runtime_error(strprintf("SQLiteDatabase: Failed to prepare statement to check table existence: %s\n", sqlite3_errstr(ret)));
Line
Count
Source
1172
0
#define strprintf tfm::format
304
0
    }
305
0
    ret = sqlite3_step(check_main_stmt);
306
0
    if (sqlite3_finalize(check_main_stmt) != SQLITE_OK) {
307
0
        throw std::runtime_error(strprintf("SQLiteDatabase: Failed to finalize statement checking table existence: %s\n", sqlite3_errstr(ret)));
Line
Count
Source
1172
0
#define strprintf tfm::format
308
0
    }
309
0
    bool table_exists;
310
0
    if (ret == SQLITE_DONE) {
311
0
        table_exists = false;
312
0
    } else if (ret == SQLITE_ROW) {
313
0
        table_exists = true;
314
0
    } else {
315
0
        throw std::runtime_error(strprintf("SQLiteDatabase: Failed to execute statement to check table existence: %s\n", sqlite3_errstr(ret)));
Line
Count
Source
1172
0
#define strprintf tfm::format
316
0
    }
317
318
    // Do the db setup things because the table doesn't exist only when we are creating a new wallet
319
0
    if (!table_exists) {
320
0
        ret = sqlite3_exec(m_db, "CREATE TABLE main(key BLOB PRIMARY KEY NOT NULL, value BLOB NOT NULL)", nullptr, nullptr, nullptr);
321
0
        if (ret != SQLITE_OK) {
322
0
            throw std::runtime_error(strprintf("SQLiteDatabase: Failed to create new database: %s\n", sqlite3_errstr(ret)));
Line
Count
Source
1172
0
#define strprintf tfm::format
323
0
        }
324
325
        // Set the application id
326
0
        uint32_t app_id = ReadBE32(Params().MessageStart().data());
327
0
        SetPragma(m_db, "application_id", strprintf("%d", static_cast<int32_t>(app_id)),
Line
Count
Source
1172
0
#define strprintf tfm::format
328
0
                  "Failed to set the application id");
329
330
        // Set the user version
331
0
        SetPragma(m_db, "user_version", strprintf("%d", WALLET_SCHEMA_VERSION),
Line
Count
Source
1172
0
#define strprintf tfm::format
332
0
                  "Failed to set the wallet schema version");
333
0
    }
334
0
}
335
336
bool SQLiteDatabase::Rewrite()
337
0
{
338
    // Rewrite the database using the VACUUM command: https://sqlite.org/lang_vacuum.html
339
0
    int ret = sqlite3_exec(m_db, "VACUUM", nullptr, nullptr, nullptr);
340
0
    return ret == SQLITE_OK;
341
0
}
342
343
bool SQLiteDatabase::Backup(const std::string& dest) const
344
0
{
345
0
    sqlite3* db_copy;
346
0
    int res = sqlite3_open(dest.c_str(), &db_copy);
347
0
    if (res != SQLITE_OK) {
348
0
        sqlite3_close(db_copy);
349
0
        return false;
350
0
    }
351
0
    sqlite3_backup* backup = sqlite3_backup_init(db_copy, "main", m_db, "main");
352
0
    if (!backup) {
353
0
        LogPrintf("%s: Unable to begin backup: %s\n", __func__, sqlite3_errmsg(m_db));
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
354
0
        sqlite3_close(db_copy);
355
0
        return false;
356
0
    }
357
    // Specifying -1 will copy all of the pages
358
0
    res = sqlite3_backup_step(backup, -1);
359
0
    if (res != SQLITE_DONE) {
360
0
        LogPrintf("%s: Unable to backup: %s\n", __func__, sqlite3_errstr(res));
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
361
0
        sqlite3_backup_finish(backup);
362
0
        sqlite3_close(db_copy);
363
0
        return false;
364
0
    }
365
0
    res = sqlite3_backup_finish(backup);
366
0
    sqlite3_close(db_copy);
367
0
    return res == SQLITE_OK;
368
0
}
369
370
void SQLiteDatabase::Close()
371
0
{
372
0
    int res = sqlite3_close(m_db);
373
0
    if (res != SQLITE_OK) {
374
0
        throw std::runtime_error(strprintf("SQLiteDatabase: Failed to close database: %s\n", sqlite3_errstr(res)));
Line
Count
Source
1172
0
#define strprintf tfm::format
375
0
    }
376
0
    m_db = nullptr;
377
0
}
378
379
bool SQLiteDatabase::HasActiveTxn()
380
0
{
381
    // 'sqlite3_get_autocommit' returns true by default, and false if a transaction has begun and not been committed or rolled back.
382
0
    return m_db && sqlite3_get_autocommit(m_db) == 0;
383
0
}
384
385
int SQliteExecHandler::Exec(SQLiteDatabase& database, const std::string& statement)
386
0
{
387
0
    return sqlite3_exec(database.m_db, statement.data(), nullptr, nullptr, nullptr);
388
0
}
389
390
std::unique_ptr<DatabaseBatch> SQLiteDatabase::MakeBatch()
391
0
{
392
    // We ignore flush_on_close because we don't do manual flushing for SQLite
393
0
    return std::make_unique<SQLiteBatch>(*this);
394
0
}
395
396
SQLiteBatch::SQLiteBatch(SQLiteDatabase& database)
397
0
    : m_database(database)
398
0
{
399
    // Make sure we have a db handle
400
0
    assert(m_database.m_db);
401
402
0
    SetupSQLStatements();
403
0
}
404
405
void SQLiteBatch::Close()
406
0
{
407
0
    bool force_conn_refresh = false;
408
409
    // If we began a transaction, and it wasn't committed, abort the transaction in progress
410
0
    if (m_txn) {
411
0
        if (TxnAbort()) {
412
0
            LogPrintf("SQLiteBatch: Batch closed unexpectedly without the transaction being explicitly committed or aborted\n");
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
413
0
        } else {
414
            // If transaction cannot be aborted, it means there is a bug or there has been data corruption. Try to recover in this case
415
            // by closing and reopening the database. Closing the database should also ensure that any changes made since the transaction
416
            // was opened will be rolled back and future transactions can succeed without committing old data.
417
0
            force_conn_refresh = true;
418
0
            LogPrintf("SQLiteBatch: Batch closed and failed to abort transaction, resetting db connection..\n");
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
419
0
        }
420
0
    }
421
422
    // Free all of the prepared statements
423
0
    const std::vector<std::pair<sqlite3_stmt**, const char*>> statements{
424
0
        {&m_read_stmt, "read"},
425
0
        {&m_insert_stmt, "insert"},
426
0
        {&m_overwrite_stmt, "overwrite"},
427
0
        {&m_delete_stmt, "delete"},
428
0
        {&m_delete_prefix_stmt, "delete prefix"},
429
0
    };
430
431
0
    for (const auto& [stmt_prepared, stmt_description] : statements) {
432
0
        int res = sqlite3_finalize(*stmt_prepared);
433
0
        if (res != SQLITE_OK) {
434
0
            LogPrintf("SQLiteBatch: Batch closed but could not finalize %s statement: %s\n",
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
435
0
                      stmt_description, sqlite3_errstr(res));
436
0
        }
437
0
        *stmt_prepared = nullptr;
438
0
    }
439
440
0
    if (force_conn_refresh) {
441
0
        m_database.Close();
442
0
        try {
443
0
            m_database.Open();
444
            // If TxnAbort failed and we refreshed the connection, the semaphore was not released, so release it here to avoid deadlocks on future writes.
445
0
            m_database.m_write_semaphore.release();
446
0
        } catch (const std::runtime_error&) {
447
            // If open fails, cleanup this object and rethrow the exception
448
0
            m_database.Close();
449
0
            throw;
450
0
        }
451
0
    }
452
0
}
453
454
bool SQLiteBatch::ReadKey(DataStream&& key, DataStream& value)
455
0
{
456
0
    if (!m_database.m_db) return false;
457
0
    assert(m_read_stmt);
458
459
    // Bind: leftmost parameter in statement is index 1
460
0
    if (!BindBlobToStatement(m_read_stmt, 1, key, "key")) return false;
461
0
    int res = sqlite3_step(m_read_stmt);
462
0
    if (res != SQLITE_ROW) {
463
0
        if (res != SQLITE_DONE) {
464
            // SQLITE_DONE means "not found", don't log an error in that case.
465
0
            LogPrintf("%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
466
0
        }
467
0
        sqlite3_clear_bindings(m_read_stmt);
468
0
        sqlite3_reset(m_read_stmt);
469
0
        return false;
470
0
    }
471
    // Leftmost column in result is index 0
472
0
    value.clear();
473
0
    value.write(SpanFromBlob(m_read_stmt, 0));
474
475
0
    sqlite3_clear_bindings(m_read_stmt);
476
0
    sqlite3_reset(m_read_stmt);
477
0
    return true;
478
0
}
479
480
bool SQLiteBatch::WriteKey(DataStream&& key, DataStream&& value, bool overwrite)
481
0
{
482
0
    if (!m_database.m_db) return false;
483
0
    assert(m_insert_stmt && m_overwrite_stmt);
484
485
0
    sqlite3_stmt* stmt;
486
0
    if (overwrite) {
487
0
        stmt = m_overwrite_stmt;
488
0
    } else {
489
0
        stmt = m_insert_stmt;
490
0
    }
491
492
    // Bind: leftmost parameter in statement is index 1
493
    // Insert index 1 is key, 2 is value
494
0
    if (!BindBlobToStatement(stmt, 1, key, "key")) return false;
495
0
    if (!BindBlobToStatement(stmt, 2, value, "value")) return false;
496
497
    // Acquire semaphore if not previously acquired when creating a transaction.
498
0
    if (!m_txn) m_database.m_write_semaphore.acquire();
499
500
    // Execute
501
0
    int res = sqlite3_step(stmt);
502
0
    sqlite3_clear_bindings(stmt);
503
0
    sqlite3_reset(stmt);
504
0
    if (res != SQLITE_DONE) {
505
0
        LogPrintf("%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
506
0
    }
507
508
0
    if (!m_txn) m_database.m_write_semaphore.release();
509
510
0
    return res == SQLITE_DONE;
511
0
}
512
513
bool SQLiteBatch::ExecStatement(sqlite3_stmt* stmt, std::span<const std::byte> blob)
514
0
{
515
0
    if (!m_database.m_db) return false;
516
0
    assert(stmt);
517
518
    // Bind: leftmost parameter in statement is index 1
519
0
    if (!BindBlobToStatement(stmt, 1, blob, "key")) return false;
520
521
    // Acquire semaphore if not previously acquired when creating a transaction.
522
0
    if (!m_txn) m_database.m_write_semaphore.acquire();
523
524
    // Execute
525
0
    int res = sqlite3_step(stmt);
526
0
    sqlite3_clear_bindings(stmt);
527
0
    sqlite3_reset(stmt);
528
0
    if (res != SQLITE_DONE) {
529
0
        LogPrintf("%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
530
0
    }
531
532
0
    if (!m_txn) m_database.m_write_semaphore.release();
533
534
0
    return res == SQLITE_DONE;
535
0
}
536
537
bool SQLiteBatch::EraseKey(DataStream&& key)
538
0
{
539
0
    return ExecStatement(m_delete_stmt, key);
540
0
}
541
542
bool SQLiteBatch::ErasePrefix(std::span<const std::byte> prefix)
543
0
{
544
0
    return ExecStatement(m_delete_prefix_stmt, prefix);
545
0
}
546
547
bool SQLiteBatch::HasKey(DataStream&& key)
548
0
{
549
0
    if (!m_database.m_db) return false;
550
0
    assert(m_read_stmt);
551
552
    // Bind: leftmost parameter in statement is index 1
553
0
    if (!BindBlobToStatement(m_read_stmt, 1, key, "key")) return false;
554
0
    int res = sqlite3_step(m_read_stmt);
555
0
    sqlite3_clear_bindings(m_read_stmt);
556
0
    sqlite3_reset(m_read_stmt);
557
0
    return res == SQLITE_ROW;
558
0
}
559
560
DatabaseCursor::Status SQLiteCursor::Next(DataStream& key, DataStream& value)
561
0
{
562
0
    int res = sqlite3_step(m_cursor_stmt);
563
0
    if (res == SQLITE_DONE) {
564
0
        return Status::DONE;
565
0
    }
566
0
    if (res != SQLITE_ROW) {
567
0
        LogPrintf("%s: Unable to execute cursor step: %s\n", __func__, sqlite3_errstr(res));
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
568
0
        return Status::FAIL;
569
0
    }
570
571
0
    key.clear();
572
0
    value.clear();
573
574
    // Leftmost column in result is index 0
575
0
    key.write(SpanFromBlob(m_cursor_stmt, 0));
576
0
    value.write(SpanFromBlob(m_cursor_stmt, 1));
577
0
    return Status::MORE;
578
0
}
579
580
SQLiteCursor::~SQLiteCursor()
581
0
{
582
0
    sqlite3_clear_bindings(m_cursor_stmt);
583
0
    sqlite3_reset(m_cursor_stmt);
584
0
    int res = sqlite3_finalize(m_cursor_stmt);
585
0
    if (res != SQLITE_OK) {
586
0
        LogPrintf("%s: cursor closed but could not finalize cursor statement: %s\n",
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
587
0
                  __func__, sqlite3_errstr(res));
588
0
    }
589
0
}
590
591
std::unique_ptr<DatabaseCursor> SQLiteBatch::GetNewCursor()
592
0
{
593
0
    if (!m_database.m_db) return nullptr;
594
0
    auto cursor = std::make_unique<SQLiteCursor>();
595
596
0
    const char* stmt_text = "SELECT key, value FROM main";
597
0
    int res = sqlite3_prepare_v2(m_database.m_db, stmt_text, -1, &cursor->m_cursor_stmt, nullptr);
598
0
    if (res != SQLITE_OK) {
599
0
        throw std::runtime_error(strprintf(
Line
Count
Source
1172
0
#define strprintf tfm::format
600
0
            "%s: Failed to setup cursor SQL statement: %s\n", __func__, sqlite3_errstr(res)));
601
0
    }
602
603
0
    return cursor;
604
0
}
605
606
std::unique_ptr<DatabaseCursor> SQLiteBatch::GetNewPrefixCursor(std::span<const std::byte> prefix)
607
0
{
608
0
    if (!m_database.m_db) return nullptr;
609
610
    // To get just the records we want, the SQL statement does a comparison of the binary data
611
    // where the data must be greater than or equal to the prefix, and less than
612
    // the prefix incremented by one (when interpreted as an integer)
613
0
    std::vector<std::byte> start_range(prefix.begin(), prefix.end());
614
0
    std::vector<std::byte> end_range(prefix.begin(), prefix.end());
615
0
    auto it = end_range.rbegin();
616
0
    for (; it != end_range.rend(); ++it) {
617
0
        if (*it == std::byte(std::numeric_limits<unsigned char>::max())) {
618
0
            *it = std::byte(0);
619
0
            continue;
620
0
        }
621
0
        *it = std::byte(std::to_integer<unsigned char>(*it) + 1);
622
0
        break;
623
0
    }
624
0
    if (it == end_range.rend()) {
625
        // If the prefix is all 0xff bytes, clear end_range as we won't need it
626
0
        end_range.clear();
627
0
    }
628
629
0
    auto cursor = std::make_unique<SQLiteCursor>(start_range, end_range);
630
0
    if (!cursor) return nullptr;
631
632
0
    const char* stmt_text = end_range.empty() ? "SELECT key, value FROM main WHERE key >= ?" :
633
0
                            "SELECT key, value FROM main WHERE key >= ? AND key < ?";
634
0
    int res = sqlite3_prepare_v2(m_database.m_db, stmt_text, -1, &cursor->m_cursor_stmt, nullptr);
635
0
    if (res != SQLITE_OK) {
636
0
        throw std::runtime_error(strprintf(
Line
Count
Source
1172
0
#define strprintf tfm::format
637
0
            "SQLiteDatabase: Failed to setup cursor SQL statement: %s\n", sqlite3_errstr(res)));
638
0
    }
639
640
0
    if (!BindBlobToStatement(cursor->m_cursor_stmt, 1, cursor->m_prefix_range_start, "prefix_start")) return nullptr;
641
0
    if (!end_range.empty()) {
642
0
        if (!BindBlobToStatement(cursor->m_cursor_stmt, 2, cursor->m_prefix_range_end, "prefix_end")) return nullptr;
643
0
    }
644
645
0
    return cursor;
646
0
}
647
648
bool SQLiteBatch::TxnBegin()
649
0
{
650
0
    if (!m_database.m_db || m_txn) return false;
651
0
    m_database.m_write_semaphore.acquire();
652
0
    Assert(!m_database.HasActiveTxn());
Line
Count
Source
106
0
#define Assert(val) inline_assertion_check<true>(val, __FILE__, __LINE__, __func__, #val)
653
0
    int res = Assert(m_exec_handler)->Exec(m_database, "BEGIN TRANSACTION");
Line
Count
Source
106
0
#define Assert(val) inline_assertion_check<true>(val, __FILE__, __LINE__, __func__, #val)
654
0
    if (res != SQLITE_OK) {
655
0
        LogPrintf("SQLiteBatch: Failed to begin the transaction\n");
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
656
0
        m_database.m_write_semaphore.release();
657
0
    } else {
658
0
        m_txn = true;
659
0
    }
660
0
    return res == SQLITE_OK;
661
0
}
662
663
bool SQLiteBatch::TxnCommit()
664
0
{
665
0
    if (!m_database.m_db || !m_txn) return false;
666
0
    Assert(m_database.HasActiveTxn());
Line
Count
Source
106
0
#define Assert(val) inline_assertion_check<true>(val, __FILE__, __LINE__, __func__, #val)
667
0
    int res = Assert(m_exec_handler)->Exec(m_database, "COMMIT TRANSACTION");
Line
Count
Source
106
0
#define Assert(val) inline_assertion_check<true>(val, __FILE__, __LINE__, __func__, #val)
668
0
    if (res != SQLITE_OK) {
669
0
        LogPrintf("SQLiteBatch: Failed to commit the transaction\n");
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
670
0
    } else {
671
0
        m_txn = false;
672
0
        m_database.m_write_semaphore.release();
673
0
    }
674
0
    return res == SQLITE_OK;
675
0
}
676
677
bool SQLiteBatch::TxnAbort()
678
0
{
679
0
    if (!m_database.m_db || !m_txn) return false;
680
0
    Assert(m_database.HasActiveTxn());
Line
Count
Source
106
0
#define Assert(val) inline_assertion_check<true>(val, __FILE__, __LINE__, __func__, #val)
681
0
    int res = Assert(m_exec_handler)->Exec(m_database, "ROLLBACK TRANSACTION");
Line
Count
Source
106
0
#define Assert(val) inline_assertion_check<true>(val, __FILE__, __LINE__, __func__, #val)
682
0
    if (res != SQLITE_OK) {
683
0
        LogPrintf("SQLiteBatch: Failed to abort the transaction\n");
Line
Count
Source
361
0
#define LogPrintf(...) LogInfo(__VA_ARGS__)
Line
Count
Source
356
0
#define LogInfo(...) LogPrintLevel_(BCLog::LogFlags::ALL, BCLog::Level::Info, /*should_ratelimit=*/true, __VA_ARGS__)
Line
Count
Source
350
0
#define LogPrintLevel_(category, level, should_ratelimit, ...) LogPrintFormatInternal(std::source_location::current(), category, level, should_ratelimit, __VA_ARGS__)
684
0
    } else {
685
0
        m_txn = false;
686
0
        m_database.m_write_semaphore.release();
687
0
    }
688
0
    return res == SQLITE_OK;
689
0
}
690
691
std::unique_ptr<SQLiteDatabase> MakeSQLiteDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error)
692
0
{
693
0
    try {
694
0
        fs::path data_file = SQLiteDataFile(path);
695
0
        auto db = std::make_unique<SQLiteDatabase>(data_file.parent_path(), data_file, options);
696
0
        if (options.verify && !db->Verify(error)) {
697
0
            status = DatabaseStatus::FAILED_VERIFY;
698
0
            return nullptr;
699
0
        }
700
0
        status = DatabaseStatus::SUCCESS;
701
0
        return db;
702
0
    } catch (const std::runtime_error& e) {
703
0
        status = DatabaseStatus::FAILED_LOAD;
704
0
        error = Untranslated(e.what());
705
0
        return nullptr;
706
0
    }
707
0
}
708
709
std::string SQLiteDatabaseVersion()
710
0
{
711
0
    return std::string(sqlite3_libversion());
712
0
}
713
} // namespace wallet