Inside Bitcoin
Opening the selected file…
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.
251DBContext().syncoptions.sync = true;252DBContext().options = GetOptions(params.cache_bytes, params.bloom_filter);253DBContext().options.create_if_missing = true;254DBContext().options.max_file_size = params.max_file_size;255assert(!(params.testing_env && params.memory_only));256if (params.testing_env) {257DBContext().options.env = params.testing_env;258} else if (params.memory_only) {259DBContext().penv = leveldb::NewMemEnv(leveldb::Env::Default());260DBContext().options.env = DBContext().penv;261}262if (!params.memory_only) {263if (params.wipe_data) {264LogInfo("Wiping LevelDB in %s", fs::PathToString(params.path));265leveldb::Status result = leveldb::DestroyDB(fs::PathToString(params.path), DBContext().options);266HandleError(result);267}268if (!params.testing_env) {269TryCreateDirectories(params.path);270}271LogInfo("Opening LevelDB in %s", fs::PathToString(params.path));272}273// PathToString() return value is safe to pass to leveldb open function,274// because on POSIX leveldb passes the byte string directly to ::open(), and275// on Windows it converts from UTF-8 to UTF-16 before calling ::CreateFileW276// (see env_posix.cc and env_windows.cc).277leveldb::Status status = leveldb::DB::Open(DBContext().options, fs::PathToString(params.path), &DBContext().pdb);278HandleError(status);279LogInfo("Opened LevelDB successfully");281if (params.options.force_compact) {282LogInfo("Starting database compaction of %s", fs::PathToString(params.path));283CompactFull();284LogInfo("Finished database compaction of %s", fs::PathToString(params.path));285}287if (!Read(OBFUSCATION_KEY, m_obfuscation) && params.obfuscate && IsEmpty()) {288// Generate and write the new obfuscation key.289const Obfuscation obfuscation{FastRandomContext{}.randbytes<Obfuscation::KEY_SIZE>()};290assert(!m_obfuscation); // Make sure the key is written without obfuscation.291Write(OBFUSCATION_KEY, obfuscation);292m_obfuscation = obfuscation;293LogInfo("Wrote new obfuscation key for %s: %s", fs::PathToString(params.path), m_obfuscation.HexKey());294}295LogInfo("Using obfuscation key for %s: %s", fs::PathToString(params.path), m_obfuscation.HexKey());296}298CDBWrapper::~CDBWrapper()299{300delete DBContext().pdb;301DBContext().pdb = nullptr;302delete DBContext().options.filter_policy;303DBContext().options.filter_policy = nullptr;304delete DBContext().options.info_log;305DBContext().options.info_log = nullptr;306delete DBContext().options.block_cache;307DBContext().options.block_cache = nullptr;308delete DBContext().penv;309DBContext().options.env = nullptr;310}312void CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync)313{314const bool log_memory = util::log::ShouldDebugLog(BCLog::LEVELDB);315double mem_before = 0;316if (log_memory) {317mem_before = DynamicMemoryUsage() / double(1_MiB);318}319leveldb::Status status = DBContext().pdb->Write(fSync ? DBContext().syncoptions : DBContext().writeoptions, &batch.m_impl_batch->batch);320HandleError(status);321if (log_memory) {322double mem_after{DynamicMemoryUsage() / double(1_MiB)};323LogDebug(BCLog::LEVELDB, "WriteBatch memory usage: db=%s, before=%.1fMiB, after=%.1fMiB\n",324m_name, mem_before, mem_after);325}326}328std::optional<std::string> CDBWrapper::GetProperty(const std::string& property) const329{330if (std::string value; DBContext().pdb->GetProperty(property, &value)) return value;331return std::nullopt;332}334void CDBWrapper::CompactFull() { DBContext().pdb->CompactRange(nullptr, nullptr); }336size_t CDBWrapper::DynamicMemoryUsage() const337{338std::optional<size_t> parsed;339if (auto memory{GetProperty("leveldb.approximate-memory-usage")}; !memory || !(parsed = ToIntegral<size_t>(*memory))) {340LogDebug(BCLog::LEVELDB, "Failed to get approximate-memory-usage property\n");341return 0;342}343return parsed.value();344}346std::optional<std::string> CDBWrapper::ReadImpl(std::span<const std::byte> key) const347{348leveldb::Slice slKey(CharCast(key.data()), key.size());349std::string strValue;350leveldb::Status status = DBContext().pdb->Get(DBContext().readoptions, slKey, &strValue);351if (!status.ok()) {352if (status.IsNotFound())353return std::nullopt;354LogError("LevelDB read failure: %s", status.ToString());355HandleError(status);356}357return strValue;358}360bool CDBWrapper::ExistsImpl(std::span<const std::byte> key) const361{362leveldb::Slice slKey(CharCast(key.data()), key.size());364std::string strValue;365leveldb::Status status = DBContext().pdb->Get(DBContext().readoptions, slKey, &strValue);366if (!status.ok()) {367if (status.IsNotFound())368return false;369LogError("LevelDB read failure: %s", status.ToString());370HandleError(status);371}372return true;373}375size_t CDBWrapper::EstimateSizeImpl(std::span<const std::byte> key1, std::span<const std::byte> key2) const376{377leveldb::Slice slKey1(CharCast(key1.data()), key1.size());378leveldb::Slice slKey2(CharCast(key2.data()), key2.size());379uint64_t size = 0;380leveldb::Range range(slKey1, slKey2);381DBContext().pdb->GetApproximateSizes(&range, 1, &size);382return size;383}385bool CDBWrapper::IsEmpty()386{387std::unique_ptr<CDBIterator> it(NewIterator());388it->SeekToFirst();389return !(it->Valid());390}392struct CDBIterator::IteratorImpl {393const std::unique_ptr<leveldb::Iterator> iter;395explicit IteratorImpl(leveldb::Iterator* _iter) : iter{_iter} {}396};398CDBIterator::CDBIterator(const CDBWrapper& _parent, std::unique_ptr<IteratorImpl> _piter) : parent(_parent),399m_impl_iter(std::move(_piter))400{401m_scratch.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);402}404CDBIterator* CDBWrapper::NewIterator()405{406return new CDBIterator{*this, std::make_unique<CDBIterator::IteratorImpl>(DBContext().pdb->NewIterator(DBContext().iteroptions))};407}409void CDBIterator::SeekImpl(std::span<const std::byte> key)410{411leveldb::Slice slKey(CharCast(key.data()), key.size());412m_impl_iter->iter->Seek(slKey);413}415std::span<const std::byte> CDBIterator::GetKeyImpl() const416{417// The returned span borrows from the current iterator entry and is only418// valid until the iterator is advanced.419return MakeByteSpan(m_impl_iter->iter->key());420}422std::span<const std::byte> CDBIterator::GetValueImpl() const423{424return MakeByteSpan(m_impl_iter->iter->value());425}427CDBIterator::~CDBIterator() = default;428bool CDBIterator::Valid() const { return m_impl_iter->iter->Valid(); }429void CDBIterator::SeekToFirst() { m_impl_iter->iter->SeekToFirst(); }430void CDBIterator::Next() { m_impl_iter->iter->Next(); }432namespace dbwrapper_private {434const Obfuscation& GetObfuscation(const CDBWrapper& w)435{436return w.m_obfuscation;437}439} // namespace dbwrapper_private
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.