Coverage Report

Created: 2025-06-10 13:21

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