Branch data 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 : : void SplitWalletPath(const fs::path& wallet_path, fs::path& env_directory, std::string& database_filename);
# 24 : :
# 25 : : /** RAII class that provides access to a WalletDatabase */
# 26 : : class DatabaseBatch
# 27 : : {
# 28 : : private:
# 29 : : virtual bool ReadKey(CDataStream&& key, CDataStream& value) = 0;
# 30 : : virtual bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) = 0;
# 31 : : virtual bool EraseKey(CDataStream&& key) = 0;
# 32 : : virtual bool HasKey(CDataStream&& key) = 0;
# 33 : :
# 34 : : public:
# 35 : 196359 : explicit DatabaseBatch() {}
# 36 : 196359 : virtual ~DatabaseBatch() {}
# 37 : :
# 38 : : DatabaseBatch(const DatabaseBatch&) = delete;
# 39 : : DatabaseBatch& operator=(const DatabaseBatch&) = delete;
# 40 : :
# 41 : : virtual void Flush() = 0;
# 42 : : virtual void Close() = 0;
# 43 : :
# 44 : : template <typename K, typename T>
# 45 : : bool Read(const K& key, T& value)
# 46 : 17370 : {
# 47 : 17370 : CDataStream ssKey(SER_DISK, CLIENT_VERSION);
# 48 : 17370 : ssKey.reserve(1000);
# 49 : 17370 : ssKey << key;
# 50 : :
# 51 : 17370 : CDataStream ssValue(SER_DISK, CLIENT_VERSION);
# 52 [ - + ][ + + ]: 17370 : if (!ReadKey(std::move(ssKey), ssValue)) return false;
# [ - + ][ + + ]
# [ + + ]
# 53 : 16037 : try {
# 54 : 16037 : ssValue >> value;
# 55 : 16037 : return true;
# 56 : 16037 : } catch (const std::exception&) {
# 57 : 0 : return false;
# 58 : 0 : }
# 59 : 16037 : }
# 60 : :
# 61 : : template <typename K, typename T>
# 62 : : bool Write(const K& key, const T& value, bool fOverwrite = true)
# 63 : 274167 : {
# 64 : 274167 : CDataStream ssKey(SER_DISK, CLIENT_VERSION);
# 65 : 274167 : ssKey.reserve(1000);
# 66 : 274167 : ssKey << key;
# 67 : :
# 68 : 274167 : CDataStream ssValue(SER_DISK, CLIENT_VERSION);
# 69 : 274167 : ssValue.reserve(10000);
# 70 : 274167 : ssValue << value;
# 71 : :
# 72 : 274167 : return WriteKey(std::move(ssKey), std::move(ssValue), fOverwrite);
# 73 : 274167 : }
# 74 : :
# 75 : : template <typename K>
# 76 : : bool Erase(const K& key)
# 77 : 14136 : {
# 78 : 14136 : CDataStream ssKey(SER_DISK, CLIENT_VERSION);
# 79 : 14136 : ssKey.reserve(1000);
# 80 : 14136 : ssKey << key;
# 81 : :
# 82 : 14136 : return EraseKey(std::move(ssKey));
# 83 : 14136 : }
# 84 : :
# 85 : : template <typename K>
# 86 : : bool Exists(const K& key)
# 87 : 112998 : {
# 88 : 112998 : CDataStream ssKey(SER_DISK, CLIENT_VERSION);
# 89 : 112998 : ssKey.reserve(1000);
# 90 : 112998 : ssKey << key;
# 91 : :
# 92 : 112998 : return HasKey(std::move(ssKey));
# 93 : 112998 : }
# 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 : 1024 : WalletDatabase() : nUpdateCounter(0), nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0) {}
# 110 : 1024 : 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 : : 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 : : unsigned int nLastSeen;
# 152 : : unsigned int nLastFlushed;
# 153 : : int64_t nLastWalletUpdate;
# 154 : :
# 155 : : /** Make a DatabaseBatch connected to this database */
# 156 : : virtual std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) = 0;
# 157 : : };
# 158 : :
# 159 : : /** RAII class that provides access to a DummyDatabase. Never fails. */
# 160 : : class DummyBatch : public DatabaseBatch
# 161 : : {
# 162 : : private:
# 163 : 0 : bool ReadKey(CDataStream&& key, CDataStream& value) override { return true; }
# 164 : 214 : bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite=true) override { return true; }
# 165 : 0 : bool EraseKey(CDataStream&& key) override { return true; }
# 166 : 0 : bool HasKey(CDataStream&& key) override { return true; }
# 167 : :
# 168 : : public:
# 169 : 0 : void Flush() override {}
# 170 : 0 : void Close() override {}
# 171 : :
# 172 : 0 : bool StartCursor() override { return true; }
# 173 : 0 : bool ReadAtCursor(CDataStream& ssKey, CDataStream& ssValue, bool& complete) override { return true; }
# 174 : 0 : void CloseCursor() override {}
# 175 : 0 : bool TxnBegin() override { return true; }
# 176 : 0 : bool TxnCommit() override { return true; }
# 177 : 0 : bool TxnAbort() override { return true; }
# 178 : : };
# 179 : :
# 180 : : /** A dummy WalletDatabase that does nothing and never fails. Only used by unit tests.
# 181 : : **/
# 182 : : class DummyDatabase : public WalletDatabase
# 183 : : {
# 184 : : public:
# 185 : 0 : void Open() override {};
# 186 : 0 : void AddRef() override {}
# 187 : 0 : void RemoveRef() override {}
# 188 : 0 : bool Rewrite(const char* pszSkip=nullptr) override { return true; }
# 189 : 0 : bool Backup(const std::string& strDest) const override { return true; }
# 190 : 0 : void Close() override {}
# 191 : 0 : void Flush() override {}
# 192 : 0 : bool PeriodicFlush() override { return true; }
# 193 : 214 : void IncrementUpdateCounter() override { ++nUpdateCounter; }
# 194 : 0 : void ReloadDbEnv() override {}
# 195 : 0 : std::string Filename() override { return "dummy"; }
# 196 : 0 : std::string Format() override { return "dummy"; }
# 197 : 123 : std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override { return std::make_unique<DummyBatch>(); }
# 198 : : };
# 199 : :
# 200 : : enum class DatabaseFormat {
# 201 : : BERKELEY,
# 202 : : SQLITE,
# 203 : : };
# 204 : :
# 205 : : struct DatabaseOptions {
# 206 : : bool require_existing = false;
# 207 : : bool require_create = false;
# 208 : : std::optional<DatabaseFormat> require_format;
# 209 : : uint64_t create_flags = 0;
# 210 : : SecureString create_passphrase;
# 211 : :
# 212 : : // Specialized options. Not every option is supported by every backend.
# 213 : : bool verify = true; //!< Check data integrity on load.
# 214 : : bool use_unsafe_sync = false; //!< Disable file sync for faster performance.
# 215 : : bool use_shared_memory = false; //!< Let other processes access the database.
# 216 : : int64_t max_log_mb = 100; //!< Max log size to allow before consolidating.
# 217 : : };
# 218 : :
# 219 : : enum class DatabaseStatus {
# 220 : : SUCCESS,
# 221 : : FAILED_BAD_PATH,
# 222 : : FAILED_BAD_FORMAT,
# 223 : : FAILED_ALREADY_LOADED,
# 224 : : FAILED_ALREADY_EXISTS,
# 225 : : FAILED_NOT_FOUND,
# 226 : : FAILED_CREATE,
# 227 : : FAILED_LOAD,
# 228 : : FAILED_VERIFY,
# 229 : : FAILED_ENCRYPT,
# 230 : : FAILED_INVALID_BACKUP_FILE,
# 231 : : };
# 232 : :
# 233 : : /** Recursively list database paths in directory. */
# 234 : : std::vector<fs::path> ListDatabases(const fs::path& path);
# 235 : :
# 236 : : void ReadDatabaseArgs(const ArgsManager& args, DatabaseOptions& options);
# 237 : : std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
# 238 : :
# 239 : : fs::path BDBDataFile(const fs::path& path);
# 240 : : fs::path SQLiteDataFile(const fs::path& path);
# 241 : : bool IsBDBFile(const fs::path& path);
# 242 : : bool IsSQLiteFile(const fs::path& path);
# 243 : : } // namespace wallet
# 244 : :
# 245 : : #endif // BITCOIN_WALLET_DB_H
|