Skip to content
Bitcoin Roots

v30.3-roots.1 · Commit 4: [PATCH 04/68] fix(wallet): preserve Roots database hardening on Core 30.3

src/wallet/sqlite.cpp

Before: src/wallet/sqlite.cpp · After: src/wallet/sqlite.cpp

File metadata
index 0940cbac3b1e2e6bbd26839137475bb0b620086e..a3f3dca63fd9ffbd1785f8d62549428d5a71a7c0 100644

Download original patch · Release notes

Diff rows 1–156 of 156. Line numbers refer to the original before/after files.

+ Added− RemovedUnmarked lines are context.

Scroll the code area horizontally to read long lines. The two line-number columns refer to before and after.

src/wallet/sqlite.cpp CHANGED
@@ -40,7 +40,7 @@ static void ErrorLogCallback(void* arg, int code, const char* msg)
40
40
  // invoked."
41
41
  // Assert that this is the case:
42
42
  assert(arg == nullptr);
43
- LogPrintf("SQLite Error. Code: %d. Message: %s\n", code, msg);
43
+ LogWarning("SQLite Error. Code: %d. Message: %s", code, msg);
44
44
  }
45
45
 
46
46
  static int TraceSqlCallback(unsigned code, void* context, void* param1, void* param2)
@@ -69,7 +69,7 @@ static bool BindBlobToStatement(sqlite3_stmt* stmt,
69
69
  // instead of the empty blob value X'', which would mess up SQL comparisons.
70
70
  int res = sqlite3_bind_blob(stmt, index, blob.data() ? static_cast<const void*>(blob.data()) : "", blob.size(), SQLITE_STATIC);
71
71
  if (res != SQLITE_OK) {
72
- LogPrintf("Unable to bind %s to statement: %s\n", description, sqlite3_errstr(res));
72
+ LogWarning("Unable to bind %s to statement: %s", description, sqlite3_errstr(res));
73
73
  sqlite3_clear_bindings(stmt);
74
74
  sqlite3_reset(stmt);
75
75
  return false;
@@ -182,7 +182,7 @@ void SQLiteDatabase::Cleanup() noexcept
182
182
  if (--g_sqlite_count == 0) {
183
183
  int ret = sqlite3_shutdown();
184
184
  if (ret != SQLITE_OK) {
185
- LogPrintf("SQLiteDatabase: Failed to shutdown SQLite: %s\n", sqlite3_errstr(ret));
185
+ LogWarning("SQLiteDatabase: Failed to shutdown SQLite: %s", sqlite3_errstr(ret));
186
186
  }
187
187
  }
188
188
  }
@@ -254,7 +254,11 @@ void SQLiteDatabase::Open()
254
254
  if (m_db == nullptr) {
255
255
  if (!m_mock) {
256
256
  TryCreateDirectories(m_dir_path);
257
+ if (!IsDirWritable(m_dir_path)) {
258
+ throw std::runtime_error(strprintf("SQLiteDatabase: Failed to open database in directory '%s': directory is not writable", fs::PathToString(m_dir_path)));
259
+ }
257
260
  }
261
+
258
262
  int ret = sqlite3_open_v2(m_file_path.c_str(), &m_db, flags, nullptr);
259
263
  if (ret != SQLITE_OK) {
260
264
  throw std::runtime_error(strprintf("SQLiteDatabase: Failed to open database: %s\n", sqlite3_errstr(ret)));
@@ -267,7 +271,7 @@ void SQLiteDatabase::Open()
267
271
  if (LogAcceptCategory(BCLog::WALLETDB, BCLog::Level::Trace)) {
268
272
  ret = sqlite3_trace_v2(m_db, SQLITE_TRACE_STMT, TraceSqlCallback, this);
269
273
  if (ret != SQLITE_OK) {
270
- LogPrintf("Failed to enable SQL tracing for %s\n", Filename());
274
+ LogWarning("Failed to enable SQL tracing for %s", Filename());
271
275
  }
272
276
  }
273
277
  }
@@ -294,7 +298,7 @@ void SQLiteDatabase::Open()
294
298
 
295
299
  if (m_use_unsafe_sync) {
296
300
  // Use normal synchronous mode for the journal
297
- LogPrintf("WARNING SQLite is configured to not wait for data to be flushed to disk. Data loss and corruption may occur.\n");
301
+ LogWarning("SQLite is configured to not wait for data to be flushed to disk. Data loss and corruption may occur.");
298
302
  SetPragma(m_db, "synchronous", "OFF", "Failed to set synchronous mode to OFF");
299
303
  }
300
304
 
@@ -353,14 +357,14 @@ bool SQLiteDatabase::Backup(const std::string& dest) const
353
357
  }
354
358
  sqlite3_backup* backup = sqlite3_backup_init(db_copy, "main", m_db, "main");
355
359
  if (!backup) {
356
- LogPrintf("%s: Unable to begin backup: %s\n", __func__, sqlite3_errmsg(m_db));
360
+ LogWarning("Unable to begin sqlite backup: %s", sqlite3_errmsg(m_db));
357
361
  sqlite3_close(db_copy);
358
362
  return false;
359
363
  }
360
364
  // Specifying -1 will copy all of the pages
361
365
  res = sqlite3_backup_step(backup, -1);
362
366
  if (res != SQLITE_DONE) {
363
- LogPrintf("%s: Unable to backup: %s\n", __func__, sqlite3_errstr(res));
367
+ LogWarning("Unable to continue sqlite backup: %s", sqlite3_errstr(res));
364
368
  sqlite3_backup_finish(backup);
365
369
  sqlite3_close(db_copy);
366
370
  return false;
@@ -412,13 +416,13 @@ void SQLiteBatch::Close()
412
416
  // If we began a transaction, and it wasn't committed, abort the transaction in progress
413
417
  if (m_txn) {
414
418
  if (TxnAbort()) {
415
- LogPrintf("SQLiteBatch: Batch closed unexpectedly without the transaction being explicitly committed or aborted\n");
419
+ LogWarning("SQLiteBatch: Batch closed unexpectedly without the transaction being explicitly committed or aborted");
416
420
  } else {
417
421
  // If transaction cannot be aborted, it means there is a bug or there has been data corruption. Try to recover in this case
418
422
  // by closing and reopening the database. Closing the database should also ensure that any changes made since the transaction
419
423
  // was opened will be rolled back and future transactions can succeed without committing old data.
420
424
  force_conn_refresh = true;
421
- LogPrintf("SQLiteBatch: Batch closed and failed to abort transaction, resetting db connection..\n");
425
+ LogWarning("SQLiteBatch: Batch closed and failed to abort transaction, resetting db connection..");
422
426
  }
423
427
  }
424
428
 
@@ -434,7 +438,7 @@ void SQLiteBatch::Close()
434
438
  for (const auto& [stmt_prepared, stmt_description] : statements) {
435
439
  int res = sqlite3_finalize(*stmt_prepared);
436
440
  if (res != SQLITE_OK) {
437
- LogPrintf("SQLiteBatch: Batch closed but could not finalize %s statement: %s\n",
441
+ LogWarning("SQLiteBatch: Batch closed but could not finalize %s statement: %s",
438
442
  stmt_description, sqlite3_errstr(res));
439
443
  }
440
444
  *stmt_prepared = nullptr;
@@ -465,7 +469,7 @@ bool SQLiteBatch::ReadKey(DataStream&& key, DataStream& value)
465
469
  if (res != SQLITE_ROW) {
466
470
  if (res != SQLITE_DONE) {
467
471
  // SQLITE_DONE means "not found", don't log an error in that case.
468
- LogPrintf("%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
472
+ LogWarning("Unable to execute read statement: %s", sqlite3_errstr(res));
469
473
  }
470
474
  sqlite3_clear_bindings(m_read_stmt);
471
475
  sqlite3_reset(m_read_stmt);
@@ -505,7 +509,7 @@ bool SQLiteBatch::WriteKey(DataStream&& key, DataStream&& value, bool overwrite)
505
509
  sqlite3_clear_bindings(stmt);
506
510
  sqlite3_reset(stmt);
507
511
  if (res != SQLITE_DONE) {
508
- LogPrintf("%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
512
+ LogWarning("Unable to execute write statement: %s", sqlite3_errstr(res));
509
513
  }
510
514
 
511
515
  if (!m_txn) m_database.m_write_semaphore.release();
@@ -529,7 +533,7 @@ bool SQLiteBatch::ExecStatement(sqlite3_stmt* stmt, std::span<const std::byte> b
529
533
  sqlite3_clear_bindings(stmt);
530
534
  sqlite3_reset(stmt);
531
535
  if (res != SQLITE_DONE) {
532
- LogPrintf("%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
536
+ LogWarning("Unable to execute exec statement: %s", sqlite3_errstr(res));
533
537
  }
534
538
 
535
539
  if (!m_txn) m_database.m_write_semaphore.release();
@@ -567,7 +571,7 @@ DatabaseCursor::Status SQLiteCursor::Next(DataStream& key, DataStream& value)
567
571
  return Status::DONE;
568
572
  }
569
573
  if (res != SQLITE_ROW) {
570
- LogPrintf("%s: Unable to execute cursor step: %s\n", __func__, sqlite3_errstr(res));
574
+ LogWarning("Unable to execute cursor step: %s", sqlite3_errstr(res));
571
575
  return Status::FAIL;
572
576
  }
573
577
 
@@ -586,8 +590,8 @@ SQLiteCursor::~SQLiteCursor()
586
590
  sqlite3_reset(m_cursor_stmt);
587
591
  int res = sqlite3_finalize(m_cursor_stmt);
588
592
  if (res != SQLITE_OK) {
589
- LogPrintf("%s: cursor closed but could not finalize cursor statement: %s\n",
590
- __func__, sqlite3_errstr(res));
593
+ LogWarning("Cursor closed but could not finalize cursor statement: %s",
594
+ sqlite3_errstr(res));
591
595
  }
592
596
  }
593
597
 
@@ -655,7 +659,7 @@ bool SQLiteBatch::TxnBegin()
655
659
  Assert(!m_database.HasActiveTxn());
656
660
  int res = Assert(m_exec_handler)->Exec(m_database, "BEGIN TRANSACTION");
657
661
  if (res != SQLITE_OK) {
658
- LogPrintf("SQLiteBatch: Failed to begin the transaction\n");
662
+ LogWarning("SQLiteBatch: Failed to begin the transaction");
659
663
  m_database.m_write_semaphore.release();
660
664
  } else {
661
665
  m_txn = true;
@@ -669,7 +673,7 @@ bool SQLiteBatch::TxnCommit()
669
673
  Assert(m_database.HasActiveTxn());
670
674
  int res = Assert(m_exec_handler)->Exec(m_database, "COMMIT TRANSACTION");
671
675
  if (res != SQLITE_OK) {
672
- LogPrintf("SQLiteBatch: Failed to commit the transaction\n");
676
+ LogWarning("SQLiteBatch: Failed to commit the transaction");
673
677
  } else {
674
678
  m_txn = false;
675
679
  m_database.m_write_semaphore.release();
@@ -683,7 +687,7 @@ bool SQLiteBatch::TxnAbort()
683
687
  Assert(m_database.HasActiveTxn());
684
688
  int res = Assert(m_exec_handler)->Exec(m_database, "ROLLBACK TRANSACTION");
685
689
  if (res != SQLITE_OK) {
686
- LogPrintf("SQLiteBatch: Failed to abort the transaction\n");
690
+ LogWarning("SQLiteBatch: Failed to abort the transaction");
687
691
  } else {
688
692
  m_txn = false;
689
693
  m_database.m_write_semaphore.release();