Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1251bool RunWithinTxn(WalletDatabase& database, std::string_view process_desc, const std::function<bool(WalletBatch&)>& func)1252{1253WalletBatch batch(database);1254return RunWithinTxn(batch, process_desc, func);1255}1257bool WalletBatch::WriteAddressPreviouslySpent(const CTxDestination& dest, bool previously_spent)1258{1259auto key{std::make_pair(DBKeys::DESTDATA, std::make_pair(EncodeDestination(dest), std::string("used")))};1260return previously_spent ? WriteIC(key, std::string("1")) : EraseIC(key);1261}1263bool WalletBatch::WriteAddressReceiveRequest(const CTxDestination& dest, const std::string& id, const std::string& receive_request)1264{1265return WriteIC(std::make_pair(DBKeys::DESTDATA, std::make_pair(EncodeDestination(dest), "rr" + id)), receive_request);1266}1268bool WalletBatch::EraseAddressReceiveRequest(const CTxDestination& dest, const std::string& id)1269{1270return EraseIC(std::make_pair(DBKeys::DESTDATA, std::make_pair(EncodeDestination(dest), "rr" + id)));1271}1273bool WalletBatch::EraseAddressData(const CTxDestination& dest)1274{1275DataStream prefix;1276prefix << DBKeys::DESTDATA << EncodeDestination(dest);1277return m_batch->ErasePrefix(prefix);1278}1280bool WalletBatch::WriteWalletFlags(const uint64_t flags)1281{1282return WriteIC(DBKeys::FLAGS, flags);1283}1285bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types)1286{1287return std::all_of(types.begin(), types.end(), [&](const std::string& type) {1288return m_batch->ErasePrefix(DataStream() << type);1289});1290}1292bool WalletBatch::TxnBegin()1293{1294return m_batch->TxnBegin();1295}1297bool WalletBatch::TxnCommit()1298{1299bool res = m_batch->TxnCommit();1300if (res) {1301for (const auto& listener : m_txn_listeners) {1302listener.on_commit();1303}1304// txn finished, clear listeners1305m_txn_listeners.clear();1306}1307return res;1308}1310bool WalletBatch::TxnAbort()1311{1312bool res = m_batch->TxnAbort();1313if (res) {1314for (const auto& listener : m_txn_listeners) {1315listener.on_abort();1316}1317// txn finished, clear listeners1318m_txn_listeners.clear();1319}1320return res;1321}1323void WalletBatch::RegisterTxnListener(const DbTxnListener& l)1324{1325assert(m_batch->HasActiveTxn());1326m_txn_listeners.emplace_back(l);1327}1329std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error)1330{1331bool exists;1332try {1333exists = fs::symlink_status(path).type() != fs::file_type::not_found;1334} catch (const fs::filesystem_error& e) {1335error = Untranslated(strprintf("Failed to access database path '%s': %s", fs::PathToString(path), e.code().message()));1336status = DatabaseStatus::FAILED_BAD_PATH;1337return nullptr;1338}1340std::optional<DatabaseFormat> format;1341if (exists) {1342if (IsBDBFile(BDBDataFile(path))) {1343format = DatabaseFormat::BERKELEY_RO;1344}1345if (IsSQLiteFile(SQLiteDataFile(path))) {1346if (format) {1347error = Untranslated(strprintf("Failed to load database path '%s'. Data is in ambiguous format.", fs::PathToString(path)));1348status = DatabaseStatus::FAILED_BAD_FORMAT;1349return nullptr;1350}1351format = DatabaseFormat::SQLITE;1352}1353} else if (options.require_existing) {1354error = Untranslated(strprintf("Failed to load database path '%s'. Path does not exist.", fs::PathToString(path)));1355status = DatabaseStatus::FAILED_NOT_FOUND;1356return nullptr;1357}1359if (!format && options.require_existing) {1360error = Untranslated(strprintf("Failed to load database path '%s'. Data is not in recognized format.", fs::PathToString(path)));1361status = DatabaseStatus::FAILED_BAD_FORMAT;1362return nullptr;1363}1365if (format && options.require_create) {1366error = Untranslated(strprintf("Failed to create database path '%s'. Database already exists.", fs::PathToString(path)));1367status = DatabaseStatus::FAILED_ALREADY_EXISTS;1368return nullptr;1369}1371// BERKELEY_RO can only be opened if require_format was set, which only occurs in migration.1372if (format && format == DatabaseFormat::BERKELEY_RO && (!options.require_format || options.require_format != DatabaseFormat::BERKELEY_RO)) {1373error = Untranslated(strprintf("Failed to open database path '%s'. The wallet appears to be a Legacy wallet, please use the wallet migration tool (migratewallet RPC or the GUI option).", fs::PathToString(path)));1374status = DatabaseStatus::FAILED_LEGACY_DISABLED;1375return nullptr;1376}1378// A db already exists so format is set, but options also specifies the format, so make sure they agree1379if (format && options.require_format && format != options.require_format) {1380error = Untranslated(strprintf("Failed to load database path '%s'. Data is not in required format.", fs::PathToString(path)));1381status = DatabaseStatus::FAILED_BAD_FORMAT;1382return nullptr;1383}1385// Format is not set when a db doesn't already exist, so use the format specified by the options if it is set.1386if (!format && options.require_format) format = options.require_format;1388if (!format) {1389format = DatabaseFormat::SQLITE;1390}1392if (format == DatabaseFormat::SQLITE) {1393return MakeSQLiteDatabase(path, options, status, error);1394}1396if (format == DatabaseFormat::BERKELEY_RO) {1397return MakeBerkeleyRODatabase(path, options, status, error);1398}1400error = Untranslated(STR_INTERNAL_BUG("Could not determine wallet format"));1401status = DatabaseStatus::FAILED_BAD_FORMAT;1402return nullptr;1403}1404} // namespace wallet