LCOV - code coverage report
Current view: top level - src/wallet - db.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 46 68 67.6 %
Date: 2020-09-26 01:30:44 Functions: 54 80 67.5 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2020 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 <optional.h>
      12             : #include <streams.h>
      13             : #include <support/allocators/secure.h>
      14             : #include <util/memory.h>
      15             : 
      16             : #include <atomic>
      17             : #include <memory>
      18             : #include <string>
      19             : 
      20             : struct bilingual_str;
      21             : 
      22             : void SplitWalletPath(const fs::path& wallet_path, fs::path& env_directory, std::string& database_filename);
      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      236355 :     explicit DatabaseBatch() {}
      35      236355 :     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       14371 :     bool Read(const K& key, T& value)
      45             :     {
      46       14371 :         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
      47       14371 :         ssKey.reserve(1000);
      48       14371 :         ssKey << key;
      49             : 
      50       14371 :         CDataStream ssValue(SER_DISK, CLIENT_VERSION);
      51       14371 :         if (!ReadKey(std::move(ssKey), ssValue)) return false;
      52             :         try {
      53       13855 :             ssValue >> value;
      54       13855 :             return true;
      55           0 :         } catch (const std::exception&) {
      56             :             return false;
      57           0 :         }
      58       14371 :     }
      59             : 
      60             :     template <typename K, typename T>
      61      438450 :     bool Write(const K& key, const T& value, bool fOverwrite = true)
      62             :     {
      63      438450 :         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
      64      438450 :         ssKey.reserve(1000);
      65      438450 :         ssKey << key;
      66             : 
      67      438450 :         CDataStream ssValue(SER_DISK, CLIENT_VERSION);
      68      438450 :         ssValue.reserve(10000);
      69      438450 :         ssValue << value;
      70             : 
      71      438450 :         return WriteKey(std::move(ssKey), std::move(ssValue), fOverwrite);
      72      438450 :     }
      73             : 
      74             :     template <typename K>
      75       10950 :     bool Erase(const K& key)
      76             :     {
      77       10950 :         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
      78       10950 :         ssKey.reserve(1000);
      79       10950 :         ssKey << key;
      80             : 
      81       10950 :         return EraseKey(std::move(ssKey));
      82       10950 :     }
      83             : 
      84             :     template <typename K>
      85         671 :     bool Exists(const K& key)
      86             :     {
      87         671 :         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
      88         671 :         ssKey.reserve(1000);
      89         671 :         ssKey << key;
      90             : 
      91         671 :         return HasKey(std::move(ssKey));
      92         671 :     }
      93             : 
      94             :     virtual bool StartCursor() = 0;
      95             :     virtual bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) = 0;
      96             :     virtual void CloseCursor() = 0;
      97             :     virtual bool TxnBegin() = 0;
      98             :     virtual bool TxnCommit() = 0;
      99             :     virtual bool TxnAbort() = 0;
     100             : };
     101             : 
     102             : /** An instance of this class represents one database.
     103             :  **/
     104             : class WalletDatabase
     105             : {
     106             : public:
     107             :     /** Create dummy DB handle */
     108        1148 :     WalletDatabase() : nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0) {}
     109        1148 :     virtual ~WalletDatabase() {};
     110             : 
     111             :     /** Open the database if it is not already opened. */
     112             :     virtual void Open(const char* mode) = 0;
     113             : 
     114             :     //! Counts the number of active database users to be sure that the database is not closed while someone is using it
     115        1148 :     std::atomic<int> m_refcount{0};
     116             :     /** Indicate the a new database user has began using the database. Increments m_refcount */
     117             :     virtual void AddRef() = 0;
     118             :     /** Indicate that database user has stopped using the database and that it could be flushed or closed. Decrement m_refcount */
     119             :     virtual void RemoveRef() = 0;
     120             : 
     121             :     /** Rewrite the entire database on disk, with the exception of key pszSkip if non-zero
     122             :      */
     123             :     virtual bool Rewrite(const char* pszSkip=nullptr) = 0;
     124             : 
     125             :     /** Back up the entire database to a file.
     126             :      */
     127             :     virtual bool Backup(const std::string& strDest) const = 0;
     128             : 
     129             :     /** Make sure all changes are flushed to database file.
     130             :      */
     131             :     virtual void Flush() = 0;
     132             :     /** Flush to the database file and close the database.
     133             :      *  Also close the environment if no other databases are open in it.
     134             :      */
     135             :     virtual void Close() = 0;
     136             :     /* flush the wallet passively (TRY_LOCK)
     137             :        ideal to be called periodically */
     138             :     virtual bool PeriodicFlush() = 0;
     139             : 
     140             :     virtual void IncrementUpdateCounter() = 0;
     141             : 
     142             :     virtual void ReloadDbEnv() = 0;
     143             : 
     144             :     /** Return path to main database file for logs and error messages. */
     145             :     virtual std::string Filename() = 0;
     146             : 
     147             :     std::atomic<unsigned int> nUpdateCounter;
     148             :     unsigned int nLastSeen;
     149             :     unsigned int nLastFlushed;
     150             :     int64_t nLastWalletUpdate;
     151             : 
     152             :     /** Make a DatabaseBatch connected to this database */
     153             :     virtual std::unique_ptr<DatabaseBatch> MakeBatch(const char* mode = "r+", bool flush_on_close = true) = 0;
     154             : };
     155             : 
     156             : /** RAII class that provides access to a DummyDatabase. Never fails. */
     157      550305 : class DummyBatch : public DatabaseBatch
     158             : {
     159             : private:
     160           0 :     bool ReadKey(CDataStream&& key, CDataStream& value) override { return true; }
     161      220108 :     bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) override { return true; }
     162           0 :     bool EraseKey(CDataStream&& key) override { return true; }
     163           0 :     bool HasKey(CDataStream&& key) override { return true; }
     164             : 
     165             : public:
     166         219 :     void Flush() override {}
     167           0 :     void Close() override {}
     168             : 
     169           0 :     bool StartCursor() override { return true; }
     170           0 :     bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) override { return true; }
     171           0 :     void CloseCursor() override {}
     172           0 :     bool TxnBegin() override { return true; }
     173           0 :     bool TxnCommit() override { return true; }
     174           0 :     bool TxnAbort() override { return true; }
     175             : };
     176             : 
     177             : /** A dummy WalletDatabase that does nothing and never fails. Only used by unit tests.
     178             :  **/
     179         610 : class DummyDatabase : public WalletDatabase
     180             : {
     181             : public:
     182           0 :     void Open(const char* mode) override {};
     183           0 :     void AddRef() override {}
     184           0 :     void RemoveRef() override {}
     185           0 :     bool Rewrite(const char* pszSkip=nullptr) override { return true; }
     186           0 :     bool Backup(const std::string& strDest) const override { return true; }
     187           0 :     void Close() override {}
     188           0 :     void Flush() override {}
     189           0 :     bool PeriodicFlush() override { return true; }
     190      220108 :     void IncrementUpdateCounter() override { ++nUpdateCounter; }
     191           0 :     void ReloadDbEnv() override {}
     192           0 :     std::string Filename() override { return "dummy"; }
     193      110061 :     std::unique_ptr<DatabaseBatch> MakeBatch(const char* mode = "r+", bool flush_on_close = true) override { return MakeUnique<DummyBatch>(); }
     194             : };
     195             : 
     196             : enum class DatabaseFormat {
     197             :     BERKELEY,
     198             :     SQLITE,
     199             : };
     200             : 
     201        6192 : struct DatabaseOptions {
     202        1032 :     bool require_existing = false;
     203        1032 :     bool require_create = false;
     204             :     Optional<DatabaseFormat> require_format;
     205        1032 :     uint64_t create_flags = 0;
     206             :     SecureString create_passphrase;
     207        1032 :     bool verify = true;
     208             : };
     209             : 
     210             : enum class DatabaseStatus {
     211             :     SUCCESS,
     212             :     FAILED_BAD_PATH,
     213             :     FAILED_BAD_FORMAT,
     214             :     FAILED_ALREADY_LOADED,
     215             :     FAILED_ALREADY_EXISTS,
     216             :     FAILED_NOT_FOUND,
     217             :     FAILED_CREATE,
     218             :     FAILED_LOAD,
     219             :     FAILED_VERIFY,
     220             :     FAILED_ENCRYPT,
     221             : };
     222             : 
     223             : std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
     224             : 
     225             : #endif // BITCOIN_WALLET_DB_H

Generated by: LCOV version 1.15