mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-03-26 15:36:19 +01:00
Add a "tx output spender" index
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.
This commit is contained in:
13
src/init.cpp
13
src/init.cpp
@@ -27,6 +27,7 @@
|
||||
#include <index/blockfilterindex.h>
|
||||
#include <index/coinstatsindex.h>
|
||||
#include <index/txindex.h>
|
||||
#include <index/txospenderindex.h>
|
||||
#include <init/common.h>
|
||||
#include <interfaces/chain.h>
|
||||
#include <interfaces/init.h>
|
||||
@@ -360,6 +361,7 @@ void Shutdown(NodeContext& node)
|
||||
// Stop and delete all indexes only after flushing background callbacks.
|
||||
for (auto* index : node.indexes) index->Stop();
|
||||
if (g_txindex) g_txindex.reset();
|
||||
if (g_txospenderindex) g_txospenderindex.reset();
|
||||
if (g_coin_stats_index) g_coin_stats_index.reset();
|
||||
DestroyAllBlockFilterIndexes();
|
||||
node.indexes.clear(); // all instances are nullptr now
|
||||
@@ -524,6 +526,7 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
|
||||
argsman.AddArg("-shutdownnotify=<cmd>", "Execute command immediately before beginning shutdown. The need for shutdown may be urgent, so be careful not to delay it long (if the command doesn't require interaction with the server, consider having it fork into the background).", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
||||
#endif
|
||||
argsman.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
||||
argsman.AddArg("-txospenderindex", strprintf("Maintain a transaction output spender index, used by the gettxspendingprevout rpc call (default: %u)", DEFAULT_TXOSPENDERINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
|
||||
argsman.AddArg("-blockfilterindex=<type>",
|
||||
strprintf("Maintain an index of compact filters by block (default: %s, values: %s).", DEFAULT_BLOCKFILTERINDEX, ListBlockFilterTypes()) +
|
||||
" If <type> is not supplied or if <type> = 1, indexes for all known types are enabled.",
|
||||
@@ -988,6 +991,8 @@ bool AppInitParameterInteraction(const ArgsManager& args)
|
||||
if (args.GetIntArg("-prune", 0)) {
|
||||
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX))
|
||||
return InitError(_("Prune mode is incompatible with -txindex."));
|
||||
if (args.GetBoolArg("-txospenderindex", DEFAULT_TXOSPENDERINDEX))
|
||||
return InitError(_("Prune mode is incompatible with -txospenderindex."));
|
||||
if (args.GetBoolArg("-reindex-chainstate", false)) {
|
||||
return InitError(_("Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead."));
|
||||
}
|
||||
@@ -1793,6 +1798,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
|
||||
LogInfo("* Using %.1f MiB for transaction index database", index_cache_sizes.tx_index * (1.0 / 1024 / 1024));
|
||||
}
|
||||
if (args.GetBoolArg("-txospenderindex", DEFAULT_TXOSPENDERINDEX)) {
|
||||
LogInfo("* Using %.1f MiB for transaction output spender index database", index_cache_sizes.txospender_index * (1.0 / 1024 / 1024));
|
||||
}
|
||||
for (BlockFilterType filter_type : g_enabled_filter_types) {
|
||||
LogInfo("* Using %.1f MiB for %s block filter index database",
|
||||
index_cache_sizes.filter_index * (1.0 / 1024 / 1024), BlockFilterTypeName(filter_type));
|
||||
@@ -1861,6 +1869,11 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
node.indexes.emplace_back(g_txindex.get());
|
||||
}
|
||||
|
||||
if (args.GetBoolArg("-txospenderindex", DEFAULT_TXOSPENDERINDEX)) {
|
||||
g_txospenderindex = std::make_unique<TxoSpenderIndex>(interfaces::MakeChain(node), index_cache_sizes.txospender_index, false, do_reindex);
|
||||
node.indexes.emplace_back(g_txospenderindex.get());
|
||||
}
|
||||
|
||||
for (const auto& filter_type : g_enabled_filter_types) {
|
||||
InitBlockFilterIndex([&]{ return interfaces::MakeChain(node); }, filter_type, index_cache_sizes.filter_index, false, do_reindex);
|
||||
node.indexes.emplace_back(GetBlockFilterIndex(filter_type));
|
||||
|
||||
Reference in New Issue
Block a user