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:
authorbitflash <dev@bitflash.network>2026-08-18 16:14:19 -0300
committerbitflash <dev@bitflash.network>2026-08-18 16:14:19 -0300
commit3f94ec0649f935d00de49ad7b55026317dc64a27 (patch)
treee67ff06c8341889cf90cbbc3b835507a90510b64 /src/db.cpp
parentf3fb7ce6759ac98a7cc39d586fc2824982c74acd (diff)
wallet: make SQLite the default backend for new wallets
A fresh install with no wallet.dat now starts on the SQLite backend and creates wallet.sqlite, instead of a Berkeley DB wallet.dat. The choice is recorded in a plain-text <datadir>/wallet-backend marker so it survives a restart without a command-line flag. Backend resolution when no -walletbackend is given: an existing wallet.sqlite (or a "sqlite" marker) stays on SQLite; an existing wallet.dat stays on Berkeley DB -- nothing is converted behind the user; a fresh datadir starts on SQLite. An explicit -walletbackend=bdb or a "bdb" marker forces Berkeley DB and overrides the default. Adds CreateNewSQLiteWallet() (WalletSQLiteRuntimeOpen gains fMustExist so the create path can make a new file) which mints the first default key straight into the SQLite store via the same FinishLoadedWallet() call the Berkeley DB create path uses, then cleans up on failure. Marker read/write helpers are plain text, hand-editable. New wallet-backend-default self-test proves the resolution in child processes (fresh->SQLite+marker, existing wallet.dat->BDB, "bdb" marker->BDB, explicit flag->wallet.dat). The three wallet.dat-specific suites now ask for -walletbackend=bdb explicitly, since a flagless fresh datadir is SQLite now. All wallet suites pass.
Diffstat (limited to 'src/db.cpp')
-rw-r--r--src/db.cpp91
1 files changed, 89 insertions, 2 deletions
diff --git a/src/db.cpp b/src/db.cpp
index aafc0f9..949865f 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -101,10 +101,13 @@ bool WalletSQLiteRuntimeActive()
101 return pWalletSQLiteRuntime != NULL; 101 return pWalletSQLiteRuntime != NULL;
102} 102}
103 103
104bool WalletSQLiteRuntimeOpen(const string& strPath, string& strErrorRet) 104bool WalletSQLiteRuntimeOpen(const string& strPath, string& strErrorRet, bool fMustExist)
105{ 105{
106 strErrorRet.clear(); 106 strErrorRet.clear();
107 if (!FileExists(strPath.c_str())) 107 // Callers that load an existing wallet want the clear "does not exist"
108 // message rather than silently creating a blank one; the create path passes
109 // fMustExist=false so Open() (SQLITE_OPEN_CREATE) can make a fresh file.
110 if (fMustExist && !FileExists(strPath.c_str()))
108 { 111 {
109 strErrorRet = strprintf("SQLite wallet does not exist: %s", 112 strErrorRet = strprintf("SQLite wallet does not exist: %s",
110 strPath.c_str()); 113 strPath.c_str());
@@ -230,6 +233,47 @@ bool WalletSQLiteRuntimeCheckpoint(string& strErrorRet)
230 return pWalletSQLiteRuntime->Checkpoint(strErrorRet); 233 return pWalletSQLiteRuntime->Checkpoint(strErrorRet);
231} 234}
232 235
236// The persistent record of which backend this datadir uses, so the choice
237// survives a restart without a command-line flag. A plain text file holding
238// "sqlite" or "bdb" -- visible and hand-editable on purpose, no hidden state.
239static string WalletBackendMarkerPath()
240{
241 return GetAppDir() + "/wallet-backend";
242}
243
244string ReadWalletBackendMarker()
245{
246 FILE* pf = fopen(WalletBackendMarkerPath().c_str(), "rb");
247 if (!pf)
248 return "";
249 char buf[16] = {0};
250 size_t n = fread(buf, 1, sizeof(buf) - 1, pf);
251 fclose(pf);
252 string s(buf, n);
253 while (!s.empty() && isspace((unsigned char)s[s.size() - 1]))
254 s.erase(s.size() - 1);
255 while (!s.empty() && isspace((unsigned char)s[0]))
256 s.erase(0, 1);
257 if (s == "sqlite" || s == "bdb")
258 return s;
259 return "";
260}
261
262bool WriteWalletBackendMarker(const string& strBackend)
263{
264 if (strBackend != "sqlite" && strBackend != "bdb")
265 return false;
266 FILE* pf = fopen(WalletBackendMarkerPath().c_str(), "wb");
267 if (!pf)
268 return false;
269 bool fOk = fwrite(strBackend.c_str(), 1, strBackend.size(), pf) == strBackend.size();
270 if (fputc('\n', pf) == EOF)
271 fOk = false;
272 if (fclose(pf) != 0)
273 fOk = false;
274 return fOk;
275}
276
233 277
234CDB::CDB(const char* pszFile, const char* pszMode, bool fTxn) : pdb(NULL) 278CDB::CDB(const char* pszFile, const char* pszMode, bool fTxn) : pdb(NULL)
235{ 279{
@@ -1609,6 +1653,49 @@ bool LoadWalletFromSQLiteRuntime(const string& strPath)
1609 return true; 1653 return true;
1610} 1654}
1611 1655
1656// Create a brand-new wallet directly in the SQLite backend. For a fresh install
1657// where SQLite is the default there is no wallet.dat to export from, so open a
1658// new wallet.sqlite (Open() creates the file and its schema) and let
1659// FinishLoadedWallet mint the first default key straight into it -- the same
1660// call the Berkeley DB create path uses, so a new wallet is identical either
1661// way. Refuses to touch an existing file, and cleans up on failure so a broken
1662// half-initialised wallet.sqlite is never left for the next start to load.
1663bool CreateNewSQLiteWallet(const string& strPath)
1664{
1665 strWalletLoadError.clear();
1666
1667 if (FileExists(strPath.c_str()))
1668 {
1669 strWalletLoadError = strprintf("SQLite wallet already exists: %s",
1670 strPath.c_str());
1671 printf("CreateNewSQLiteWallet: %s\n", strWalletLoadError.c_str());
1672 return false;
1673 }
1674
1675 string strError;
1676 if (!WalletSQLiteRuntimeOpen(strPath, strError, false))
1677 {
1678 strWalletLoadError = strError;
1679 printf("CreateNewSQLiteWallet: cannot create SQLite wallet: %s\n",
1680 strError.c_str());
1681 return false;
1682 }
1683
1684 vector<unsigned char> vchNoDefaultKey;
1685 if (!FinishLoadedWallet(vchNoDefaultKey, true))
1686 {
1687 WalletSQLiteRuntimeClose();
1688 remove(strPath.c_str());
1689 remove((strPath + "-wal").c_str());
1690 remove((strPath + "-shm").c_str());
1691 if (strWalletLoadError.empty())
1692 strWalletLoadError = "could not initialise the new SQLite wallet";
1693 return false;
1694 }
1695
1696 return true;
1697}
1698
1612 1699
1613// Write a copy of wallet.dat that can be opened anywhere. 1700// Write a copy of wallet.dat that can be opened anywhere.
1614// 1701//