upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/db.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/db.cpp')
-rw-r--r--src/db.cpp107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/db.cpp b/src/db.cpp
index 7cfb7c5..771a4ba 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -124,6 +124,13 @@ void WalletSQLiteRuntimeClose()
124{ 124{
125 if (pWalletSQLiteRuntime) 125 if (pWalletSQLiteRuntime)
126 { 126 {
127 // Fold the write-ahead log into the main file on the way out. WAL +
128 // synchronous=FULL already makes every committed write durable across a
129 // kill, so this is housekeeping, not the thing that protects the data:
130 // if it fails, or the node is killed before it runs, the wallet is
131 // still whole. Best effort, never throws.
132 string strCheckpointError;
133 pWalletSQLiteRuntime->Checkpoint(strCheckpointError);
127 delete pWalletSQLiteRuntime; 134 delete pWalletSQLiteRuntime;
128 pWalletSQLiteRuntime = NULL; 135 pWalletSQLiteRuntime = NULL;
129 } 136 }
@@ -1426,6 +1433,106 @@ bool LoadWalletFromSQLite(const string& strPath)
1426 return FinishLoadedWallet(visitor.vchDefaultKey, false); 1433 return FinishLoadedWallet(visitor.vchDefaultKey, false);
1427} 1434}
1428 1435
1436// Open a SQLite wallet read-write and keep it open as the active runtime
1437// backend, then load its records into memory the same way LoadWalletFromSQLite
1438// does. Unlike the read-only staging path, this leaves pWalletSQLiteRuntime set
1439// so every later CWalletDB read/write/erase routes to this file for the life of
1440// the process. The Berkeley DB wallet.dat is never opened.
1441bool LoadWalletFromSQLiteRuntime(const string& strPath)
1442{
1443 strWalletLoadError.clear();
1444
1445 if (!FileExists(strPath.c_str()))
1446 {
1447 strWalletLoadError = strprintf("SQLite wallet does not exist: %s",
1448 strPath.c_str());
1449 printf("LoadWallet: %s\n", strWalletLoadError.c_str());
1450 return false;
1451 }
1452
1453 string strError;
1454 if (!WalletSQLiteRuntimeOpen(strPath, strError))
1455 {
1456 strWalletLoadError = strError;
1457 printf("LoadWallet: cannot open SQLite wallet backend: %s\n",
1458 strError.c_str());
1459 return false;
1460 }
1461
1462 CSQLiteWalletRuntimeLoadVisitor visitor;
1463 try
1464 {
1465 CRITICAL_BLOCK(cs_mapKeys)
1466 CRITICAL_BLOCK(cs_mapWallet)
1467 {
1468 if (!pWalletSQLiteRuntime->ScanRecords(visitor, strError))
1469 {
1470 WalletSQLiteRuntimeClose();
1471 if (strWalletLoadError.empty())
1472 strWalletLoadError = strError;
1473 printf("LoadWallet: SQLite wallet backend could not be read. "
1474 "Failed while handling a '%s' record: %s\n",
1475 visitor.strLastType.c_str(), strError.c_str());
1476 return false;
1477 }
1478 }
1479 }
1480 catch (const std::exception& e)
1481 {
1482 WalletSQLiteRuntimeClose();
1483 strWalletLoadError = strprintf(
1484 "SQLite wallet backend could not be read while handling a '%s' record: %s",
1485 visitor.strLastType.c_str(), e.what());
1486 printf("LoadWallet: %s\n", strWalletLoadError.c_str());
1487 return false;
1488 }
1489 catch (...)
1490 {
1491 WalletSQLiteRuntimeClose();
1492 strWalletLoadError = strprintf(
1493 "SQLite wallet backend could not be read while handling a '%s' record",
1494 visitor.strLastType.c_str());
1495 printf("LoadWallet: %s\n", strWalletLoadError.c_str());
1496 return false;
1497 }
1498
1499 // Refuse an empty or non-wallet SQLite file up front, with a message that
1500 // names the likely cause. FinishLoadedWallet below already rejects a
1501 // missing default key (it is the fMayCreateDefaultKey=false path), but its
1502 // wording -- "no usable default public key" -- reads as corruption when the
1503 // real story is usually "this file was never an exported wallet". A blank
1504 // wallet.sqlite left by a typo or a half-run export should say so.
1505 if (visitor.vchDefaultKey.empty())
1506 {
1507 WalletSQLiteRuntimeClose();
1508 strWalletLoadError =
1509 "SQLite wallet has no default key record; it may be empty or not a "
1510 "wallet export. Create it with -walletsqliteexport.";
1511 printf("LoadWallet: %s\n", strWalletLoadError.c_str());
1512 return false;
1513 }
1514
1515 if (!ReconcileLoadedWalletMetadata(visitor.fHaveStoredMineMode,
1516 visitor.fHaveStoredHDCoinType))
1517 {
1518 WalletSQLiteRuntimeClose();
1519 if (strWalletLoadError.empty())
1520 strWalletLoadError = "SQLite wallet metadata is not supported by this build";
1521 return false;
1522 }
1523
1524 // Never fabricate a default key: an export always carries one, and a file
1525 // that does not is refused with the wallet left open to no writes rather
1526 // than quietly minted into a new identity.
1527 if (!FinishLoadedWallet(visitor.vchDefaultKey, false))
1528 {
1529 WalletSQLiteRuntimeClose();
1530 return false;
1531 }
1532
1533 return true;
1534}
1535
1429 1536
1430// Write a copy of wallet.dat that can be opened anywhere. 1537// Write a copy of wallet.dat that can be opened anywhere.
1431// 1538//