mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-03-03 18:26:15 +00:00
Adds an outpoint -> txid index, which can be used to find which transactions spent a given output. We use a composite key with 2 parts (suggested by @romanz): hash(spent outpoint) and tx position, with an empty value. To find the spending tx for a given outpoint, we do a prefix search (prefix being the hash of the provided outpoint), and for all keys that match this prefix we load the tx at the position specified in the key and return it, along with the block hash, if does spend the provided outpoint. To handle reorgs we just erase the keys computed from the removed block. This index is extremely useful for Lightning and more generally for layer-2 protocols that rely on chains of unpublished transactions. If enabled, this index will be used by `gettxspendingprevout` when it does not find a spending transaction in the mempool.
71 lines
2.9 KiB
C++
71 lines
2.9 KiB
C++
// Copyright (c) 2021-present 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/caches.h>
|
|
|
|
#include <common/args.h>
|
|
#include <common/system.h>
|
|
#include <index/txindex.h>
|
|
#include <index/txospenderindex.h>
|
|
#include <kernel/caches.h>
|
|
#include <logging.h>
|
|
#include <node/interface_ui.h>
|
|
#include <tinyformat.h>
|
|
#include <util/byte_units.h>
|
|
|
|
#include <algorithm>
|
|
#include <string>
|
|
|
|
// Unlike for the UTXO database, for the txindex scenario the leveldb cache make
|
|
// a meaningful difference: https://github.com/bitcoin/bitcoin/pull/8273#issuecomment-229601991
|
|
//! Max memory allocated to tx index DB specific cache in bytes.
|
|
static constexpr size_t MAX_TX_INDEX_CACHE{1024_MiB};
|
|
//! Max memory allocated to all block filter index caches combined in bytes.
|
|
static constexpr size_t MAX_FILTER_INDEX_CACHE{1024_MiB};
|
|
//! Max memory allocated to tx spenderindex DB specific cache in bytes.
|
|
static constexpr size_t MAX_TXOSPENDER_INDEX_CACHE{1024_MiB};
|
|
//! Maximum dbcache size on 32-bit systems.
|
|
static constexpr size_t MAX_32BIT_DBCACHE{1024_MiB};
|
|
|
|
namespace node {
|
|
size_t CalculateDbCacheBytes(const ArgsManager& args)
|
|
{
|
|
if (auto db_cache{args.GetIntArg("-dbcache")}) {
|
|
if (*db_cache < 0) db_cache = 0;
|
|
const uint64_t db_cache_bytes{SaturatingLeftShift<uint64_t>(*db_cache, 20)};
|
|
constexpr auto max_db_cache{sizeof(void*) == 4 ? MAX_32BIT_DBCACHE : std::numeric_limits<size_t>::max()};
|
|
return std::max<size_t>(MIN_DB_CACHE, std::min<uint64_t>(db_cache_bytes, max_db_cache));
|
|
}
|
|
return DEFAULT_DB_CACHE;
|
|
}
|
|
|
|
CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes)
|
|
{
|
|
size_t total_cache{CalculateDbCacheBytes(args)};
|
|
|
|
IndexCacheSizes index_sizes;
|
|
index_sizes.tx_index = std::min(total_cache / 8, args.GetBoolArg("-txindex", DEFAULT_TXINDEX) ? MAX_TX_INDEX_CACHE : 0);
|
|
total_cache -= index_sizes.tx_index;
|
|
index_sizes.txospender_index = std::min(total_cache / 8, args.GetBoolArg("-txospenderindex", DEFAULT_TXOSPENDERINDEX) ? MAX_TXOSPENDER_INDEX_CACHE : 0);
|
|
total_cache -= index_sizes.txospender_index;
|
|
if (n_indexes > 0) {
|
|
size_t max_cache = std::min(total_cache / 8, MAX_FILTER_INDEX_CACHE);
|
|
index_sizes.filter_index = max_cache / n_indexes;
|
|
total_cache -= index_sizes.filter_index * n_indexes;
|
|
}
|
|
return {index_sizes, kernel::CacheSizes{total_cache}};
|
|
}
|
|
|
|
void LogOversizedDbCache(const ArgsManager& args) noexcept
|
|
{
|
|
if (const auto total_ram{GetTotalRAM()}) {
|
|
const size_t db_cache{CalculateDbCacheBytes(args)};
|
|
if (ShouldWarnOversizedDbCache(db_cache, *total_ram)) {
|
|
InitWarning(bilingual_str{tfm::format(_("A %zu MiB dbcache may be too large for a system memory of only %zu MiB."),
|
|
db_cache >> 20, *total_ram >> 20)});
|
|
}
|
|
}
|
|
}
|
|
} // namespace node
|