LCOV - code coverage report
Current view: top level - src/wallet - db.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 44 70 62.9 %
Date: 2026-06-25 07:23:43 Functions: 65 93 69.9 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2021 The Bitcoin Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #ifndef BITCOIN_WALLET_DB_H
       7             : #define BITCOIN_WALLET_DB_H
       8             : 
       9             : #include <clientversion.h>
      10             : #include <fs.h>
      11             : #include <streams.h>
      12             : #include <support/allocators/secure.h>
      13             : 
      14             : #include <atomic>
      15             : #include <memory>
      16             : #include <optional>
      17             : #include <string>
      18             : 
      19             : class ArgsManager;
      20             : struct bilingual_str;
      21             : 
      22             : namespace wallet {
      23             : 
      24             : /** RAII class that provides access to a WalletDatabase */
      25             : class DatabaseBatch
      26             : {
      27             : private:
      28             :     virtual bool ReadKey(CDataStream&& key, CDataStream& value) = 0;
      29             :     virtual bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) = 0;
      30             :     virtual bool EraseKey(CDataStream&& key) = 0;
      31             :     virtual bool HasKey(CDataStream&& key) = 0;
      32             : 
      33             : public:
      34      450613 :     explicit DatabaseBatch() {}
      35      450612 :     virtual ~DatabaseBatch() {}
      36             : 
      37             :     DatabaseBatch(const DatabaseBatch&) = delete;
      38             :     DatabaseBatch& operator=(const DatabaseBatch&) = delete;
      39             : 
      40             :     virtual void Flush() = 0;
      41             :     virtual void Close() = 0;
      42             : 
      43             :     template <typename K, typename T>
      44       41878 :     bool Read(const K& key, T& value)
      45             :     {
      46       41878 :         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
      47       41878 :         ssKey.reserve(1000);
      48       41878 :         ssKey << key;
      49             : 
      50       41878 :         CDataStream ssValue(SER_DISK, CLIENT_VERSION);
      51       41878 :         if (!ReadKey(std::move(ssKey), ssValue)) return false;
      52             :         try {
      53       35617 :             ssValue >> value;
      54       35617 :             return true;
      55           0 :         } catch (const std::exception&) {
      56           0 :             return false;
      57           0 :         }
      58       41878 :     }
      59             : 
      60             :     template <typename K, typename T>
      61      570323 :     bool Write(const K& key, const T& value, bool fOverwrite = true)
      62             :     {
      63      570323 :         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
      64      570323 :         ssKey.reserve(1000);
      65      570323 :         ssKey << key;
      66             : 
      67      570323 :         CDataStream ssValue(SER_DISK, CLIENT_VERSION);
      68      570323 :         ssValue.reserve(10000);
      69      570323 :         ssValue << value;
      70             : 
      71      570323 :         return WriteKey(std::move(ssKey), std::move(ssValue), fOverwrite);
      72      570323 :     }
      73             : 
      74             :     template <typename K>
      75       23359 :     bool Erase(const K& key)
      76             :     {
      77       23359 :         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
      78       23359 :         ssKey.reserve(1000);
      79       23359 :         ssKey << key;
      80             : 
      81       23359 :         return EraseKey(std::move(ssKey));
      82       23359 :     }
      83             : 
      84             :     template <typename K>
      85             :     bool Exists(const K& key)
      86             :     {
      87             :         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
      88             :         ssKey.reserve(1000);
      89             :         ssKey << key;
      90             : 
      91             :         return HasKey(std::move(ssKey));
      92             :     }
      93             :     virtual bool ErasePrefix(Span<const std::byte> prefix) = 0;
      94             : 
      95             :     virtual bool StartCursor() = 0;
      96             :     virtual bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) = 0;
      97             :     virtual void CloseCursor() = 0;
      98             :     virtual bool TxnBegin() = 0;
      99             :     virtual bool TxnCommit() = 0;
     100             :     virtual bool TxnAbort() = 0;
     101             : };
     102             : 
     103             : /** An instance of this class represents one database.
     104             :  **/
     105             : class WalletDatabase
     106             : {
     107             : public:
     108             :     /** Create dummy DB handle */
     109        9075 :     WalletDatabase() : nUpdateCounter(0) {}
     110        3025 :     virtual ~WalletDatabase() {};
     111             : 
     112             :     /** Open the database if it is not already opened. */
     113             :     virtual void Open() = 0;
     114             : 
     115             :     //! Counts the number of active database users to be sure that the database is not closed while someone is using it
     116        3025 :     std::atomic<int> m_refcount{0};
     117             :     /** Indicate the a new database user has began using the database. Increments m_refcount */
     118             :     virtual void AddRef() = 0;
     119             :     /** Indicate that database user has stopped using the database and that it could be flushed or closed. Decrement m_refcount */
     120             :     virtual void RemoveRef() = 0;
     121             : 
     122             :     /** Rewrite the entire database on disk, with the exception of key pszSkip if non-zero
     123             :      */
     124             :     virtual bool Rewrite(const char* pszSkip=nullptr) = 0;
     125             : 
     126             :     /** Back up the entire database to a file.
     127             :      */
     128             :     virtual bool Backup(const std::string& strDest) const = 0;
     129             : 
     130             :     /** Make sure all changes are flushed to database file.
     131             :      */
     132             :     virtual void Flush() = 0;
     133             :     /** Flush to the database file and close the database.
     134             :      *  Also close the environment if no other databases are open in it.
     135             :      */
     136             :     virtual void Close() = 0;
     137             :     /* flush the wallet passively (TRY_LOCK)
     138             :        ideal to be called periodically */
     139             :     virtual bool PeriodicFlush() = 0;
     140             : 
     141             :     virtual void IncrementUpdateCounter() = 0;
     142             : 
     143             :     virtual void ReloadDbEnv() = 0;
     144             : 
     145             :     /** Return path to main database file for logs and error messages. */
     146             :     virtual std::string Filename() = 0;
     147             : 
     148             :     virtual std::string Format() = 0;
     149             : 
     150             :     std::atomic<unsigned int> nUpdateCounter;
     151        3025 :     unsigned int nLastSeen{0};
     152        3025 :     unsigned int nLastFlushed{0};
     153        3025 :     int64_t nLastWalletUpdate{0};
     154             : 
     155             :     /** Make a DatabaseBatch connected to this database */
     156             :     virtual std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) = 0;
     157             : 
     158        1209 :     virtual bool SupportsAutoBackup() { return false; }
     159             : };
     160             : 
     161             : /** RAII class that provides access to a DummyDatabase. Never fails. */
     162             : class DummyBatch : public DatabaseBatch
     163             : {
     164             : private:
     165           0 :     bool ReadKey(CDataStream&& key, CDataStream& value) override { return true; }
     166         124 :     bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) override { return true; }
     167           0 :     bool EraseKey(CDataStream&& key) override { return true; }
     168           0 :     bool HasKey(CDataStream&& key) override { return true; }
     169           0 :     bool ErasePrefix(Span<const std::byte> prefix) override { return true; }
     170             : 
     171             : public:
     172           0 :     void Flush() override {}
     173           0 :     void Close() override {}
     174             : 
     175           0 :     bool StartCursor() override { return true; }
     176           0 :     bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) override { return true; }
     177           0 :     void CloseCursor() override {}
     178           0 :     bool TxnBegin() override { return true; }
     179           0 :     bool TxnCommit() override { return true; }
     180           0 :     bool TxnAbort() override { return true; }
     181             : };
     182             : 
     183             : /** A dummy WalletDatabase that does nothing and never fails. Only used by unit tests.
     184             :  **/
     185             : class DummyDatabase : public WalletDatabase
     186             : {
     187             : public:
     188           0 :     void Open() override {};
     189           0 :     void AddRef() override {}
     190           0 :     void RemoveRef() override {}
     191           0 :     bool Rewrite(const char* pszSkip=nullptr) override { return true; }
     192           0 :     bool Backup(const std::string& strDest) const override { return true; }
     193           0 :     void Close() override {}
     194           0 :     void Flush() override {}
     195           0 :     bool PeriodicFlush() override { return true; }
     196         124 :     void IncrementUpdateCounter() override { ++nUpdateCounter; }
     197           0 :     void ReloadDbEnv() override {}
     198           0 :     std::string Filename() override { return "dummy"; }
     199           0 :     std::string Format() override { return "dummy"; }
     200          85 :     std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override { return std::make_unique<DummyBatch>(); }
     201             : };
     202             : 
     203             : enum class DatabaseFormat {
     204             :     BERKELEY,
     205             :     SQLITE,
     206             : };
     207             : 
     208       34251 : struct DatabaseOptions {
     209       11417 :     bool require_existing = false;
     210       11417 :     bool require_create = false;
     211             :     std::optional<DatabaseFormat> require_format;
     212       11417 :     uint64_t create_flags = 0;
     213             :     SecureString create_passphrase;
     214             : 
     215             :     // Specialized options. Not every option is supported by every backend.
     216       11417 :     bool verify = true;             //!< Check data integrity on load.
     217       11417 :     bool use_unsafe_sync = false;   //!< Disable file sync for faster performance.
     218       11417 :     bool use_shared_memory = false; //!< Let other processes access the database.
     219       11417 :     int64_t max_log_mb = 100;       //!< Max log size to allow before consolidating.
     220             : };
     221             : 
     222             : enum class DatabaseStatus {
     223             :     SUCCESS,
     224             :     FAILED_BAD_PATH,
     225             :     FAILED_BAD_FORMAT,
     226             :     FAILED_ALREADY_LOADED,
     227             :     FAILED_ALREADY_EXISTS,
     228             :     FAILED_NOT_FOUND,
     229             :     FAILED_CREATE,
     230             :     FAILED_LOAD,
     231             :     FAILED_VERIFY,
     232             :     FAILED_ENCRYPT,
     233             :     FAILED_INVALID_BACKUP_FILE,
     234             : };
     235             : 
     236             : /** Recursively list database paths in directory. */
     237             : std::vector<fs::path> ListDatabases(const fs::path& path);
     238             : 
     239             : void ReadDatabaseArgs(const ArgsManager& args, DatabaseOptions& options);
     240             : std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
     241             : 
     242             : fs::path BDBDataFile(const fs::path& path);
     243             : fs::path SQLiteDataFile(const fs::path& path);
     244             : bool IsBDBFile(const fs::path& path);
     245             : bool IsSQLiteFile(const fs::path& path);
     246             : } // namespace wallet
     247             : 
     248             : #endif // BITCOIN_WALLET_DB_H

Generated by: LCOV version 1.16