Line data Source code
1 : // Copyright (c) 2020-2021 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 <wallet/sqlite.h>
6 :
7 : #include <chainparams.h>
8 : #include <crypto/common.h>
9 : #include <logging.h>
10 : #include <sync.h>
11 : #include <util/strencodings.h>
12 : #include <util/system.h>
13 : #include <util/translation.h>
14 : #include <wallet/db.h>
15 :
16 : #include <sqlite3.h>
17 : #include <stdint.h>
18 :
19 : #include <optional>
20 : #include <utility>
21 : #include <vector>
22 :
23 : namespace wallet {
24 : static constexpr int32_t WALLET_SCHEMA_VERSION = 0;
25 :
26 68636 : static Span<const std::byte> SpanFromBlob(sqlite3_stmt* stmt, int col)
27 : {
28 137272 : return {reinterpret_cast<const std::byte*>(sqlite3_column_blob(stmt, col)),
29 68636 : static_cast<size_t>(sqlite3_column_bytes(stmt, col))};
30 : }
31 :
32 12 : static void ErrorLogCallback(void* arg, int code, const char* msg)
33 : {
34 : // From sqlite3_config() documentation for the SQLITE_CONFIG_LOG option:
35 : // "The void pointer that is the second argument to SQLITE_CONFIG_LOG is passed through as
36 : // the first parameter to the application-defined logger function whenever that function is
37 : // invoked."
38 : // Assert that this is the case:
39 12 : assert(arg == nullptr);
40 12 : LogPrintf("SQLite Error. Code: %d. Message: %s\n", code, msg);
41 12 : }
42 :
43 251212 : static int TraceSqlCallback(unsigned code, void* context, void* param1, void* param2)
44 : {
45 251212 : auto* db = static_cast<SQLiteDatabase*>(context);
46 251212 : if (code == SQLITE_TRACE_STMT) {
47 251212 : auto* stmt = static_cast<sqlite3_stmt*>(param1);
48 : // To be conservative and avoid leaking potentially secret information
49 : // in the log file, only expand statements that query the database, not
50 : // statements that update the database.
51 251212 : char* expanded{sqlite3_stmt_readonly(stmt) ? sqlite3_expanded_sql(stmt) : nullptr};
52 251212 : LogPrintf("[%s] SQLite Statement: %s\n", db->Filename(), expanded ? expanded : sqlite3_sql(stmt));
53 251212 : if (expanded) sqlite3_free(expanded);
54 251212 : }
55 251212 : return SQLITE_OK;
56 0 : }
57 :
58 460516 : static bool BindBlobToStatement(sqlite3_stmt* stmt,
59 : int index,
60 : Span<const std::byte> blob,
61 : const std::string& description)
62 : {
63 460516 : int res = sqlite3_bind_blob(stmt, index, blob.data(), blob.size(), SQLITE_STATIC);
64 460516 : if (res != SQLITE_OK) {
65 0 : LogPrintf("Unable to bind %s to statement: %s\n", description, sqlite3_errstr(res));
66 0 : sqlite3_clear_bindings(stmt);
67 0 : sqlite3_reset(stmt);
68 0 : return false;
69 : }
70 :
71 460516 : return true;
72 460516 : }
73 :
74 1692 : static std::optional<int> ReadPragmaInteger(sqlite3* db, const std::string& key, const std::string& description, bilingual_str& error)
75 : {
76 1692 : std::string stmt_text = strprintf("PRAGMA %s", key);
77 1692 : sqlite3_stmt* pragma_read_stmt{nullptr};
78 1692 : int ret = sqlite3_prepare_v2(db, stmt_text.c_str(), -1, &pragma_read_stmt, nullptr);
79 1692 : if (ret != SQLITE_OK) {
80 0 : sqlite3_finalize(pragma_read_stmt);
81 0 : error = Untranslated(strprintf("SQLiteDatabase: Failed to prepare the statement to fetch %s: %s", description, sqlite3_errstr(ret)));
82 0 : return std::nullopt;
83 : }
84 1692 : ret = sqlite3_step(pragma_read_stmt);
85 1692 : if (ret != SQLITE_ROW) {
86 0 : sqlite3_finalize(pragma_read_stmt);
87 0 : error = Untranslated(strprintf("SQLiteDatabase: Failed to fetch %s: %s", description, sqlite3_errstr(ret)));
88 0 : return std::nullopt;
89 : }
90 1692 : int result = sqlite3_column_int(pragma_read_stmt, 0);
91 1692 : sqlite3_finalize(pragma_read_stmt);
92 1692 : return result;
93 1692 : }
94 :
95 4084 : static void SetPragma(sqlite3* db, const std::string& key, const std::string& value, const std::string& err_msg)
96 : {
97 4084 : std::string stmt_text = strprintf("PRAGMA %s = %s", key, value);
98 4084 : int ret = sqlite3_exec(db, stmt_text.c_str(), nullptr, nullptr, nullptr);
99 4084 : if (ret != SQLITE_OK) {
100 0 : throw std::runtime_error(strprintf("SQLiteDatabase: %s: %s\n", err_msg, sqlite3_errstr(ret)));
101 : }
102 4084 : }
103 :
104 : Mutex SQLiteDatabase::g_sqlite_mutex;
105 : int SQLiteDatabase::g_sqlite_count = 0;
106 :
107 2154 : SQLiteDatabase::SQLiteDatabase(const fs::path& dir_path, const fs::path& file_path, const DatabaseOptions& options, bool mock)
108 2154 : : WalletDatabase(), m_mock(mock), m_dir_path(fs::PathToString(dir_path)), m_file_path(fs::PathToString(file_path)), m_use_unsafe_sync(options.use_unsafe_sync)
109 2154 : {
110 : {
111 : LOCK(g_sqlite_mutex);
112 : LogPrintf("Using SQLite Version %s\n", SQLiteDatabaseVersion());
113 : LogPrintf("Using wallet %s\n", m_dir_path);
114 :
115 : if (++g_sqlite_count == 1) {
116 : // Setup logging
117 : int ret = sqlite3_config(SQLITE_CONFIG_LOG, ErrorLogCallback, nullptr);
118 : if (ret != SQLITE_OK) {
119 : throw std::runtime_error(strprintf("SQLiteDatabase: Failed to setup error log: %s\n", sqlite3_errstr(ret)));
120 : }
121 : // Force serialized threading mode
122 : ret = sqlite3_config(SQLITE_CONFIG_SERIALIZED);
123 : if (ret != SQLITE_OK) {
124 : throw std::runtime_error(strprintf("SQLiteDatabase: Failed to configure serialized threading mode: %s\n", sqlite3_errstr(ret)));
125 : }
126 : }
127 : int ret = sqlite3_initialize(); // This is a no-op if sqlite3 is already initialized
128 : if (ret != SQLITE_OK) {
129 : throw std::runtime_error(strprintf("SQLiteDatabase: Failed to initialize SQLite: %s\n", sqlite3_errstr(ret)));
130 : }
131 : }
132 :
133 : try {
134 : Open();
135 : } catch (const std::runtime_error&) {
136 : // If open fails, cleanup this object and rethrow the exception
137 : Cleanup();
138 : throw;
139 : }
140 1077 : }
141 :
142 208864 : void SQLiteBatch::SetupSQLStatements()
143 : {
144 1253184 : const std::vector<std::pair<sqlite3_stmt**, const char*>> statements{
145 208864 : {&m_read_stmt, "SELECT value FROM main WHERE key = ?"},
146 208864 : {&m_insert_stmt, "INSERT INTO main VALUES(?, ?)"},
147 208864 : {&m_overwrite_stmt, "INSERT or REPLACE into main values(?, ?)"},
148 208864 : {&m_delete_stmt, "DELETE FROM main WHERE key = ?"},
149 208864 : {&m_cursor_stmt, "SELECT key, value FROM main"},
150 208864 : {&m_delete_prefix_stmt, "DELETE FROM main WHERE instr(key, ?) = 1"},
151 : };
152 :
153 1462048 : for (const auto& [stmt_prepared, stmt_text] : statements) {
154 1253184 : if (*stmt_prepared == nullptr) {
155 3759552 : int res = sqlite3_prepare_v2(m_database.m_db, stmt_text, -1, stmt_prepared, nullptr);
156 1253184 : if (res != SQLITE_OK) {
157 0 : throw std::runtime_error(strprintf(
158 0 : "SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
159 : }
160 1253184 : }
161 : }
162 208864 : }
163 :
164 3201 : SQLiteDatabase::~SQLiteDatabase()
165 3201 : {
166 1067 : Cleanup();
167 3201 : }
168 :
169 1077 : void SQLiteDatabase::Cleanup() noexcept
170 : {
171 1077 : AssertLockNotHeld(g_sqlite_mutex);
172 :
173 1077 : Close();
174 :
175 1077 : LOCK(g_sqlite_mutex);
176 1077 : if (--g_sqlite_count == 0) {
177 669 : int ret = sqlite3_shutdown();
178 669 : if (ret != SQLITE_OK) {
179 0 : LogPrintf("SQLiteDatabase: Failed to shutdown SQLite: %s\n", sqlite3_errstr(ret));
180 0 : }
181 669 : }
182 1077 : }
183 :
184 846 : bool SQLiteDatabase::Verify(bilingual_str& error)
185 : {
186 846 : assert(m_db);
187 :
188 : // Check the application ID matches our network magic
189 846 : auto read_result = ReadPragmaInteger(m_db, "application_id", "the application id", error);
190 846 : if (!read_result.has_value()) return false;
191 846 : uint32_t app_id = static_cast<uint32_t>(read_result.value());
192 846 : uint32_t net_magic = ReadBE32(Params().MessageStart());
193 846 : if (app_id != net_magic) {
194 0 : error = strprintf(_("SQLiteDatabase: Unexpected application id. Expected %u, got %u"), net_magic, app_id);
195 0 : return false;
196 : }
197 :
198 : // Check our schema version
199 846 : read_result = ReadPragmaInteger(m_db, "user_version", "sqlite wallet schema version", error);
200 846 : if (!read_result.has_value()) return false;
201 846 : int32_t user_ver = read_result.value();
202 846 : if (user_ver != WALLET_SCHEMA_VERSION) {
203 0 : error = strprintf(_("SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported"), user_ver, WALLET_SCHEMA_VERSION);
204 0 : return false;
205 : }
206 :
207 846 : sqlite3_stmt* stmt{nullptr};
208 846 : int ret = sqlite3_prepare_v2(m_db, "PRAGMA integrity_check", -1, &stmt, nullptr);
209 846 : if (ret != SQLITE_OK) {
210 0 : sqlite3_finalize(stmt);
211 0 : error = strprintf(_("SQLiteDatabase: Failed to prepare statement to verify database: %s"), sqlite3_errstr(ret));
212 0 : return false;
213 : }
214 846 : while (true) {
215 1692 : ret = sqlite3_step(stmt);
216 1692 : if (ret == SQLITE_DONE) {
217 846 : break;
218 : }
219 846 : if (ret != SQLITE_ROW) {
220 0 : error = strprintf(_("SQLiteDatabase: Failed to execute statement to verify database: %s"), sqlite3_errstr(ret));
221 0 : break;
222 : }
223 846 : const char* msg = (const char*)sqlite3_column_text(stmt, 0);
224 846 : if (!msg) {
225 0 : error = strprintf(_("SQLiteDatabase: Failed to read database verification error: %s"), sqlite3_errstr(ret));
226 0 : break;
227 : }
228 846 : std::string str_msg(msg);
229 846 : if (str_msg == "ok") {
230 846 : continue;
231 : }
232 0 : if (error.empty()) {
233 0 : error = _("Failed to verify database") + Untranslated("\n");
234 0 : }
235 0 : error += Untranslated(strprintf("%s\n", str_msg));
236 846 : }
237 846 : sqlite3_finalize(stmt);
238 846 : return error.empty();
239 846 : }
240 :
241 1077 : void SQLiteDatabase::Open()
242 : {
243 1077 : int flags = SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
244 1077 : if (m_mock) {
245 36 : flags |= SQLITE_OPEN_MEMORY; // In memory database for mock db
246 36 : }
247 :
248 1077 : if (m_db == nullptr) {
249 1077 : if (!m_mock) {
250 1041 : TryCreateDirectories(fs::PathFromString(m_dir_path));
251 1039 : }
252 1075 : int ret = sqlite3_open_v2(m_file_path.c_str(), &m_db, flags, nullptr);
253 1075 : if (ret != SQLITE_OK) {
254 0 : throw std::runtime_error(strprintf("SQLiteDatabase: Failed to open database: %s\n", sqlite3_errstr(ret)));
255 : }
256 1075 : ret = sqlite3_extended_result_codes(m_db, 1);
257 1075 : if (ret != SQLITE_OK) {
258 0 : throw std::runtime_error(strprintf("SQLiteDatabase: Failed to enable extended result codes: %s\n", sqlite3_errstr(ret)));
259 : }
260 : // Trace SQL statements if tracing is enabled with -debug=walletdb -loglevel=walletdb:trace
261 1075 : if (LogAcceptCategory(BCLog::WALLETDB, BCLog::Level::Trace)) {
262 1041 : ret = sqlite3_trace_v2(m_db, SQLITE_TRACE_STMT, TraceSqlCallback, this);
263 1041 : if (ret != SQLITE_OK) {
264 0 : LogPrintf("Failed to enable SQL tracing for %s\n", Filename());
265 0 : }
266 1041 : }
267 1075 : }
268 :
269 1075 : if (sqlite3_db_readonly(m_db, "main") != 0) {
270 0 : throw std::runtime_error("SQLiteDatabase: Database opened in readonly mode but read-write permissions are needed");
271 : }
272 :
273 : // Acquire an exclusive lock on the database
274 : // First change the locking mode to exclusive
275 1075 : SetPragma(m_db, "locking_mode", "exclusive", "Unable to change database locking mode to exclusive");
276 : // Now begin a transaction to acquire the exclusive lock. This lock won't be released until we close because of the exclusive locking mode.
277 1075 : int ret = sqlite3_exec(m_db, "BEGIN EXCLUSIVE TRANSACTION", nullptr, nullptr, nullptr);
278 1075 : if (ret != SQLITE_OK) {
279 8 : throw std::runtime_error("SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another instance of " PACKAGE_NAME "?\n");
280 : }
281 1067 : ret = sqlite3_exec(m_db, "COMMIT", nullptr, nullptr, nullptr);
282 1067 : if (ret != SQLITE_OK) {
283 0 : throw std::runtime_error(strprintf("SQLiteDatabase: Unable to end exclusive lock transaction: %s\n", sqlite3_errstr(ret)));
284 : }
285 :
286 : // Enable fullfsync for the platforms that use it
287 1067 : SetPragma(m_db, "fullfsync", "true", "Failed to enable fullfsync");
288 :
289 1067 : if (m_use_unsafe_sync) {
290 : // Use normal synchronous mode for the journal
291 936 : LogPrintf("WARNING SQLite is configured to not wait for data to be flushed to disk. Data loss and corruption may occur.\n");
292 936 : SetPragma(m_db, "synchronous", "OFF", "Failed to set synchronous mode to OFF");
293 936 : }
294 :
295 : // Make the table for our key-value pairs
296 : // First check that the main table exists
297 1067 : sqlite3_stmt* check_main_stmt{nullptr};
298 1067 : ret = sqlite3_prepare_v2(m_db, "SELECT name FROM sqlite_master WHERE type='table' AND name='main'", -1, &check_main_stmt, nullptr);
299 1067 : if (ret != SQLITE_OK) {
300 0 : throw std::runtime_error(strprintf("SQLiteDatabase: Failed to prepare statement to check table existence: %s\n", sqlite3_errstr(ret)));
301 : }
302 1067 : ret = sqlite3_step(check_main_stmt);
303 1067 : if (sqlite3_finalize(check_main_stmt) != SQLITE_OK) {
304 0 : throw std::runtime_error(strprintf("SQLiteDatabase: Failed to finalize statement checking table existence: %s\n", sqlite3_errstr(ret)));
305 : }
306 : bool table_exists;
307 1067 : if (ret == SQLITE_DONE) {
308 503 : table_exists = false;
309 1067 : } else if (ret == SQLITE_ROW) {
310 564 : table_exists = true;
311 564 : } else {
312 0 : throw std::runtime_error(strprintf("SQLiteDatabase: Failed to execute statement to check table existence: %s\n", sqlite3_errstr(ret)));
313 : }
314 :
315 : // Do the db setup things because the table doesn't exist only when we are creating a new wallet
316 1067 : if (!table_exists) {
317 503 : ret = sqlite3_exec(m_db, "CREATE TABLE main(key BLOB PRIMARY KEY NOT NULL, value BLOB NOT NULL)", nullptr, nullptr, nullptr);
318 503 : if (ret != SQLITE_OK) {
319 0 : throw std::runtime_error(strprintf("SQLiteDatabase: Failed to create new database: %s\n", sqlite3_errstr(ret)));
320 : }
321 :
322 : // Set the application id
323 503 : uint32_t app_id = ReadBE32(Params().MessageStart());
324 1006 : SetPragma(m_db, "application_id", strprintf("%d", static_cast<int32_t>(app_id)),
325 503 : "Failed to set the application id");
326 :
327 : // Set the user version
328 1006 : SetPragma(m_db, "user_version", strprintf("%d", WALLET_SCHEMA_VERSION),
329 503 : "Failed to set the wallet schema version");
330 503 : }
331 1069 : }
332 :
333 35 : bool SQLiteDatabase::Rewrite(const char* skip)
334 : {
335 : // Rewrite the database using the VACUUM command: https://sqlite.org/lang_vacuum.html
336 35 : int ret = sqlite3_exec(m_db, "VACUUM", nullptr, nullptr, nullptr);
337 35 : return ret == SQLITE_OK;
338 : }
339 :
340 44 : bool SQLiteDatabase::Backup(const std::string& dest) const
341 : {
342 : sqlite3* db_copy;
343 44 : int res = sqlite3_open(dest.c_str(), &db_copy);
344 44 : if (res != SQLITE_OK) {
345 6 : sqlite3_close(db_copy);
346 6 : return false;
347 : }
348 38 : sqlite3_backup* backup = sqlite3_backup_init(db_copy, "main", m_db, "main");
349 38 : if (!backup) {
350 0 : LogPrintf("%s: Unable to begin backup: %s\n", __func__, sqlite3_errmsg(m_db));
351 0 : sqlite3_close(db_copy);
352 0 : return false;
353 : }
354 : // Specifying -1 will copy all of the pages
355 38 : res = sqlite3_backup_step(backup, -1);
356 38 : if (res != SQLITE_DONE) {
357 6 : LogPrintf("%s: Unable to backup: %s\n", __func__, sqlite3_errstr(res));
358 6 : sqlite3_backup_finish(backup);
359 6 : sqlite3_close(db_copy);
360 6 : return false;
361 : }
362 32 : res = sqlite3_backup_finish(backup);
363 32 : sqlite3_close(db_copy);
364 32 : return res == SQLITE_OK;
365 44 : }
366 :
367 1753 : void SQLiteDatabase::Close()
368 : {
369 1753 : int res = sqlite3_close(m_db);
370 1753 : if (res != SQLITE_OK) {
371 0 : throw std::runtime_error(strprintf("SQLiteDatabase: Failed to close database: %s\n", sqlite3_errstr(res)));
372 : }
373 1753 : m_db = nullptr;
374 1753 : }
375 :
376 208864 : std::unique_ptr<DatabaseBatch> SQLiteDatabase::MakeBatch(bool flush_on_close)
377 : {
378 : // We ignore flush_on_close because we don't do manual flushing for SQLite
379 208864 : return std::make_unique<SQLiteBatch>(*this);
380 : }
381 :
382 417728 : SQLiteBatch::SQLiteBatch(SQLiteDatabase& database)
383 208864 : : m_database(database)
384 417728 : {
385 : // Make sure we have a db handle
386 : assert(m_database.m_db);
387 :
388 : SetupSQLStatements();
389 208864 : }
390 :
391 208864 : void SQLiteBatch::Close()
392 : {
393 : // If this batch started a transaction that was never committed/aborted,
394 : // abort it now. We intentionally only abort transactions this batch owns:
395 : // nested WalletBatches sharing the SQLite connection must not roll back an
396 : // outer transaction started by a different batch.
397 208864 : if (m_txn_started && m_database.m_db && sqlite3_get_autocommit(m_database.m_db) == 0) {
398 0 : if (TxnAbort()) {
399 0 : LogPrintf("SQLiteBatch: Batch closed unexpectedly without the transaction being explicitly committed or aborted\n");
400 0 : } else {
401 0 : LogPrintf("SQLiteBatch: Batch closed and failed to abort transaction\n");
402 : }
403 0 : }
404 :
405 : // Free all of the prepared statements
406 1253184 : const std::vector<std::pair<sqlite3_stmt**, const char*>> statements{
407 208864 : {&m_read_stmt, "read"},
408 208864 : {&m_insert_stmt, "insert"},
409 208864 : {&m_overwrite_stmt, "overwrite"},
410 208864 : {&m_delete_stmt, "delete"},
411 208864 : {&m_cursor_stmt, "cursor"},
412 208864 : {&m_delete_prefix_stmt, "delete prefix"},
413 : };
414 :
415 2715230 : for (const auto& [stmt_prepared, stmt_description] : statements) {
416 1253183 : int res = sqlite3_finalize(*stmt_prepared);
417 1253183 : if (res != SQLITE_OK) {
418 0 : LogPrintf("SQLiteBatch: Batch closed but could not finalize %s statement: %s\n",
419 : stmt_description, sqlite3_errstr(res));
420 0 : }
421 1253183 : *stmt_prepared = nullptr;
422 : }
423 208864 : }
424 :
425 13353 : bool SQLiteBatch::ReadKey(CDataStream&& key, CDataStream& value)
426 : {
427 13353 : if (!m_database.m_db) return false;
428 13353 : assert(m_read_stmt);
429 :
430 : // Bind: leftmost parameter in statement is index 1
431 13353 : if (!BindBlobToStatement(m_read_stmt, 1, key, "key")) return false;
432 13353 : int res = sqlite3_step(m_read_stmt);
433 13353 : if (res != SQLITE_ROW) {
434 2389 : if (res != SQLITE_DONE) {
435 : // SQLITE_DONE means "not found", don't log an error in that case.
436 0 : LogPrintf("%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
437 0 : }
438 2389 : sqlite3_clear_bindings(m_read_stmt);
439 2389 : sqlite3_reset(m_read_stmt);
440 2389 : return false;
441 : }
442 : // Leftmost column in result is index 0
443 10964 : value.clear();
444 10964 : value.write(SpanFromBlob(m_read_stmt, 0));
445 :
446 10964 : sqlite3_clear_bindings(m_read_stmt);
447 10964 : sqlite3_reset(m_read_stmt);
448 10964 : return true;
449 13353 : }
450 :
451 220009 : bool SQLiteBatch::WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite)
452 : {
453 220009 : if (!m_database.m_db) return false;
454 220009 : assert(m_insert_stmt && m_overwrite_stmt);
455 :
456 : sqlite3_stmt* stmt;
457 220009 : if (overwrite) {
458 199603 : stmt = m_overwrite_stmt;
459 199603 : } else {
460 20406 : stmt = m_insert_stmt;
461 : }
462 :
463 : // Bind: leftmost parameter in statement is index 1
464 : // Insert index 1 is key, 2 is value
465 220009 : if (!BindBlobToStatement(stmt, 1, key, "key")) return false;
466 220009 : if (!BindBlobToStatement(stmt, 2, value, "value")) return false;
467 :
468 : // Execute
469 220009 : int res = sqlite3_step(stmt);
470 220009 : sqlite3_clear_bindings(stmt);
471 220009 : sqlite3_reset(stmt);
472 220009 : if (res != SQLITE_DONE) {
473 0 : LogPrintf("%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
474 0 : }
475 220009 : return res == SQLITE_DONE;
476 220009 : }
477 :
478 7145 : bool SQLiteBatch::ExecStatement(sqlite3_stmt* stmt, Span<const std::byte> blob)
479 : {
480 7145 : if (!m_database.m_db) return false;
481 7145 : assert(stmt);
482 :
483 : // Bind: leftmost parameter in statement is index 1
484 7145 : if (!BindBlobToStatement(stmt, 1, blob, "key")) return false;
485 :
486 : // Execute
487 7145 : int res = sqlite3_step(stmt);
488 7145 : sqlite3_clear_bindings(stmt);
489 7145 : sqlite3_reset(stmt);
490 7145 : if (res != SQLITE_DONE) {
491 0 : LogPrintf("%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
492 0 : }
493 7145 : return res == SQLITE_DONE;
494 7145 : }
495 :
496 7138 : bool SQLiteBatch::EraseKey(CDataStream&& key)
497 : {
498 7138 : return ExecStatement(m_delete_stmt, key);
499 : }
500 :
501 7 : bool SQLiteBatch::ErasePrefix(Span<const std::byte> prefix)
502 : {
503 7 : return ExecStatement(m_delete_prefix_stmt, prefix);
504 : }
505 :
506 0 : bool SQLiteBatch::HasKey(CDataStream&& key)
507 : {
508 0 : if (!m_database.m_db) return false;
509 0 : assert(m_read_stmt);
510 :
511 : // Bind: leftmost parameter in statement is index 1
512 0 : if (!BindBlobToStatement(m_read_stmt, 1, key, "key")) return false;
513 0 : int res = sqlite3_step(m_read_stmt);
514 0 : sqlite3_clear_bindings(m_read_stmt);
515 0 : sqlite3_reset(m_read_stmt);
516 0 : return res == SQLITE_ROW;
517 0 : }
518 :
519 886 : bool SQLiteBatch::StartCursor()
520 : {
521 886 : assert(!m_cursor_init);
522 886 : if (!m_database.m_db) return false;
523 886 : m_cursor_init = true;
524 886 : return true;
525 886 : }
526 :
527 29722 : bool SQLiteBatch::ReadAtCursor(CDataStream& key, CDataStream& value, bool& complete)
528 : {
529 29722 : complete = false;
530 :
531 29722 : if (!m_cursor_init) return false;
532 :
533 29722 : int res = sqlite3_step(m_cursor_stmt);
534 29722 : if (res == SQLITE_DONE) {
535 886 : complete = true;
536 886 : return true;
537 : }
538 28836 : if (res != SQLITE_ROW) {
539 0 : LogPrintf("SQLiteBatch::ReadAtCursor: Unable to execute cursor step: %s\n", sqlite3_errstr(res));
540 0 : return false;
541 : }
542 :
543 28836 : key.clear();
544 28836 : value.clear();
545 :
546 : // Leftmost column in result is index 0
547 28836 : key.write(SpanFromBlob(m_cursor_stmt, 0));
548 28836 : value.write(SpanFromBlob(m_cursor_stmt, 1));
549 28836 : return true;
550 29722 : }
551 :
552 886 : void SQLiteBatch::CloseCursor()
553 : {
554 886 : sqlite3_reset(m_cursor_stmt);
555 886 : m_cursor_init = false;
556 886 : }
557 :
558 129 : bool SQLiteBatch::TxnBegin()
559 : {
560 129 : if (!m_database.m_db || sqlite3_get_autocommit(m_database.m_db) == 0) return false;
561 129 : int res = sqlite3_exec(m_database.m_db, "BEGIN TRANSACTION", nullptr, nullptr, nullptr);
562 129 : if (res != SQLITE_OK) {
563 0 : LogPrintf("SQLiteBatch: Failed to begin the transaction\n");
564 0 : } else {
565 129 : m_txn_started = true;
566 : }
567 129 : return res == SQLITE_OK;
568 129 : }
569 :
570 119 : bool SQLiteBatch::TxnCommit()
571 : {
572 : // Refuse to operate on a transaction this batch does not own, so a nested
573 : // batch whose TxnBegin() failed cannot accidentally commit an outer
574 : // transaction started by a different batch on the shared connection.
575 119 : if (!m_txn_started) return false;
576 119 : if (!m_database.m_db || sqlite3_get_autocommit(m_database.m_db) != 0) return false;
577 119 : int res = sqlite3_exec(m_database.m_db, "COMMIT TRANSACTION", nullptr, nullptr, nullptr);
578 119 : if (res != SQLITE_OK) {
579 0 : LogPrintf("SQLiteBatch: Failed to commit the transaction\n");
580 0 : } else {
581 119 : m_txn_started = false;
582 : }
583 119 : return res == SQLITE_OK;
584 119 : }
585 :
586 10 : bool SQLiteBatch::TxnAbort()
587 : {
588 : // Refuse to operate on a transaction this batch does not own; see TxnCommit.
589 10 : if (!m_txn_started) return false;
590 10 : if (!m_database.m_db || sqlite3_get_autocommit(m_database.m_db) != 0) return false;
591 10 : int res = sqlite3_exec(m_database.m_db, "ROLLBACK TRANSACTION", nullptr, nullptr, nullptr);
592 10 : if (res != SQLITE_OK) {
593 0 : LogPrintf("SQLiteBatch: Failed to abort the transaction\n");
594 0 : } else {
595 10 : m_txn_started = false;
596 : }
597 10 : return res == SQLITE_OK;
598 10 : }
599 :
600 1041 : std::unique_ptr<SQLiteDatabase> MakeSQLiteDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error)
601 : {
602 : try {
603 1041 : fs::path data_file = SQLiteDataFile(path);
604 1041 : auto db = std::make_unique<SQLiteDatabase>(data_file.parent_path(), data_file, options);
605 1031 : if (options.verify && !db->Verify(error)) {
606 0 : status = DatabaseStatus::FAILED_VERIFY;
607 0 : return nullptr;
608 : }
609 1031 : status = DatabaseStatus::SUCCESS;
610 1031 : return db;
611 1041 : } catch (const std::runtime_error& e) {
612 10 : status = DatabaseStatus::FAILED_LOAD;
613 10 : error = Untranslated(e.what());
614 10 : return nullptr;
615 10 : }
616 1051 : }
617 :
618 1077 : std::string SQLiteDatabaseVersion()
619 : {
620 1077 : return std::string(sqlite3_libversion());
621 : }
622 : } // namespace wallet
|