LCOV - code coverage report
Current view: top level - src/wallet - sqlite.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 293 399 73.4 %
Date: 2020-09-26 01:30:44 Functions: 34 37 91.9 %

          Line data    Source code
       1             : // Copyright (c) 2020 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 <util/memory.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             : static const char* DATABASE_FILENAME = "wallet.dat";
      20             : 
      21       13037 : static const int32_t WALLET_SCHEMA_VERSION = 0;
      22       13037 : 
      23             : std::atomic<int> g_dbs_open{0};
      24             : 
      25           0 : static void ErrorLogCallback(void* arg, int code, const char* msg)
      26             : {
      27           0 :     assert(arg == nullptr); // That's what we tell it to do during the setup
      28           0 :     LogPrintf("SQLite Error. Code: %d. Message: %s\n", code, msg);
      29           0 : }
      30             : 
      31         200 : SQLiteDatabase::SQLiteDatabase(const fs::path& dir_path, const fs::path& file_path, bool mock) :
      32         200 :     WalletDatabase(), m_mock(mock), m_dir_path(dir_path.string()), m_file_path(file_path.string())
      33         300 : {
      34         100 :     LogPrintf("Using SQLite Version %s\n", SQLiteDatabaseVersion());
      35         100 :     LogPrintf("Using wallet %s\n", m_dir_path);
      36             : 
      37         100 :     if (g_dbs_open.fetch_add(1) == 0) {
      38             :         // Setup logging
      39          67 :         int ret = sqlite3_config(SQLITE_CONFIG_LOG, ErrorLogCallback, nullptr);
      40          67 :         if (ret != SQLITE_OK) {
      41           0 :             throw std::runtime_error(strprintf("SQLiteDatabase: Failed to setup error log: %s\n", sqlite3_errstr(ret)));
      42             :         }
      43             :         // Force serialized threading mode
      44          67 :         ret = sqlite3_config(SQLITE_CONFIG_SERIALIZED);
      45          67 :         if (ret != SQLITE_OK) {
      46           0 :             throw std::runtime_error(strprintf("SQLiteDatabase: Failed to configure serialized threading mode: %s\n", sqlite3_errstr(ret)));
      47             :         }
      48          67 :     }
      49         100 :     int ret = sqlite3_initialize(); // This is a no-op if sqlite3 is already initialized
      50         100 :     if (ret != SQLITE_OK) {
      51           0 :         throw std::runtime_error(strprintf("SQLiteDatabase: Failed to initialize SQLite: %s\n", sqlite3_errstr(ret)));
      52             :     }
      53         200 : }
      54             : 
      55       13072 : bool SQLiteDatabase::PrepareDirectory() const
      56             : {
      57       13072 :     if (m_mock) return true;
      58             :     // Try to create the directory containing the wallet file and lock it
      59       13072 :     TryCreateDirectories(m_dir_path);
      60       13072 :     if (!LockDirectory(m_dir_path, ".walletlock")) {
      61           0 :         LogPrintf("Cannot obtain a lock on wallet directory %s. Another instance of bitcoin may be using it.\n", m_dir_path);
      62           0 :         return false;
      63             :     }
      64       13072 :     return true;
      65       13072 : }
      66             : 
      67       13037 : void SQLiteDatabase::SetupSQLStatements()
      68             : {
      69       13037 :     std::string read_sql = "SELECT value FROM main WHERE key = ?";
      70       13037 :     std::string insert_sql = "INSERT INTO main VALUES(?, ?)";
      71       13037 :     std::string overwrite_sql = "INSERT OR REPLACE INTO main VALUES(?, ?)";
      72       13037 :     std::string delete_sql = "DELETE FROM main WHERE key = ?";
      73       13037 :     std::string cursor_sql = "SELECT key, value FROM main";
      74             : 
      75             :     int res;
      76       13037 :     if (!m_read_stmt) {
      77          78 :         if ((res = sqlite3_prepare_v2(m_db, read_sql.c_str(), -1, &m_read_stmt, nullptr)) != SQLITE_OK) {
      78           0 :             throw std::runtime_error(strprintf("SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
      79             :         }
      80             :     }
      81       13037 :     if (!m_insert_stmt) {
      82          78 :         if ((res = sqlite3_prepare_v2(m_db, insert_sql.c_str(), -1, &m_insert_stmt, nullptr)) != SQLITE_OK) {
      83           0 :             throw std::runtime_error(strprintf("SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
      84             :         }
      85             :     }
      86       13037 :     if (!m_overwrite_stmt) {
      87          78 :         if ((res = sqlite3_prepare_v2(m_db, overwrite_sql.c_str(), -1, &m_overwrite_stmt, nullptr)) != SQLITE_OK) {
      88           0 :             throw std::runtime_error(strprintf("SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
      89             :         }
      90             :     }
      91       13037 :     if (!m_delete_stmt) {
      92          78 :         if ((res = sqlite3_prepare_v2(m_db, delete_sql.c_str(), -1, &m_delete_stmt, nullptr)) != SQLITE_OK) {
      93           0 :             throw std::runtime_error(strprintf("SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
      94             :         }
      95             :     }
      96       13037 :     if (!m_cursor_stmt) {
      97          78 :         if ((res = sqlite3_prepare_v2(m_db, cursor_sql.c_str(), -1, &m_cursor_stmt, nullptr)) != SQLITE_OK) {
      98           0 :             throw std::runtime_error(strprintf("SQLiteDatabase: Failed to setup SQL statements : %s\n", sqlite3_errstr(res)));
      99             :         }
     100             :     }
     101       13037 : }
     102             : 
     103         300 : SQLiteDatabase::~SQLiteDatabase()
     104         400 : {
     105         100 :     Close();
     106         200 :     if (g_dbs_open.fetch_sub(1) == 1) {
     107         167 :         int ret = sqlite3_shutdown();
     108         167 :         if (ret != SQLITE_OK) {
     109         100 :             LogPrintf("SQLiteDatabase: Failed to shutdown SQLite: %s\n", sqlite3_errstr(ret));
     110         100 :         }
     111          67 :     }
     112         300 : }
     113             : 
     114          35 : bool SQLiteDatabase::Verify(bilingual_str& error)
     115             : {
     116          35 :     if (!PrepareDirectory()) return false;
     117             : 
     118          35 :     sqlite3* db = nullptr;
     119          35 :     int ret = sqlite3_open_v2(m_file_path.c_str(), &db, SQLITE_OPEN_READONLY, nullptr);
     120          35 :     if (ret == SQLITE_NOTFOUND) {
     121           0 :         sqlite3_close(db);
     122           0 :         return true; // Return true if the file doesn't exist
     123          35 :     } else if (ret != SQLITE_OK) {
     124           0 :         sqlite3_close(db);
     125           0 :         error = strprintf(_("SQLiteDatabase: Failed to verify database: %s"), sqlite3_errstr(ret));
     126           0 :         return false;
     127             :     }
     128             : 
     129             :     // Check the application ID matches our network magic
     130          35 :     sqlite3_stmt* app_id_stmt;
     131          35 :     ret = sqlite3_prepare_v2(db, "PRAGMA application_id", -1, &app_id_stmt, nullptr);
     132          35 :     if (ret != SQLITE_OK) {
     133           0 :         sqlite3_finalize(app_id_stmt);
     134           0 :         sqlite3_close(db);
     135           0 :         error = strprintf(_("SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s"), sqlite3_errstr(ret));
     136           0 :         return false;
     137             :     }
     138          35 :     ret = sqlite3_step(app_id_stmt);
     139          35 :     if (ret != SQLITE_ROW) {
     140           0 :         sqlite3_finalize(app_id_stmt);
     141           0 :         sqlite3_close(db);
     142           0 :         error = strprintf(_("SQLiteDatabase: Failed to fetch the application id: %s"), sqlite3_errstr(ret));
     143           0 :         return false;
     144             :     }
     145          35 :     uint32_t app_id = (uint32_t)sqlite3_column_int(app_id_stmt, 0);
     146          35 :     sqlite3_finalize(app_id_stmt);
     147          35 :     uint32_t net_magic = ReadBE32(Params().MessageStart());
     148          35 :     if (app_id != net_magic) {
     149           0 :         sqlite3_close(db);
     150           0 :         error = strprintf(_("SQLiteDatabase: Unexpected application id. Expected %u, got %u"), net_magic, app_id);
     151           0 :         return false;
     152             :     }
     153             : 
     154             :     // Check our schema version
     155          35 :     sqlite3_stmt* user_ver_stmt;
     156          35 :     ret = sqlite3_prepare_v2(db, "PRAGMA user_version", -1, &user_ver_stmt, nullptr);
     157          35 :     if (ret != SQLITE_OK) {
     158           0 :         sqlite3_finalize(user_ver_stmt);
     159           0 :         sqlite3_close(db);
     160           0 :         error = strprintf(_("SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s"), sqlite3_errstr(ret));
     161           0 :         return false;
     162             :     }
     163          35 :     ret = sqlite3_step(user_ver_stmt);
     164          35 :     if (ret != SQLITE_ROW) {
     165           0 :         sqlite3_finalize(user_ver_stmt);
     166           0 :         sqlite3_close(db);
     167           0 :         error = strprintf(_("SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s"), sqlite3_errstr(ret));
     168           0 :         return false;
     169             :     }
     170          35 :     int32_t user_ver = sqlite3_column_int(user_ver_stmt, 0);
     171          35 :     sqlite3_finalize(user_ver_stmt);
     172          35 :     if (user_ver != WALLET_SCHEMA_VERSION) {
     173           0 :         sqlite3_close(db);
     174           0 :         error = strprintf(_("SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported"), user_ver, WALLET_SCHEMA_VERSION);
     175           0 :         return false;
     176             :     }
     177             : 
     178          35 :     sqlite3_stmt* stmt;
     179          35 :     ret = sqlite3_prepare_v2(db, "PRAGMA integrity_check", -1, &stmt, nullptr);
     180          35 :     if (ret != SQLITE_OK) {
     181           0 :         sqlite3_finalize(stmt);
     182           0 :         sqlite3_close(db);
     183           0 :         error = strprintf(_("SQLiteDatabase: Failed to verify database: %s"), sqlite3_errstr(ret));
     184           0 :         return false;
     185             :     }
     186             :     while (true) {
     187          70 :         ret = sqlite3_step(stmt);
     188          70 :         if (ret == SQLITE_DONE) {
     189             :             break;
     190          35 :         } else if (ret != SQLITE_ROW) {
     191           0 :             error = strprintf(_("SQLiteDatabase: Failed to verify database: %s"), sqlite3_errstr(ret));
     192           0 :             break;
     193             :         }
     194          35 :         const char* msg = (const char*)sqlite3_column_text(stmt, 0);
     195          35 :         if (!msg) {
     196           0 :             error = strprintf(_("SQLiteDatabase: Failed to verify database: %s"), sqlite3_errstr(ret));
     197           0 :             break;
     198             :         }
     199          35 :         std::string str_msg(msg);
     200          35 :         if (str_msg == "ok") {
     201          35 :             continue;
     202             :         }
     203           0 :         error += Untranslated("\n" + str_msg);
     204          35 :     }
     205          35 :     sqlite3_finalize(stmt);
     206          35 :     sqlite3_close(db);
     207          35 :     return error.original.empty();
     208          35 : }
     209             : 
     210       13037 : void SQLiteDatabase::Open(const char* mode)
     211             : {
     212       13037 :     if (!PrepareDirectory()) {
     213           0 :         throw std::runtime_error("Cannot obtain a lock on wallet directory");
     214             :     }
     215             : 
     216       13037 :     bool read_only = (!strchr(mode, '+') && !strchr(mode, 'w'));
     217             : 
     218       13037 :     bool create = strchr(mode, 'c') != nullptr;
     219             :     int flags;
     220       13037 :     if (read_only) {
     221             :         flags = SQLITE_OPEN_READONLY;
     222           0 :     } else {
     223             :         flags = SQLITE_OPEN_READWRITE;
     224             :     }
     225       13037 :     if (create) {
     226          78 :         flags |= SQLITE_OPEN_CREATE;
     227          78 :     }
     228       13037 :     if (m_mock) {
     229           0 :         flags |= SQLITE_OPEN_MEMORY; // In memory database for mock db
     230           0 :     }
     231             : 
     232       13037 :     if (m_db == nullptr) {
     233          78 :         sqlite3* db = nullptr;
     234          78 :         int ret = sqlite3_open_v2(m_file_path.c_str(), &db, flags, nullptr);
     235          78 :         if (ret != SQLITE_OK) {
     236           0 :             throw std::runtime_error(strprintf("SQLiteDatabase: Failed to open database: %s\n", sqlite3_errstr(ret)));
     237             :         }
     238             :         // TODO: Maybe(?) Check the file wasn't copied and a duplicate opened
     239             : 
     240          78 :         if (create) {
     241             :             bool table_exists;
     242             :             // Check that the main table exists
     243          78 :             sqlite3_stmt* check_main_stmt;
     244          78 :             std::string check_main = "SELECT name FROM sqlite_master WHERE type='table' AND name='main'";
     245          78 :             ret = sqlite3_prepare_v2(db, check_main.c_str(), -1, &check_main_stmt, nullptr);
     246          78 :             if (ret != SQLITE_OK) {
     247           0 :                 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to prepare statement to check table existence: %s\n", sqlite3_errstr(ret)));
     248             :             }
     249          78 :             ret = sqlite3_step(check_main_stmt);
     250          78 :             if (sqlite3_finalize(check_main_stmt) != SQLITE_OK) {
     251           0 :                 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to finalize statement checking table existence: %s\n", sqlite3_errstr(ret)));
     252             :             }
     253          78 :             if (ret == SQLITE_DONE) {
     254             :                 table_exists = false;
     255          78 :             } else if (ret == SQLITE_ROW) {
     256             :                 table_exists = true;
     257             :             } else {
     258           0 :                 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to execute statement to check table existence: %s\n", sqlite3_errstr(ret)));
     259             :             }
     260             : 
     261          78 :             if (!table_exists) {
     262             :                 // Make the table for our key-value pairs
     263          43 :                 std::string create_stmt = "CREATE TABLE main(key BLOB PRIMARY KEY, value BLOB)";
     264          43 :                 ret = sqlite3_exec(db, create_stmt.c_str(), nullptr, nullptr, nullptr);
     265          43 :                 if (ret != SQLITE_OK) {
     266           0 :                     throw std::runtime_error(strprintf("SQLiteDatabase: Failed to create new database: %s\n", sqlite3_errstr(ret)));
     267             :                 }
     268          43 :             }
     269             : 
     270             :             // Enable fullfysnc for the platforms that use it
     271          78 :             std::string fullfsync_stmt = "PRAGMA fullfsync = true";
     272          78 :             ret = sqlite3_exec(db, fullfsync_stmt.c_str(), nullptr, nullptr, nullptr);
     273          78 :             if (ret != SQLITE_OK) {
     274           0 :                 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to enable fullfsync: %s\n", sqlite3_errstr(ret)));
     275             :             }
     276             : 
     277             :             // Set the application id
     278          78 :             uint32_t app_id = ReadBE32(Params().MessageStart());
     279          78 :             std::string set_app_id = strprintf("PRAGMA application_id = %d", (int32_t)app_id);
     280          78 :             ret = sqlite3_exec(db, set_app_id.c_str(), nullptr, nullptr, nullptr);
     281          78 :             if (ret != SQLITE_OK) {
     282           0 :                 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to set the application id: %s\n", sqlite3_errstr(ret)));
     283             :             }
     284             : 
     285             :             // Set the user version
     286          78 :             std::string set_user_ver = strprintf("PRAGMA user_version = %d", WALLET_SCHEMA_VERSION);
     287          78 :             ret = sqlite3_exec(db, set_user_ver.c_str(), nullptr, nullptr, nullptr);
     288          78 :             if (ret != SQLITE_OK) {
     289           0 :                 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to set the wallet schema version: %s\n", sqlite3_errstr(ret)));
     290             :             }
     291          78 :         }
     292             : 
     293          78 :         m_db = db;
     294       13037 :     } else if (!read_only && sqlite3_db_readonly(m_db, "main") != 0) {
     295           0 :         throw std::runtime_error(strprintf("SQLiteDatabase: SQLiteBatch requested read-write permission but database only has readonly"));
     296             :     }
     297       13037 :     SetupSQLStatements();
     298       13037 : }
     299             : 
     300           4 : bool SQLiteDatabase::Rewrite(const char* skip)
     301             : {
     302           4 :     while (true) {
     303           4 :         if (m_refcount == 0) {
     304             :             break;
     305             :         }
     306           0 :         UninterruptibleSleep(std::chrono::milliseconds{100});
     307             :     }
     308             : 
     309             :     // Rewrite the database using the VACUUM command: https://sqlite.org/lang_vacuum.html
     310           4 :     int ret = sqlite3_exec(m_db, "VACUUM", nullptr, nullptr, nullptr);
     311           4 :     return ret == SQLITE_OK;
     312             : }
     313             : 
     314          95 : bool SQLiteDatabase::PeriodicFlush()
     315             : {
     316          95 :     return true;
     317             : }
     318             : 
     319           1 : bool SQLiteDatabase::Backup(const std::string& dest) const
     320             : {
     321           1 :     sqlite3* db_copy;
     322           1 :     int res = sqlite3_open(dest.c_str(), &db_copy);
     323           1 :     if (res != SQLITE_OK) {
     324           0 :         sqlite3_close(db_copy);
     325           0 :         return false;
     326             :     }
     327           1 :     sqlite3_backup* backup = sqlite3_backup_init(db_copy, "main", m_db, "main");
     328           1 :     if (!backup) {
     329           0 :         sqlite3_backup_finish(backup);
     330           0 :         sqlite3_close(db_copy);
     331           0 :         return false;
     332             :     }
     333             :     // Copy all of the pages using -1
     334           1 :     res = sqlite3_backup_step(backup, -1);
     335           1 :     if (res != SQLITE_DONE) {
     336             :         sqlite3_backup_finish(backup);
     337           0 :         sqlite3_close(db_copy);
     338           0 :         return false;
     339             :     }
     340             :     res = sqlite3_backup_finish(backup);
     341           1 :     sqlite3_close(db_copy);
     342           1 :     return res == SQLITE_OK;
     343           1 : }
     344             : 
     345         156 : void SQLiteDatabase::Close()
     346             : {
     347         156 :     if (!m_db) return;
     348             : 
     349          78 :     assert(m_refcount == 0);
     350             : 
     351             :     // Free all of the prepared statements
     352          78 :     sqlite3_finalize(m_read_stmt);
     353          78 :     sqlite3_finalize(m_insert_stmt);
     354          78 :     sqlite3_finalize(m_overwrite_stmt);
     355          78 :     sqlite3_finalize(m_delete_stmt);
     356          78 :     sqlite3_finalize(m_cursor_stmt);
     357             : 
     358          78 :     int res = sqlite3_close(m_db);
     359          78 :     if (res != SQLITE_OK) {
     360           0 :         throw std::runtime_error(strprintf("SQLiteDatabase: Failed to close database: %s\n", sqlite3_errstr(res)));
     361             :     }
     362          78 :     m_db = nullptr;
     363             : 
     364          78 :     UnlockDirectory(m_dir_path, ".walletlock");
     365         156 : }
     366             : 
     367         134 : void SQLiteDatabase::Flush() {}
     368             : 
     369           4 : void SQLiteDatabase::ReloadDbEnv() {}
     370             : 
     371       13037 : void SQLiteDatabase::RemoveRef()
     372             : {
     373       13037 :     m_refcount--;
     374       13037 : }
     375             : 
     376       13037 : void SQLiteDatabase::AddRef()
     377             : {
     378       13037 :     m_refcount++;
     379       13037 : }
     380             : 
     381       13037 : std::unique_ptr<DatabaseBatch> SQLiteDatabase::MakeBatch(const char* mode, bool flush_on_close)
     382             : {
     383             :     // We ignore flush_on_close because we don't do manual flushing for SQLite
     384       13037 :     return MakeUnique<SQLiteBatch>(*this, mode);
     385             : }
     386             : 
     387       26074 : SQLiteBatch::SQLiteBatch(SQLiteDatabase& database, const char* mode)
     388       13037 :     : m_database(database)
     389       26074 : {
     390       13037 :     m_read_only = (!strchr(mode, '+') && !strchr(mode, 'w'));
     391       13037 :     m_database.AddRef();
     392       13037 :     m_database.Open(mode);
     393       26074 : }
     394             : 
     395           6 : void SQLiteBatch::Flush() {}
     396             : 
     397       13037 : void SQLiteBatch::Close()
     398             : {
     399       13037 :     if (m_database.m_db && sqlite3_get_autocommit(m_database.m_db) == 0) {
     400           0 :         TxnAbort();
     401           0 :     }
     402       13037 :     m_database.RemoveRef();
     403       13037 : }
     404             : 
     405         304 : bool SQLiteBatch::ReadKey(CDataStream&& key, CDataStream& value)
     406             : {
     407         304 :     if (!m_database.m_db) return false;
     408         304 :     assert(m_database.m_read_stmt);
     409             : 
     410             :     // Bind: leftmost parameter in statement is index 1
     411         304 :     int res = sqlite3_bind_blob(m_database.m_read_stmt, 1, key.data(), key.size(), SQLITE_STATIC);
     412         304 :     if (res != SQLITE_OK) {
     413           0 :         sqlite3_clear_bindings(m_database.m_read_stmt);
     414           0 :         sqlite3_reset(m_database.m_read_stmt);
     415           0 :         return false;
     416             :     }
     417         304 :     res = sqlite3_step(m_database.m_read_stmt);
     418         304 :     if (res != SQLITE_ROW) {
     419         121 :         sqlite3_clear_bindings(m_database.m_read_stmt);
     420         121 :         sqlite3_reset(m_database.m_read_stmt);
     421         121 :         return false;
     422             :     }
     423             :     // Leftmost column in result is index 0
     424         183 :     const char* data = (const char*)sqlite3_column_blob(m_database.m_read_stmt, 0);
     425         183 :     int data_size = sqlite3_column_bytes(m_database.m_read_stmt, 0);
     426         183 :     value.write(data, data_size);
     427             : 
     428         183 :     sqlite3_clear_bindings(m_database.m_read_stmt);
     429         183 :     sqlite3_reset(m_database.m_read_stmt);
     430             :     return true;
     431         304 : }
     432             : 
     433       16449 : bool SQLiteBatch::WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite)
     434             : {
     435       16449 :     if (!m_database.m_db) return false;
     436       16449 :     if (m_read_only) assert(!"Write called on database in read-only mode");
     437       16449 :     assert(m_database.m_insert_stmt && m_database.m_overwrite_stmt);
     438             : 
     439             :     sqlite3_stmt* stmt;
     440       16449 :     if (overwrite) {
     441       16174 :         stmt = m_database.m_overwrite_stmt;
     442       16174 :     } else {
     443         275 :         stmt = m_database.m_insert_stmt;
     444             :     }
     445             : 
     446             :     // Bind: leftmost parameter in statement is index 1
     447             :     // Insert index 1 is key, 2 is value
     448       16449 :     int res = sqlite3_bind_blob(stmt, 1, key.data(), key.size(), SQLITE_STATIC);
     449       16449 :     if (res != SQLITE_OK) {
     450           0 :         sqlite3_clear_bindings(stmt);
     451           0 :         sqlite3_reset(stmt);
     452           0 :         return false;
     453             :     }
     454       16449 :     res = sqlite3_bind_blob(stmt, 2, value.data(), value.size(), SQLITE_STATIC);
     455       16449 :     if (res != SQLITE_OK) {
     456           0 :         sqlite3_clear_bindings(stmt);
     457           0 :         sqlite3_reset(stmt);
     458           0 :         return false;
     459             :     }
     460             : 
     461             :     // Execute
     462       16449 :     res = sqlite3_step(stmt);
     463       16449 :     sqlite3_clear_bindings(stmt);
     464       16449 :     sqlite3_reset(stmt);
     465       16449 :     return res == SQLITE_DONE;
     466       16449 : }
     467             : 
     468          51 : bool SQLiteBatch::EraseKey(CDataStream&& key)
     469             : {
     470          51 :     if (!m_database.m_db) return false;
     471          51 :     if (m_read_only) assert(!"Erase called on database in read-only mode");
     472          51 :     assert(m_database.m_delete_stmt);
     473             : 
     474             :     // Bind: leftmost parameter in statement is index 1
     475          51 :     int res = sqlite3_bind_blob(m_database.m_delete_stmt, 1, key.data(), key.size(), SQLITE_STATIC);
     476          51 :     if (res != SQLITE_OK) {
     477           0 :         sqlite3_clear_bindings(m_database.m_delete_stmt);
     478           0 :         sqlite3_reset(m_database.m_delete_stmt);
     479           0 :         return false;
     480             :     }
     481             : 
     482             :     // Execute
     483          51 :     res = sqlite3_step(m_database.m_delete_stmt);
     484          51 :     sqlite3_clear_bindings(m_database.m_delete_stmt);
     485          51 :     sqlite3_reset(m_database.m_delete_stmt);
     486          51 :     return res == SQLITE_DONE;
     487          51 : }
     488             : 
     489           0 : bool SQLiteBatch::HasKey(CDataStream&& key)
     490             : {
     491           0 :     if (!m_database.m_db) return false;
     492           0 :     assert(m_database.m_read_stmt);
     493             : 
     494             :     // Bind: leftmost parameter in statement is index 1
     495             :     bool ret = false;
     496           0 :     int res = sqlite3_bind_blob(m_database.m_read_stmt, 1, key.data(), key.size(), SQLITE_STATIC);
     497           0 :     if (res == SQLITE_OK) {
     498           0 :         res = sqlite3_step(m_database.m_read_stmt);
     499           0 :         if (res == SQLITE_ROW) {
     500             :             ret = true;
     501           0 :         }
     502             :     }
     503             : 
     504           0 :     sqlite3_clear_bindings(m_database.m_read_stmt);
     505           0 :     sqlite3_reset(m_database.m_read_stmt);
     506           0 :     return ret;
     507           0 : }
     508             : 
     509          78 : bool SQLiteBatch::StartCursor()
     510             : {
     511          78 :     assert(!m_cursor_init);
     512          78 :     if (!m_database.m_db) return false;
     513          78 :     m_cursor_init = true;
     514          78 :     return true;
     515          78 : }
     516             : 
     517        2906 : bool SQLiteBatch::ReadAtCursor(CDataStream& key, CDataStream& value, bool& complete)
     518             : {
     519        2906 :     complete = false;
     520             : 
     521        2906 :     if (!m_cursor_init) return false;
     522             : 
     523        2906 :     int res = sqlite3_step(m_database.m_cursor_stmt);
     524        2906 :     if (res == SQLITE_DONE) {
     525          78 :         complete = true;
     526          78 :         return true;
     527        2828 :     } else if (res != SQLITE_ROW) {
     528           0 :         return false;
     529             :     }
     530             : 
     531             :     // Leftmost column in result is index 0
     532        2828 :     const char* key_data = (const char*)sqlite3_column_blob(m_database.m_cursor_stmt, 0);
     533        2828 :     int key_data_size = sqlite3_column_bytes(m_database.m_cursor_stmt, 0);
     534        2828 :     key.write(key_data, key_data_size);
     535        2828 :     const char* value_data = (const char*)sqlite3_column_blob(m_database.m_cursor_stmt, 1);
     536        2828 :     int value_data_size = sqlite3_column_bytes(m_database.m_cursor_stmt, 1);
     537        2828 :     value.write(value_data, value_data_size);
     538             :     return true;
     539        2906 : }
     540             : 
     541          78 : void SQLiteBatch::CloseCursor()
     542             : {
     543          78 :     sqlite3_reset(m_database.m_cursor_stmt);
     544          78 :     m_cursor_init = false;
     545          78 : }
     546             : 
     547           4 : bool SQLiteBatch::TxnBegin()
     548             : {
     549           4 :     if (!m_database.m_db || sqlite3_get_autocommit(m_database.m_db) == 0) return false;
     550           4 :     int res = sqlite3_exec(m_database.m_db, "BEGIN TRANSACTION", nullptr, nullptr, nullptr);
     551           4 :     return res == SQLITE_OK;
     552           4 : }
     553             : 
     554           4 : bool SQLiteBatch::TxnCommit()
     555             : {
     556           4 :     if (!m_database.m_db || sqlite3_get_autocommit(m_database.m_db) != 0) return false;
     557           4 :     int res = sqlite3_exec(m_database.m_db, "COMMIT TRANSACTION", nullptr, nullptr, nullptr);
     558           4 :     return res == SQLITE_OK;
     559           4 : }
     560             : 
     561           0 : bool SQLiteBatch::TxnAbort()
     562             : {
     563           0 :     if (!m_database.m_db || sqlite3_get_autocommit(m_database.m_db) != 0) return false;
     564           0 :     int res = sqlite3_exec(m_database.m_db, "ROLLBACK TRANSACTION", nullptr, nullptr, nullptr);
     565           0 :     return res == SQLITE_OK;
     566           0 : }
     567             : 
     568         959 : bool ExistsSQLiteDatabase(const fs::path& path)
     569             : {
     570         959 :     fs::path file = path / DATABASE_FILENAME;
     571         959 :     return fs::symlink_status(file).type() == fs::regular_file && IsSQLiteFile(file);
     572         959 : }
     573             : 
     574         100 : std::unique_ptr<SQLiteDatabase> MakeSQLiteDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error)
     575             : {
     576         100 :     fs::path file = path / DATABASE_FILENAME;
     577         100 :     auto db = MakeUnique<SQLiteDatabase>(path, file);
     578         100 :     if (options.verify && fs::is_regular_file(file) && !db->Verify(error)) {
     579           0 :         status = DatabaseStatus::FAILED_VERIFY;
     580           0 :         return nullptr;
     581             :     }
     582         100 :     return db;
     583         100 : }
     584             : 
     585         100 : std::string SQLiteDatabaseVersion()
     586             : {
     587         100 :     return std::string(sqlite3_libversion());
     588             : }
     589             : 
     590         500 : bool IsSQLiteFile(const fs::path& path)
     591             : {
     592         500 :     if (!fs::exists(path)) return false;
     593             : 
     594             :     // A SQLite Database file is at least 512 bytes.
     595         500 :     boost::system::error_code ec;
     596         500 :     auto size = fs::file_size(path, ec);
     597         500 :     if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), path.string());
     598         500 :     if (size < 512) return false;
     599             : 
     600         500 :     fsbridge::ifstream file(path, std::ios::binary);
     601         500 :     if (!file.is_open()) return false;
     602             : 
     603             :     // Magic is at beginning and is 16 bytes long
     604         500 :     char magic[16];
     605         500 :     file.read(magic, 16);
     606             : 
     607             :     // Application id is at offset 68 and 4 bytes long
     608         500 :     file.seekg(68, std::ios::beg);
     609         500 :     char app_id[4];
     610         500 :     file.read(app_id, 4);
     611             : 
     612         500 :     file.close();
     613             : 
     614             :     // Check the magic, see https://sqlite.org/fileformat2.html
     615         500 :     std::string magic_str(magic);
     616         500 :     if (magic_str != std::string("SQLite format 3")) {
     617         443 :         return false;
     618             :     }
     619             : 
     620             :     // Check the application id matches our network magic
     621          57 :     return memcmp(Params().MessageStart(), app_id, 4) == 0;
     622         500 : }

Generated by: LCOV version 1.15