Merge bitcoin/bitcoin#25862: refactor, kernel: Remove gArgs accesses from dbwrapper and txdb
aadd7c5b9brefactor, validation: Add ChainstateManagerOpts db options (Ryan Ofsky)0352258148refactor, txdb: Use DBParams struct in CBlockTreeDB (Ryan Ofsky)c00fa1a734refactor, txdb: Add CoinsViewOptions struct (Ryan Ofsky)2eaeded37frefactor, dbwrapper: Add DBParams and DBOptions structs (Ryan Ofsky) Pull request description: Code in the libbitcoin_kernel library should not be calling `ArgsManager` methods or trying to read options from the command line. Instead it should just get options values from simple structs and function arguments that are passed in externally. This PR removes `gArgs` accesses from `dbwrapper` and `txdb` modules by defining appropriate options structs, and is a followup to PR's #25290 #25487 #25527 which remove other `ArgsManager` calls from kernel modules. This PR does not change behavior in any way. It is a simpler alternative to #25623 because the only thing it does is remove `gArgs` references from kernel code. It avoids other unnecessary changes like adding options to the kernel API (they can be added separately later). ACKs for top commit: TheCharlatan: Code review ACKaadd7c5b9bachow101: ACKaadd7c5b9bfurszy: diff ACKaadd7c5bTree-SHA512: 46dfd5d99ab3110492e7bba97a87122c831b8344caaf7dd2ebdb6e0ad6aa9174d4d1832d6f3a7465eda9294fe50defaa3c000afbbddc4e72838687df09a63ffd
This commit is contained in:
21 files changed
+193
-73
No files matched your search
@@ -204,8 +204,10 @@ BITCOIN_CORE_H = \
|
|||||||
node/chainstate.h \
|
node/chainstate.h \
|
||||||
node/chainstatemanager_args.h \
|
node/chainstatemanager_args.h \
|
||||||
node/coin.h \
|
node/coin.h \
|
||||||
|
node/coins_view_args.h \
|
||||||
node/connection_types.h \
|
node/connection_types.h \
|
||||||
node/context.h \
|
node/context.h \
|
||||||
|
node/database_args.h \
|
||||||
node/eviction.h \
|
node/eviction.h \
|
||||||
node/interface_ui.h \
|
node/interface_ui.h \
|
||||||
node/mempool_args.h \
|
node/mempool_args.h \
|
||||||
@@ -388,8 +390,10 @@ libbitcoin_node_a_SOURCES = \
|
|||||||
node/chainstate.cpp \
|
node/chainstate.cpp \
|
||||||
node/chainstatemanager_args.cpp \
|
node/chainstatemanager_args.cpp \
|
||||||
node/coin.cpp \
|
node/coin.cpp \
|
||||||
|
node/coins_view_args.cpp \
|
||||||
node/connection_types.cpp \
|
node/connection_types.cpp \
|
||||||
node/context.cpp \
|
node/context.cpp \
|
||||||
|
node/database_args.cpp \
|
||||||
node/eviction.cpp \
|
node/eviction.cpp \
|
||||||
node/interface_ui.cpp \
|
node/interface_ui.cpp \
|
||||||
node/interfaces.cpp \
|
node/interfaces.cpp \
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ int main(int argc, char* argv[])
|
|||||||
// SETUP: Chainstate
|
// SETUP: Chainstate
|
||||||
const ChainstateManager::Options chainman_opts{
|
const ChainstateManager::Options chainman_opts{
|
||||||
.chainparams = chainparams,
|
.chainparams = chainparams,
|
||||||
|
.datadir = gArgs.GetDataDirNet(),
|
||||||
.adjusted_time_callback = NodeClock::now,
|
.adjusted_time_callback = NodeClock::now,
|
||||||
};
|
};
|
||||||
ChainstateManager chainman{chainman_opts};
|
ChainstateManager chainman{chainman_opts};
|
||||||
|
|||||||
+16
-16
@@ -127,40 +127,40 @@ static leveldb::Options GetOptions(size_t nCacheSize)
|
|||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate)
|
CDBWrapper::CDBWrapper(const DBParams& params)
|
||||||
: m_name{fs::PathToString(path.stem())}, m_path{path}, m_is_memory{fMemory}
|
: m_name{fs::PathToString(params.path.stem())}, m_path{params.path}, m_is_memory{params.memory_only}
|
||||||
{
|
{
|
||||||
penv = nullptr;
|
penv = nullptr;
|
||||||
readoptions.verify_checksums = true;
|
readoptions.verify_checksums = true;
|
||||||
iteroptions.verify_checksums = true;
|
iteroptions.verify_checksums = true;
|
||||||
iteroptions.fill_cache = false;
|
iteroptions.fill_cache = false;
|
||||||
syncoptions.sync = true;
|
syncoptions.sync = true;
|
||||||
options = GetOptions(nCacheSize);
|
options = GetOptions(params.cache_bytes);
|
||||||
options.create_if_missing = true;
|
options.create_if_missing = true;
|
||||||
if (fMemory) {
|
if (params.memory_only) {
|
||||||
penv = leveldb::NewMemEnv(leveldb::Env::Default());
|
penv = leveldb::NewMemEnv(leveldb::Env::Default());
|
||||||
options.env = penv;
|
options.env = penv;
|
||||||
} else {
|
} else {
|
||||||
if (fWipe) {
|
if (params.wipe_data) {
|
||||||
LogPrintf("Wiping LevelDB in %s\n", fs::PathToString(path));
|
LogPrintf("Wiping LevelDB in %s\n", fs::PathToString(params.path));
|
||||||
leveldb::Status result = leveldb::DestroyDB(fs::PathToString(path), options);
|
leveldb::Status result = leveldb::DestroyDB(fs::PathToString(params.path), options);
|
||||||
dbwrapper_private::HandleError(result);
|
dbwrapper_private::HandleError(result);
|
||||||
}
|
}
|
||||||
TryCreateDirectories(path);
|
TryCreateDirectories(params.path);
|
||||||
LogPrintf("Opening LevelDB in %s\n", fs::PathToString(path));
|
LogPrintf("Opening LevelDB in %s\n", fs::PathToString(params.path));
|
||||||
}
|
}
|
||||||
// PathToString() return value is safe to pass to leveldb open function,
|
// PathToString() return value is safe to pass to leveldb open function,
|
||||||
// because on POSIX leveldb passes the byte string directly to ::open(), and
|
// because on POSIX leveldb passes the byte string directly to ::open(), and
|
||||||
// on Windows it converts from UTF-8 to UTF-16 before calling ::CreateFileW
|
// on Windows it converts from UTF-8 to UTF-16 before calling ::CreateFileW
|
||||||
// (see env_posix.cc and env_windows.cc).
|
// (see env_posix.cc and env_windows.cc).
|
||||||
leveldb::Status status = leveldb::DB::Open(options, fs::PathToString(path), &pdb);
|
leveldb::Status status = leveldb::DB::Open(options, fs::PathToString(params.path), &pdb);
|
||||||
dbwrapper_private::HandleError(status);
|
dbwrapper_private::HandleError(status);
|
||||||
LogPrintf("Opened LevelDB successfully\n");
|
LogPrintf("Opened LevelDB successfully\n");
|
||||||
|
|
||||||
if (gArgs.GetBoolArg("-forcecompactdb", false)) {
|
if (params.options.force_compact) {
|
||||||
LogPrintf("Starting database compaction of %s\n", fs::PathToString(path));
|
LogPrintf("Starting database compaction of %s\n", fs::PathToString(params.path));
|
||||||
pdb->CompactRange(nullptr, nullptr);
|
pdb->CompactRange(nullptr, nullptr);
|
||||||
LogPrintf("Finished database compaction of %s\n", fs::PathToString(path));
|
LogPrintf("Finished database compaction of %s\n", fs::PathToString(params.path));
|
||||||
}
|
}
|
||||||
|
|
||||||
// The base-case obfuscation key, which is a noop.
|
// The base-case obfuscation key, which is a noop.
|
||||||
@@ -168,7 +168,7 @@ CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bo
|
|||||||
|
|
||||||
bool key_exists = Read(OBFUSCATE_KEY_KEY, obfuscate_key);
|
bool key_exists = Read(OBFUSCATE_KEY_KEY, obfuscate_key);
|
||||||
|
|
||||||
if (!key_exists && obfuscate && IsEmpty()) {
|
if (!key_exists && params.obfuscate && IsEmpty()) {
|
||||||
// Initialize non-degenerate obfuscation if it won't upset
|
// Initialize non-degenerate obfuscation if it won't upset
|
||||||
// existing, non-obfuscated data.
|
// existing, non-obfuscated data.
|
||||||
std::vector<unsigned char> new_key = CreateObfuscateKey();
|
std::vector<unsigned char> new_key = CreateObfuscateKey();
|
||||||
@@ -177,10 +177,10 @@ CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bo
|
|||||||
Write(OBFUSCATE_KEY_KEY, new_key);
|
Write(OBFUSCATE_KEY_KEY, new_key);
|
||||||
obfuscate_key = new_key;
|
obfuscate_key = new_key;
|
||||||
|
|
||||||
LogPrintf("Wrote new obfuscate key for %s: %s\n", fs::PathToString(path), HexStr(obfuscate_key));
|
LogPrintf("Wrote new obfuscate key for %s: %s\n", fs::PathToString(params.path), HexStr(obfuscate_key));
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPrintf("Using obfuscation key for %s: %s\n", fs::PathToString(path), HexStr(obfuscate_key));
|
LogPrintf("Using obfuscation key for %s: %s\n", fs::PathToString(params.path), HexStr(obfuscate_key));
|
||||||
}
|
}
|
||||||
|
|
||||||
CDBWrapper::~CDBWrapper()
|
CDBWrapper::~CDBWrapper()
|
||||||
|
|||||||
+24
-9
@@ -31,6 +31,29 @@ class Env;
|
|||||||
static const size_t DBWRAPPER_PREALLOC_KEY_SIZE = 64;
|
static const size_t DBWRAPPER_PREALLOC_KEY_SIZE = 64;
|
||||||
static const size_t DBWRAPPER_PREALLOC_VALUE_SIZE = 1024;
|
static const size_t DBWRAPPER_PREALLOC_VALUE_SIZE = 1024;
|
||||||
|
|
||||||
|
//! User-controlled performance and debug options.
|
||||||
|
struct DBOptions {
|
||||||
|
//! Compact database on startup.
|
||||||
|
bool force_compact = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Application-specific storage settings.
|
||||||
|
struct DBParams {
|
||||||
|
//! Location in the filesystem where leveldb data will be stored.
|
||||||
|
fs::path path;
|
||||||
|
//! Configures various leveldb cache settings.
|
||||||
|
size_t cache_bytes;
|
||||||
|
//! If true, use leveldb's memory environment.
|
||||||
|
bool memory_only = false;
|
||||||
|
//! If true, remove all existing data.
|
||||||
|
bool wipe_data = false;
|
||||||
|
//! If true, store data obfuscated via simple XOR. If false, XOR with a
|
||||||
|
//! zero'd byte array.
|
||||||
|
bool obfuscate = false;
|
||||||
|
//! Passed-through options.
|
||||||
|
DBOptions options{};
|
||||||
|
};
|
||||||
|
|
||||||
class dbwrapper_error : public std::runtime_error
|
class dbwrapper_error : public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -230,15 +253,7 @@ private:
|
|||||||
bool m_is_memory;
|
bool m_is_memory;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
CDBWrapper(const DBParams& params);
|
||||||
* @param[in] path Location in the filesystem where leveldb data will be stored.
|
|
||||||
* @param[in] nCacheSize Configures various leveldb cache settings.
|
|
||||||
* @param[in] fMemory If true, use leveldb's memory environment.
|
|
||||||
* @param[in] fWipe If true, remove all existing data.
|
|
||||||
* @param[in] obfuscate If true, store data obfuscated via simple XOR. If false, XOR
|
|
||||||
* with a zero'd byte array.
|
|
||||||
*/
|
|
||||||
CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false, bool obfuscate = false);
|
|
||||||
~CDBWrapper();
|
~CDBWrapper();
|
||||||
|
|
||||||
CDBWrapper(const CDBWrapper&) = delete;
|
CDBWrapper(const CDBWrapper&) = delete;
|
||||||
|
|||||||
+8
-1
@@ -8,6 +8,7 @@
|
|||||||
#include <kernel/chain.h>
|
#include <kernel/chain.h>
|
||||||
#include <node/blockstorage.h>
|
#include <node/blockstorage.h>
|
||||||
#include <node/context.h>
|
#include <node/context.h>
|
||||||
|
#include <node/database_args.h>
|
||||||
#include <node/interface_ui.h>
|
#include <node/interface_ui.h>
|
||||||
#include <shutdown.h>
|
#include <shutdown.h>
|
||||||
#include <tinyformat.h>
|
#include <tinyformat.h>
|
||||||
@@ -48,7 +49,13 @@ CBlockLocator GetLocator(interfaces::Chain& chain, const uint256& block_hash)
|
|||||||
}
|
}
|
||||||
|
|
||||||
BaseIndex::DB::DB(const fs::path& path, size_t n_cache_size, bool f_memory, bool f_wipe, bool f_obfuscate) :
|
BaseIndex::DB::DB(const fs::path& path, size_t n_cache_size, bool f_memory, bool f_wipe, bool f_obfuscate) :
|
||||||
CDBWrapper(path, n_cache_size, f_memory, f_wipe, f_obfuscate)
|
CDBWrapper{DBParams{
|
||||||
|
.path = path,
|
||||||
|
.cache_bytes = n_cache_size,
|
||||||
|
.memory_only = f_memory,
|
||||||
|
.wipe_data = f_wipe,
|
||||||
|
.obfuscate = f_obfuscate,
|
||||||
|
.options = [] { DBOptions options; node::ReadDatabaseArgs(gArgs, options); return options; }()}}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool BaseIndex::DB::ReadBestBlock(CBlockLocator& locator) const
|
bool BaseIndex::DB::ReadBestBlock(CBlockLocator& locator) const
|
||||||
|
|||||||
@@ -1046,6 +1046,7 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
|
|||||||
{
|
{
|
||||||
ChainstateManager::Options chainman_opts_dummy{
|
ChainstateManager::Options chainman_opts_dummy{
|
||||||
.chainparams = chainparams,
|
.chainparams = chainparams,
|
||||||
|
.datadir = args.GetDataDirNet(),
|
||||||
};
|
};
|
||||||
if (const auto error{ApplyArgsManOptions(args, chainman_opts_dummy)}) {
|
if (const auto error{ApplyArgsManOptions(args, chainman_opts_dummy)}) {
|
||||||
return InitError(*error);
|
return InitError(*error);
|
||||||
@@ -1444,6 +1445,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||||||
bool fReindexChainState = args.GetBoolArg("-reindex-chainstate", false);
|
bool fReindexChainState = args.GetBoolArg("-reindex-chainstate", false);
|
||||||
ChainstateManager::Options chainman_opts{
|
ChainstateManager::Options chainman_opts{
|
||||||
.chainparams = chainparams,
|
.chainparams = chainparams,
|
||||||
|
.datadir = args.GetDataDirNet(),
|
||||||
.adjusted_time_callback = GetAdjustedTime,
|
.adjusted_time_callback = GetAdjustedTime,
|
||||||
};
|
};
|
||||||
Assert(!ApplyArgsManOptions(args, chainman_opts)); // no error can happen, already checked in AppInitParameterInteraction
|
Assert(!ApplyArgsManOptions(args, chainman_opts)); // no error can happen, already checked in AppInitParameterInteraction
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#define BITCOIN_KERNEL_CHAINSTATEMANAGER_OPTS_H
|
#define BITCOIN_KERNEL_CHAINSTATEMANAGER_OPTS_H
|
||||||
|
|
||||||
#include <arith_uint256.h>
|
#include <arith_uint256.h>
|
||||||
|
#include <dbwrapper.h>
|
||||||
|
#include <txdb.h>
|
||||||
#include <uint256.h>
|
#include <uint256.h>
|
||||||
#include <util/time.h>
|
#include <util/time.h>
|
||||||
|
|
||||||
@@ -27,6 +29,7 @@ namespace kernel {
|
|||||||
*/
|
*/
|
||||||
struct ChainstateManagerOpts {
|
struct ChainstateManagerOpts {
|
||||||
const CChainParams& chainparams;
|
const CChainParams& chainparams;
|
||||||
|
fs::path datadir;
|
||||||
const std::function<NodeClock::time_point()> adjusted_time_callback{nullptr};
|
const std::function<NodeClock::time_point()> adjusted_time_callback{nullptr};
|
||||||
std::optional<bool> check_block_index{};
|
std::optional<bool> check_block_index{};
|
||||||
bool checkpoints_enabled{DEFAULT_CHECKPOINTS_ENABLED};
|
bool checkpoints_enabled{DEFAULT_CHECKPOINTS_ENABLED};
|
||||||
@@ -36,6 +39,9 @@ struct ChainstateManagerOpts {
|
|||||||
std::optional<uint256> assumed_valid_block{};
|
std::optional<uint256> assumed_valid_block{};
|
||||||
//! If the tip is older than this, the node is considered to be in initial block download.
|
//! If the tip is older than this, the node is considered to be in initial block download.
|
||||||
std::chrono::seconds max_tip_age{DEFAULT_MAX_TIP_AGE};
|
std::chrono::seconds max_tip_age{DEFAULT_MAX_TIP_AGE};
|
||||||
|
DBOptions block_tree_db{};
|
||||||
|
DBOptions coins_db{};
|
||||||
|
CoinsViewOptions coins_view{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
|
|||||||
@@ -64,7 +64,12 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
|
|||||||
// new CBlockTreeDB tries to delete the existing file, which
|
// new CBlockTreeDB tries to delete the existing file, which
|
||||||
// fails if it's still open from the previous loop. Close it first:
|
// fails if it's still open from the previous loop. Close it first:
|
||||||
pblocktree.reset();
|
pblocktree.reset();
|
||||||
pblocktree.reset(new CBlockTreeDB(cache_sizes.block_tree_db, options.block_tree_db_in_memory, options.reindex));
|
pblocktree = std::make_unique<CBlockTreeDB>(DBParams{
|
||||||
|
.path = chainman.m_options.datadir / "blocks" / "index",
|
||||||
|
.cache_bytes = static_cast<size_t>(cache_sizes.block_tree_db),
|
||||||
|
.memory_only = options.block_tree_db_in_memory,
|
||||||
|
.wipe_data = options.reindex,
|
||||||
|
.options = chainman.m_options.block_tree_db});
|
||||||
|
|
||||||
if (options.reindex) {
|
if (options.reindex) {
|
||||||
pblocktree->WriteReindexing(true);
|
pblocktree->WriteReindexing(true);
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
#include <node/chainstatemanager_args.h>
|
#include <node/chainstatemanager_args.h>
|
||||||
|
|
||||||
#include <arith_uint256.h>
|
#include <arith_uint256.h>
|
||||||
|
#include <kernel/chainstatemanager_opts.h>
|
||||||
|
#include <node/coins_view_args.h>
|
||||||
|
#include <node/database_args.h>
|
||||||
#include <tinyformat.h>
|
#include <tinyformat.h>
|
||||||
#include <uint256.h>
|
#include <uint256.h>
|
||||||
#include <util/strencodings.h>
|
#include <util/strencodings.h>
|
||||||
@@ -34,6 +37,10 @@ std::optional<bilingual_str> ApplyArgsManOptions(const ArgsManager& args, Chains
|
|||||||
|
|
||||||
if (auto value{args.GetIntArg("-maxtipage")}) opts.max_tip_age = std::chrono::seconds{*value};
|
if (auto value{args.GetIntArg("-maxtipage")}) opts.max_tip_age = std::chrono::seconds{*value};
|
||||||
|
|
||||||
|
ReadDatabaseArgs(args, opts.block_tree_db);
|
||||||
|
ReadDatabaseArgs(args, opts.coins_db);
|
||||||
|
ReadCoinsViewArgs(args, opts.coins_view);
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
} // namespace node
|
} // namespace node
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright (c) 2022 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <node/coins_view_args.h>
|
||||||
|
|
||||||
|
#include <txdb.h>
|
||||||
|
#include <util/system.h>
|
||||||
|
|
||||||
|
namespace node {
|
||||||
|
void ReadCoinsViewArgs(const ArgsManager& args, CoinsViewOptions& options)
|
||||||
|
{
|
||||||
|
if (auto value = args.GetIntArg("-dbbatchsize")) options.batch_write_bytes = *value;
|
||||||
|
if (auto value = args.GetIntArg("-dbcrashratio")) options.simulate_crash_ratio = *value;
|
||||||
|
}
|
||||||
|
} // namespace node
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// Copyright (c) 2022 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#ifndef BITCOIN_NODE_COINS_VIEW_ARGS_H
|
||||||
|
#define BITCOIN_NODE_COINS_VIEW_ARGS_H
|
||||||
|
|
||||||
|
class ArgsManager;
|
||||||
|
struct CoinsViewOptions;
|
||||||
|
|
||||||
|
namespace node {
|
||||||
|
void ReadCoinsViewArgs(const ArgsManager& args, CoinsViewOptions& options);
|
||||||
|
} // namespace node
|
||||||
|
|
||||||
|
#endif // BITCOIN_NODE_COINS_VIEW_ARGS_H
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (c) 2022 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <node/database_args.h>
|
||||||
|
|
||||||
|
#include <dbwrapper.h>
|
||||||
|
#include <util/system.h>
|
||||||
|
|
||||||
|
namespace node {
|
||||||
|
void ReadDatabaseArgs(const ArgsManager& args, DBOptions& options)
|
||||||
|
{
|
||||||
|
// Settings here apply to all databases (chainstate, blocks, and index
|
||||||
|
// databases), but it'd be easy to parse database-specific options by adding
|
||||||
|
// a database_type string or enum parameter to this function.
|
||||||
|
if (auto value = args.GetBoolArg("-forcecompactdb")) options.force_compact = *value;
|
||||||
|
}
|
||||||
|
} // namespace node
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// Copyright (c) 2022 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#ifndef BITCOIN_NODE_DATABASE_ARGS_H
|
||||||
|
#define BITCOIN_NODE_DATABASE_ARGS_H
|
||||||
|
|
||||||
|
class ArgsManager;
|
||||||
|
struct DBOptions;
|
||||||
|
|
||||||
|
namespace node {
|
||||||
|
void ReadDatabaseArgs(const ArgsManager& args, DBOptions& options);
|
||||||
|
} // namespace node
|
||||||
|
|
||||||
|
#endif // BITCOIN_NODE_DATABASE_ARGS_H
|
||||||
@@ -278,7 +278,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
|
|||||||
CCoinsViewTest base;
|
CCoinsViewTest base;
|
||||||
SimulationTest(&base, false);
|
SimulationTest(&base, false);
|
||||||
|
|
||||||
CCoinsViewDB db_base{"test", /*nCacheSize=*/1 << 23, /*fMemory=*/true, /*fWipe=*/false};
|
CCoinsViewDB db_base{{.path = "test", .cache_bytes = 1 << 23, .memory_only = true}, {}};
|
||||||
SimulationTest(&db_base, true);
|
SimulationTest(&db_base, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1064,7 +1064,7 @@ void TestFlushBehavior(
|
|||||||
BOOST_AUTO_TEST_CASE(ccoins_flush_behavior)
|
BOOST_AUTO_TEST_CASE(ccoins_flush_behavior)
|
||||||
{
|
{
|
||||||
// Create two in-memory caches atop a leveldb view.
|
// Create two in-memory caches atop a leveldb view.
|
||||||
CCoinsViewDB base{"test", /*nCacheSize=*/ 1 << 23, /*fMemory=*/ true, /*fWipe=*/ false};
|
CCoinsViewDB base{{.path = "test", .cache_bytes = 1 << 23, .memory_only = true}, {}};
|
||||||
std::vector<std::unique_ptr<CCoinsViewCacheTest>> caches;
|
std::vector<std::unique_ptr<CCoinsViewCacheTest>> caches;
|
||||||
caches.push_back(std::make_unique<CCoinsViewCacheTest>(&base));
|
caches.push_back(std::make_unique<CCoinsViewCacheTest>(&base));
|
||||||
caches.push_back(std::make_unique<CCoinsViewCacheTest>(caches.back().get()));
|
caches.push_back(std::make_unique<CCoinsViewCacheTest>(caches.back().get()));
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper)
|
|||||||
// Perform tests both obfuscated and non-obfuscated.
|
// Perform tests both obfuscated and non-obfuscated.
|
||||||
for (const bool obfuscate : {false, true}) {
|
for (const bool obfuscate : {false, true}) {
|
||||||
fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_obfuscate_true" : "dbwrapper_obfuscate_false");
|
fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_obfuscate_true" : "dbwrapper_obfuscate_false");
|
||||||
CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
|
CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = true, .wipe_data = false, .obfuscate = obfuscate});
|
||||||
uint8_t key{'k'};
|
uint8_t key{'k'};
|
||||||
uint256 in = InsecureRand256();
|
uint256 in = InsecureRand256();
|
||||||
uint256 res;
|
uint256 res;
|
||||||
@@ -47,7 +47,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_basic_data)
|
|||||||
// Perform tests both obfuscated and non-obfuscated.
|
// Perform tests both obfuscated and non-obfuscated.
|
||||||
for (bool obfuscate : {false, true}) {
|
for (bool obfuscate : {false, true}) {
|
||||||
fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_1_obfuscate_true" : "dbwrapper_1_obfuscate_false");
|
fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_1_obfuscate_true" : "dbwrapper_1_obfuscate_false");
|
||||||
CDBWrapper dbw(ph, (1 << 20), false, true, obfuscate);
|
CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = false, .wipe_data = true, .obfuscate = obfuscate});
|
||||||
|
|
||||||
uint256 res;
|
uint256 res;
|
||||||
uint32_t res_uint_32;
|
uint32_t res_uint_32;
|
||||||
@@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch)
|
|||||||
// Perform tests both obfuscated and non-obfuscated.
|
// Perform tests both obfuscated and non-obfuscated.
|
||||||
for (const bool obfuscate : {false, true}) {
|
for (const bool obfuscate : {false, true}) {
|
||||||
fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_batch_obfuscate_true" : "dbwrapper_batch_obfuscate_false");
|
fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_batch_obfuscate_true" : "dbwrapper_batch_obfuscate_false");
|
||||||
CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
|
CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = true, .wipe_data = false, .obfuscate = obfuscate});
|
||||||
|
|
||||||
uint8_t key{'i'};
|
uint8_t key{'i'};
|
||||||
uint256 in = InsecureRand256();
|
uint256 in = InsecureRand256();
|
||||||
@@ -164,7 +164,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator)
|
|||||||
// Perform tests both obfuscated and non-obfuscated.
|
// Perform tests both obfuscated and non-obfuscated.
|
||||||
for (const bool obfuscate : {false, true}) {
|
for (const bool obfuscate : {false, true}) {
|
||||||
fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_iterator_obfuscate_true" : "dbwrapper_iterator_obfuscate_false");
|
fs::path ph = m_args.GetDataDirBase() / (obfuscate ? "dbwrapper_iterator_obfuscate_true" : "dbwrapper_iterator_obfuscate_false");
|
||||||
CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
|
CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = true, .wipe_data = false, .obfuscate = obfuscate});
|
||||||
|
|
||||||
// The two keys are intentionally chosen for ordering
|
// The two keys are intentionally chosen for ordering
|
||||||
uint8_t key{'j'};
|
uint8_t key{'j'};
|
||||||
@@ -207,7 +207,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
|
|||||||
fs::create_directories(ph);
|
fs::create_directories(ph);
|
||||||
|
|
||||||
// Set up a non-obfuscated wrapper to write some initial data.
|
// Set up a non-obfuscated wrapper to write some initial data.
|
||||||
std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(ph, (1 << 10), false, false, false);
|
std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(DBParams{.path = ph, .cache_bytes = 1 << 10, .memory_only = false, .wipe_data = false, .obfuscate = false});
|
||||||
uint8_t key{'k'};
|
uint8_t key{'k'};
|
||||||
uint256 in = InsecureRand256();
|
uint256 in = InsecureRand256();
|
||||||
uint256 res;
|
uint256 res;
|
||||||
@@ -220,7 +220,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
|
|||||||
dbw.reset();
|
dbw.reset();
|
||||||
|
|
||||||
// Now, set up another wrapper that wants to obfuscate the same directory
|
// Now, set up another wrapper that wants to obfuscate the same directory
|
||||||
CDBWrapper odbw(ph, (1 << 10), false, false, true);
|
CDBWrapper odbw({.path = ph, .cache_bytes = 1 << 10, .memory_only = false, .wipe_data = false, .obfuscate = true});
|
||||||
|
|
||||||
// Check that the key/val we wrote with unobfuscated wrapper exists and
|
// Check that the key/val we wrote with unobfuscated wrapper exists and
|
||||||
// is readable.
|
// is readable.
|
||||||
@@ -248,7 +248,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex)
|
|||||||
fs::create_directories(ph);
|
fs::create_directories(ph);
|
||||||
|
|
||||||
// Set up a non-obfuscated wrapper to write some initial data.
|
// Set up a non-obfuscated wrapper to write some initial data.
|
||||||
std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(ph, (1 << 10), false, false, false);
|
std::unique_ptr<CDBWrapper> dbw = std::make_unique<CDBWrapper>(DBParams{.path = ph, .cache_bytes = 1 << 10, .memory_only = false, .wipe_data = false, .obfuscate = false});
|
||||||
uint8_t key{'k'};
|
uint8_t key{'k'};
|
||||||
uint256 in = InsecureRand256();
|
uint256 in = InsecureRand256();
|
||||||
uint256 res;
|
uint256 res;
|
||||||
@@ -261,7 +261,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex)
|
|||||||
dbw.reset();
|
dbw.reset();
|
||||||
|
|
||||||
// Simulate a -reindex by wiping the existing data store
|
// Simulate a -reindex by wiping the existing data store
|
||||||
CDBWrapper odbw(ph, (1 << 10), false, true, true);
|
CDBWrapper odbw({.path = ph, .cache_bytes = 1 << 10, .memory_only = false, .wipe_data = true, .obfuscate = true});
|
||||||
|
|
||||||
// Check that the key/val we wrote with unobfuscated wrapper doesn't exist
|
// Check that the key/val we wrote with unobfuscated wrapper doesn't exist
|
||||||
uint256 res2;
|
uint256 res2;
|
||||||
@@ -280,7 +280,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex)
|
|||||||
BOOST_AUTO_TEST_CASE(iterator_ordering)
|
BOOST_AUTO_TEST_CASE(iterator_ordering)
|
||||||
{
|
{
|
||||||
fs::path ph = m_args.GetDataDirBase() / "iterator_ordering";
|
fs::path ph = m_args.GetDataDirBase() / "iterator_ordering";
|
||||||
CDBWrapper dbw(ph, (1 << 20), true, false, false);
|
CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = true, .wipe_data = false, .obfuscate = false});
|
||||||
for (int x=0x00; x<256; ++x) {
|
for (int x=0x00; x<256; ++x) {
|
||||||
uint8_t key = x;
|
uint8_t key = x;
|
||||||
uint32_t value = x*x;
|
uint32_t value = x*x;
|
||||||
@@ -348,7 +348,7 @@ struct StringContentsSerializer {
|
|||||||
BOOST_AUTO_TEST_CASE(iterator_string_ordering)
|
BOOST_AUTO_TEST_CASE(iterator_string_ordering)
|
||||||
{
|
{
|
||||||
fs::path ph = m_args.GetDataDirBase() / "iterator_string_ordering";
|
fs::path ph = m_args.GetDataDirBase() / "iterator_string_ordering";
|
||||||
CDBWrapper dbw(ph, (1 << 20), true, false, false);
|
CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20, .memory_only = true, .wipe_data = false, .obfuscate = false});
|
||||||
for (int x = 0; x < 10; ++x) {
|
for (int x = 0; x < 10; ++x) {
|
||||||
for (int y = 0; y < 10; ++y) {
|
for (int y = 0; y < 10; ++y) {
|
||||||
std::string key{ToString(x)};
|
std::string key{ToString(x)};
|
||||||
@@ -390,7 +390,7 @@ BOOST_AUTO_TEST_CASE(unicodepath)
|
|||||||
// the ANSI CreateDirectoryA call and the code page isn't UTF8.
|
// the ANSI CreateDirectoryA call and the code page isn't UTF8.
|
||||||
// It will succeed if created with CreateDirectoryW.
|
// It will succeed if created with CreateDirectoryW.
|
||||||
fs::path ph = m_args.GetDataDirBase() / "test_runner_₿_🏃_20191128_104644";
|
fs::path ph = m_args.GetDataDirBase() / "test_runner_₿_🏃_20191128_104644";
|
||||||
CDBWrapper dbw(ph, (1 << 20));
|
CDBWrapper dbw({.path = ph, .cache_bytes = 1 << 20});
|
||||||
|
|
||||||
fs::path lockPath = ph / "LOCK";
|
fs::path lockPath = ph / "LOCK";
|
||||||
BOOST_CHECK(fs::exists(lockPath));
|
BOOST_CHECK(fs::exists(lockPath));
|
||||||
|
|||||||
@@ -180,11 +180,15 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve
|
|||||||
|
|
||||||
const ChainstateManager::Options chainman_opts{
|
const ChainstateManager::Options chainman_opts{
|
||||||
.chainparams = chainparams,
|
.chainparams = chainparams,
|
||||||
|
.datadir = m_args.GetDataDirNet(),
|
||||||
.adjusted_time_callback = GetAdjustedTime,
|
.adjusted_time_callback = GetAdjustedTime,
|
||||||
.check_block_index = true,
|
.check_block_index = true,
|
||||||
};
|
};
|
||||||
m_node.chainman = std::make_unique<ChainstateManager>(chainman_opts);
|
m_node.chainman = std::make_unique<ChainstateManager>(chainman_opts);
|
||||||
m_node.chainman->m_blockman.m_block_tree_db = std::make_unique<CBlockTreeDB>(m_cache_sizes.block_tree_db, true);
|
m_node.chainman->m_blockman.m_block_tree_db = std::make_unique<CBlockTreeDB>(DBParams{
|
||||||
|
.path = m_args.GetDataDirNet() / "blocks" / "index",
|
||||||
|
.cache_bytes = static_cast<size_t>(m_cache_sizes.block_tree_db),
|
||||||
|
.memory_only = true});
|
||||||
|
|
||||||
constexpr int script_check_threads = 2;
|
constexpr int script_check_threads = 2;
|
||||||
StartScriptCheckWorkerThreads(script_check_threads);
|
StartScriptCheckWorkerThreads(script_check_threads);
|
||||||
|
|||||||
@@ -374,6 +374,7 @@ struct SnapshotTestSetup : TestChain100Setup {
|
|||||||
BOOST_CHECK_EQUAL(chainman.GetAll().size(), 0);
|
BOOST_CHECK_EQUAL(chainman.GetAll().size(), 0);
|
||||||
const ChainstateManager::Options chainman_opts{
|
const ChainstateManager::Options chainman_opts{
|
||||||
.chainparams = ::Params(),
|
.chainparams = ::Params(),
|
||||||
|
.datadir = m_args.GetDataDirNet(),
|
||||||
.adjusted_time_callback = GetAdjustedTime,
|
.adjusted_time_callback = GetAdjustedTime,
|
||||||
};
|
};
|
||||||
// For robustness, ensure the old manager is destroyed before creating a
|
// For robustness, ensure the old manager is destroyed before creating a
|
||||||
|
|||||||
+11
-15
@@ -70,21 +70,22 @@ struct CoinEntry {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
CCoinsViewDB::CCoinsViewDB(fs::path ldb_path, size_t nCacheSize, bool fMemory, bool fWipe) :
|
CCoinsViewDB::CCoinsViewDB(DBParams db_params, CoinsViewOptions options) :
|
||||||
m_db(std::make_unique<CDBWrapper>(ldb_path, nCacheSize, fMemory, fWipe, true)),
|
m_db_params{std::move(db_params)},
|
||||||
m_ldb_path(ldb_path),
|
m_options{std::move(options)},
|
||||||
m_is_memory(fMemory) { }
|
m_db{std::make_unique<CDBWrapper>(m_db_params)} { }
|
||||||
|
|
||||||
void CCoinsViewDB::ResizeCache(size_t new_cache_size)
|
void CCoinsViewDB::ResizeCache(size_t new_cache_size)
|
||||||
{
|
{
|
||||||
// We can't do this operation with an in-memory DB since we'll lose all the coins upon
|
// We can't do this operation with an in-memory DB since we'll lose all the coins upon
|
||||||
// reset.
|
// reset.
|
||||||
if (!m_is_memory) {
|
if (!m_db_params.memory_only) {
|
||||||
// Have to do a reset first to get the original `m_db` state to release its
|
// Have to do a reset first to get the original `m_db` state to release its
|
||||||
// filesystem lock.
|
// filesystem lock.
|
||||||
m_db.reset();
|
m_db.reset();
|
||||||
m_db = std::make_unique<CDBWrapper>(
|
m_db_params.cache_bytes = new_cache_size;
|
||||||
m_ldb_path, new_cache_size, m_is_memory, /*fWipe=*/false, /*obfuscate=*/true);
|
m_db_params.wipe_data = false;
|
||||||
|
m_db = std::make_unique<CDBWrapper>(m_db_params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,8 +116,6 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, boo
|
|||||||
CDBBatch batch(*m_db);
|
CDBBatch batch(*m_db);
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
size_t changed = 0;
|
size_t changed = 0;
|
||||||
size_t batch_size = (size_t)gArgs.GetIntArg("-dbbatchsize", nDefaultDbBatchSize);
|
|
||||||
int crash_simulate = gArgs.GetIntArg("-dbcrashratio", 0);
|
|
||||||
assert(!hashBlock.IsNull());
|
assert(!hashBlock.IsNull());
|
||||||
|
|
||||||
uint256 old_tip = GetBestBlock();
|
uint256 old_tip = GetBestBlock();
|
||||||
@@ -147,13 +146,13 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, boo
|
|||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
it = erase ? mapCoins.erase(it) : std::next(it);
|
it = erase ? mapCoins.erase(it) : std::next(it);
|
||||||
if (batch.SizeEstimate() > batch_size) {
|
if (batch.SizeEstimate() > m_options.batch_write_bytes) {
|
||||||
LogPrint(BCLog::COINDB, "Writing partial batch of %.2f MiB\n", batch.SizeEstimate() * (1.0 / 1048576.0));
|
LogPrint(BCLog::COINDB, "Writing partial batch of %.2f MiB\n", batch.SizeEstimate() * (1.0 / 1048576.0));
|
||||||
m_db->WriteBatch(batch);
|
m_db->WriteBatch(batch);
|
||||||
batch.Clear();
|
batch.Clear();
|
||||||
if (crash_simulate) {
|
if (m_options.simulate_crash_ratio) {
|
||||||
static FastRandomContext rng;
|
static FastRandomContext rng;
|
||||||
if (rng.randrange(crash_simulate) == 0) {
|
if (rng.randrange(m_options.simulate_crash_ratio) == 0) {
|
||||||
LogPrintf("Simulating a crash. Goodbye.\n");
|
LogPrintf("Simulating a crash. Goodbye.\n");
|
||||||
_Exit(0);
|
_Exit(0);
|
||||||
}
|
}
|
||||||
@@ -176,9 +175,6 @@ size_t CCoinsViewDB::EstimateSize() const
|
|||||||
return m_db->EstimateSize(DB_COIN, uint8_t(DB_COIN + 1));
|
return m_db->EstimateSize(DB_COIN, uint8_t(DB_COIN + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(gArgs.GetDataDirNet() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
|
bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
|
||||||
return Read(std::make_pair(DB_BLOCK_FILES, nFile), info);
|
return Read(std::make_pair(DB_BLOCK_FILES, nFile), info);
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-8
@@ -45,18 +45,24 @@ static const int64_t max_filter_index_cache = 1024;
|
|||||||
//! Max memory allocated to coin DB specific cache (MiB)
|
//! Max memory allocated to coin DB specific cache (MiB)
|
||||||
static const int64_t nMaxCoinsDBCache = 8;
|
static const int64_t nMaxCoinsDBCache = 8;
|
||||||
|
|
||||||
|
//! User-controlled performance and debug options.
|
||||||
|
struct CoinsViewOptions {
|
||||||
|
//! Maximum database write batch size in bytes.
|
||||||
|
size_t batch_write_bytes = nDefaultDbBatchSize;
|
||||||
|
//! If non-zero, randomly exit when the database is flushed with (1/ratio)
|
||||||
|
//! probability.
|
||||||
|
int simulate_crash_ratio = 0;
|
||||||
|
};
|
||||||
|
|
||||||
/** CCoinsView backed by the coin database (chainstate/) */
|
/** CCoinsView backed by the coin database (chainstate/) */
|
||||||
class CCoinsViewDB final : public CCoinsView
|
class CCoinsViewDB final : public CCoinsView
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
DBParams m_db_params;
|
||||||
|
CoinsViewOptions m_options;
|
||||||
std::unique_ptr<CDBWrapper> m_db;
|
std::unique_ptr<CDBWrapper> m_db;
|
||||||
fs::path m_ldb_path;
|
|
||||||
bool m_is_memory;
|
|
||||||
public:
|
public:
|
||||||
/**
|
explicit CCoinsViewDB(DBParams db_params, CoinsViewOptions options);
|
||||||
* @param[in] ldb_path Location in the filesystem where leveldb data will be stored.
|
|
||||||
*/
|
|
||||||
explicit CCoinsViewDB(fs::path ldb_path, size_t nCacheSize, bool fMemory, bool fWipe);
|
|
||||||
|
|
||||||
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override;
|
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override;
|
||||||
bool HaveCoin(const COutPoint &outpoint) const override;
|
bool HaveCoin(const COutPoint &outpoint) const override;
|
||||||
@@ -80,8 +86,7 @@ public:
|
|||||||
class CBlockTreeDB : public CDBWrapper
|
class CBlockTreeDB : public CDBWrapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CBlockTreeDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
|
using CDBWrapper::CDBWrapper;
|
||||||
|
|
||||||
bool WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo);
|
bool WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo);
|
||||||
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &info);
|
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &info);
|
||||||
bool ReadLastBlockFile(int &nFile);
|
bool ReadLastBlockFile(int &nFile);
|
||||||
|
|||||||
+11
-8
@@ -1511,13 +1511,9 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
|
|||||||
return nSubsidy;
|
return nSubsidy;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoinsViews::CoinsViews(
|
CoinsViews::CoinsViews(DBParams db_params, CoinsViewOptions options)
|
||||||
fs::path ldb_name,
|
: m_dbview{std::move(db_params), std::move(options)},
|
||||||
size_t cache_size_bytes,
|
m_catcherview(&m_dbview) {}
|
||||||
bool in_memory,
|
|
||||||
bool should_wipe) : m_dbview(
|
|
||||||
gArgs.GetDataDirNet() / ldb_name, cache_size_bytes, in_memory, should_wipe),
|
|
||||||
m_catcherview(&m_dbview) {}
|
|
||||||
|
|
||||||
void CoinsViews::InitCache()
|
void CoinsViews::InitCache()
|
||||||
{
|
{
|
||||||
@@ -1546,7 +1542,14 @@ void Chainstate::InitCoinsDB(
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_coins_views = std::make_unique<CoinsViews>(
|
m_coins_views = std::make_unique<CoinsViews>(
|
||||||
leveldb_name, cache_size_bytes, in_memory, should_wipe);
|
DBParams{
|
||||||
|
.path = m_chainman.m_options.datadir / leveldb_name,
|
||||||
|
.cache_bytes = cache_size_bytes,
|
||||||
|
.memory_only = in_memory,
|
||||||
|
.wipe_data = should_wipe,
|
||||||
|
.obfuscate = true,
|
||||||
|
.options = m_chainman.m_options.coins_db},
|
||||||
|
m_chainman.m_options.coins_view);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chainstate::InitCoinsCache(size_t cache_size_bytes)
|
void Chainstate::InitCoinsCache(size_t cache_size_bytes)
|
||||||
|
|||||||
+1
-1
@@ -408,7 +408,7 @@ public:
|
|||||||
//! state to disk, which should not be done until the health of the database is verified.
|
//! state to disk, which should not be done until the health of the database is verified.
|
||||||
//!
|
//!
|
||||||
//! All arguments forwarded onto CCoinsViewDB.
|
//! All arguments forwarded onto CCoinsViewDB.
|
||||||
CoinsViews(fs::path ldb_name, size_t cache_size_bytes, bool in_memory, bool should_wipe);
|
CoinsViews(DBParams db_params, CoinsViewOptions options);
|
||||||
|
|
||||||
//! Initialize the CCoinsViewCache member.
|
//! Initialize the CCoinsViewCache member.
|
||||||
void InitCache() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
void InitCache() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||||
|
|||||||
Reference in new issue
Block a user