diff --git a/doc/files.md b/doc/files.md
index a74cbd28e3..8e15fccec9 100644
--- a/doc/files.md
+++ b/doc/files.md
@@ -1,33 +1,34 @@
* banlist.dat: stores the IPs/Subnets of banned nodes
* bitcoin.conf: contains configuration settings for bitcoind or bitcoin-qt
* bitcoind.pid: stores the process id of bitcoind while running
* blocks/blk000??.dat: block data (custom, 128 MiB per file); since 0.8.0
* blocks/rev000??.dat; block undo data (custom); since 0.8.0 (format changed since pre-0.8)
* blocks/index/*; block index (LevelDB); since 0.8.0
* chainstate/*; block chain state database (LevelDB); since 0.8.0
* database/*: BDB database environment; only used for wallet since 0.8.0; moved to wallets/ directory on new installs since 0.18.7
* db.log: wallet database log file; moved to wallets/ directory on new installs since 0.18.7
* debug.log: contains debug information and general logging generated by bitcoind or bitcoin-qt
+* indexes/txindex/*: optional transaction index database (LevelDB); since 0.19.7
* mempool.dat: dump of the mempool's transactions; since 0.14.0.
* peers.dat: peer IP address database (custom format); since 0.7.0
* wallet.dat: personal wallet (BDB) with keys and transactions; moved to wallets/ directory on new installs since 0.18.7
* wallets/database/*: BDB database environment; used for wallets since 0.18.7
* wallets/db.log: wallet database log file; since 0.18.7
* wallets/wallet.dat: personal wallet (BDB) with keys and transactions; since 0.18.7
* .cookie: session RPC authentication cookie (written at start when cookie authentication is used, deleted on shutdown): since 0.12.0
* onion_private_key: cached Tor hidden service private key for `-listenonion`: since 0.12.0
Only used in pre-0.8.0
---------------------
* blktree/*; block chain index (LevelDB); since pre-0.8, replaced by blocks/index/* in 0.8.0
* coins/*; unspent transaction output database (LevelDB); since pre-0.8, replaced by chainstate/* in 0.8.0
Only used before 0.8.0
---------------------
* blkindex.dat: block chain index database (BDB); replaced by {chainstate/*,blocks/index/*,blocks/rev000??.dat} in 0.8.0
* blk000?.dat: block data (custom, 2 GiB per file); replaced by blocks/blk000??.dat in 0.8.0
Only used before 0.7.0
---------------------
* addr.dat: peer IP address database (BDB); replaced by peers.dat in 0.7.0
diff --git a/doc/release-notes.md b/doc/release-notes.md
index 8e8ff46bab..b3de6650b4 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -1,16 +1,28 @@
Bitcoin ABC version 0.19.7 is now available from:
This release includes the following features and fixes:
- `-includeconf=` can be used to include additional configuration files.
Only works inside the `bitcoin.conf` file, not inside included files or from
command-line. Multiple files may be included. Can be disabled from command-
line via `-noincludeconf`. Note that multi-argument commands like
`-includeconf` will override preceding `-noincludeconf`, i.e.
noincludeconf=1
includeconf=relative.conf
as bitcoin.conf will still include `relative.conf`.
- The `createrawtransaction` RPC will now accept an array or dictionary (kept for compatibility) for the `outputs` parameter. This means the order of transaction outputs can be specified by the client.
- The new RPC `testmempoolaccept` can be used to test acceptance of a transaction to the mempool without adding it.
- An `initialblockdownload` boolean has been added to the `getblockchaininfo` RPC to indicate whether the node is currently in IBD or not.
+
+Transaction index changes
+-------------------------
+
+The transaction index is now built separately from the main node procedure,
+meaning the `-txindex` flag can be toggled without a full reindex. If bitcoind
+is run with `-txindex` on a node that is already partially or fully synced
+without one, the transaction index will be built in the background and become
+available once caught up. When switching from running `-txindex` to running
+without the flag, the transaction index database will *not* be deleted
+automatically, meaning it could be turned back on at a later time without a full
+resync.
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 7d23b34a7f..0ebd3c9cd8 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -1,206 +1,207 @@
# Copyright (c) 2013-2016 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
TESTS += test/test_bitcoin
LOG_DRIVER = $(srcdir)/test/test-bitcoin-driver
EXTRA_DIST += test/test-bitcoin-driver
bin_PROGRAMS += test/test_bitcoin
noinst_PROGRAMS += test/test_bitcoin_fuzzy
TEST_SRCDIR = test
TEST_BINARY=test/test_bitcoin$(EXEEXT)
JSON_TEST_FILES = \
test/data/script_tests.json \
test/data/base58_keys_valid.json \
test/data/base58_encode_decode.json \
test/data/base58_keys_invalid.json \
test/data/blockfilters.json \
test/data/tx_invalid.json \
test/data/tx_valid.json \
test/data/sighash.json
RAW_TEST_FILES =
GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h)
# test_bitcoin binary #
BITCOIN_TESTS =\
test/scriptnum10.h \
test/activation_tests.cpp \
test/addrman_tests.cpp \
test/allocator_tests.cpp \
test/amount_tests.cpp \
test/arith_uint256_tests.cpp \
test/avalanche_tests.cpp \
test/base32_tests.cpp \
test/base58_tests.cpp \
test/base64_tests.cpp \
test/bip32_tests.cpp \
test/blockcheck_tests.cpp \
test/blockencodings_tests.cpp \
test/blockfilter_tests.cpp \
test/blockindex_tests.cpp \
test/blockstatus_tests.cpp \
test/bloom_tests.cpp \
test/bswap_tests.cpp \
test/cashaddr_tests.cpp \
test/cashaddrenc_tests.cpp \
test/checkdatasig_tests.cpp \
test/checkpoints_tests.cpp \
test/checkqueue_tests.cpp \
test/coins_tests.cpp \
test/compress_tests.cpp \
test/config_tests.cpp \
test/core_io_tests.cpp \
test/crypto_tests.cpp \
test/cuckoocache_tests.cpp \
test/dbwrapper_tests.cpp \
test/DoS_tests.cpp \
test/dstencode_tests.cpp \
test/excessiveblock_tests.cpp \
test/feerate_tests.cpp \
test/finalization_tests.cpp \
test/getarg_tests.cpp \
test/hash_tests.cpp \
test/inv_tests.cpp \
test/jsonutil.cpp \
test/jsonutil.h \
test/key_tests.cpp \
test/lcg_tests.cpp \
test/lcg.h \
test/limitedmap_tests.cpp \
test/main_tests.cpp \
test/mempool_tests.cpp \
test/merkle_tests.cpp \
test/miner_tests.cpp \
test/monolith_opcodes_tests.cpp \
test/multisig_tests.cpp \
test/net_tests.cpp \
test/netbase_tests.cpp \
test/pmt_tests.cpp \
test/policyestimator_tests.cpp \
test/pow_tests.cpp \
test/prevector_tests.cpp \
test/radix_tests.cpp \
test/raii_event_tests.cpp \
test/random_tests.cpp \
test/rcu_tests.cpp \
test/reverselock_tests.cpp \
test/rpc_tests.cpp \
test/rpc_server_tests.cpp \
test/rwcollection_tests.cpp \
test/sanity_tests.cpp \
test/scheduler_tests.cpp \
test/schnorr_tests.cpp \
test/script_commitment_tests.cpp \
test/script_P2SH_tests.cpp \
test/script_tests.cpp \
test/scriptflags.cpp \
test/scriptflags.h \
test/scriptnum_tests.cpp \
test/serialize_tests.cpp \
test/sigcache_tests.cpp \
test/sigencoding_tests.cpp \
test/sighash_tests.cpp \
test/sighashtype_tests.cpp \
test/sigopcount_tests.cpp \
test/sigutil.cpp \
test/sigutil.h \
test/skiplist_tests.cpp \
test/streams_tests.cpp \
test/sync_tests.cpp \
test/test_bitcoin.cpp \
test/test_bitcoin.h \
test/test_bitcoin_main.cpp \
test/timedata_tests.cpp \
test/transaction_tests.cpp \
+ test/txindex_tests.cpp \
test/txvalidationcache_tests.cpp \
test/uint256_tests.cpp \
test/undo_tests.cpp \
test/univalue_tests.cpp \
test/util_tests.cpp \
test/validation_tests.cpp \
test/work_comparator_tests.cpp \
rpc/test/server_tests.cpp
if ENABLE_WALLET
BITCOIN_TESTS += \
wallet/test/wallet_test_fixture.cpp \
wallet/test/wallet_test_fixture.h \
wallet/test/accounting_tests.cpp \
wallet/test/wallet_tests.cpp \
wallet/test/walletdb_tests.cpp \
wallet/test/wallet_crypto_tests.cpp
endif
test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(TESTDEFS) $(EVENT_CFLAGS)
test_test_bitcoin_LDADD =
if ENABLE_WALLET
test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
endif
test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \
$(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS)
test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static
if ENABLE_ZMQ
test_test_bitcoin_LDADD += $(ZMQ_LIBS)
endif
#
# test_bitcoin_fuzzy binary #
test_test_bitcoin_fuzzy_SOURCES = test/test_bitcoin_fuzzy.cpp
test_test_bitcoin_fuzzy_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
test_test_bitcoin_fuzzy_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_test_bitcoin_fuzzy_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
test_test_bitcoin_fuzzy_LDADD = \
$(LIBUNIVALUE) \
$(LIBBITCOIN_SERVER) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CONSENSUS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBSECP256K1)
test_test_bitcoin_fuzzy_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS)
#
nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
$(BITCOIN_TESTS): $(GENERATED_TEST_FILES)
CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES)
CLEANFILES += $(CLEAN_BITCOIN_TEST)
bitcoin_test: $(TEST_BINARY)
bitcoin_test_check: $(TEST_BINARY) FORCE
$(MAKE) check-TESTS TESTS=$^
bitcoin_test_clean : FORCE
rm -f $(CLEAN_BITCOIN_TEST) $(test_test_bitcoin_OBJECTS) $(TEST_BINARY)
check-local:
@echo "Running test/util/bitcoin-util-test.py..."
$(top_builddir)/test/util/bitcoin-util-test.py
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check
if EMBEDDED_UNIVALUE
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check
endif
%.json.h: %.json
@$(MKDIR_P) $(@D)
@{ \
echo "namespace json_tests{" && \
echo "static unsigned const char $(*F)[] = {" && \
$(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' && \
echo "};};"; \
} > "$@.new" && mv -f "$@.new" "$@"
@echo "Generated $@"
diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp
index 356de099e5..844412465c 100644
--- a/src/index/txindex.cpp
+++ b/src/index/txindex.cpp
@@ -1,281 +1,305 @@
// Copyright (c) 2017-2018 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
#include
#include
#include
#include
#include
#include
#include
constexpr int64_t SYNC_LOG_INTERVAL = 30; // seconds
constexpr int64_t SYNC_LOCATOR_WRITE_INTERVAL = 30; // seconds
+std::unique_ptr g_txindex;
+
template
static void FatalError(const char *fmt, const Args &... args) {
std::string strMessage = tfm::format(fmt, args...);
SetMiscWarning(strMessage);
LogPrintf("*** %s\n", strMessage);
uiInterface.ThreadSafeMessageBox(
"Error: A fatal internal error occurred, see debug.log for details", "",
CClientUIInterface::MSG_ERROR);
StartShutdown();
}
TxIndex::TxIndex(std::unique_ptr db)
: m_db(std::move(db)), m_synced(false), m_best_block_index(nullptr) {}
TxIndex::~TxIndex() {
Interrupt();
Stop();
}
bool TxIndex::Init() {
LOCK(cs_main);
// Attempt to migrate txindex from the old database to the new one. Even if
// chain_tip is null, the node could be reindexing and we still want to
// delete txindex records in the old database.
if (!m_db->MigrateData(*pblocktree, chainActive.GetLocator())) {
return false;
}
CBlockLocator locator;
if (!m_db->ReadBestBlock(locator)) {
locator.SetNull();
}
m_best_block_index = FindForkInGlobalIndex(chainActive, locator);
m_synced = m_best_block_index.load() == chainActive.Tip();
return true;
}
static const CBlockIndex *NextSyncBlock(const CBlockIndex *pindex_prev) {
AssertLockHeld(cs_main);
if (!pindex_prev) {
return chainActive.Genesis();
}
const CBlockIndex *pindex = chainActive.Next(pindex_prev);
if (pindex) {
return pindex;
}
return chainActive.Next(chainActive.FindFork(pindex_prev));
}
void TxIndex::ThreadSync() {
const CBlockIndex *pindex = m_best_block_index.load();
if (!m_synced) {
auto &config = GetConfig();
int64_t last_log_time = 0;
int64_t last_locator_write_time = 0;
while (true) {
if (m_interrupt) {
WriteBestBlock(pindex);
return;
}
{
LOCK(cs_main);
const CBlockIndex *pindex_next = NextSyncBlock(pindex);
if (!pindex_next) {
WriteBestBlock(pindex);
m_best_block_index = pindex;
m_synced = true;
break;
}
pindex = pindex_next;
}
int64_t current_time = GetTime();
if (last_log_time + SYNC_LOG_INTERVAL < current_time) {
LogPrintf("Syncing txindex with block chain from height %d\n",
pindex->nHeight);
last_log_time = current_time;
}
if (last_locator_write_time + SYNC_LOCATOR_WRITE_INTERVAL <
current_time) {
WriteBestBlock(pindex);
last_locator_write_time = current_time;
}
CBlock block;
if (!ReadBlockFromDisk(block, pindex, config)) {
FatalError("%s: Failed to read block %s from disk", __func__,
pindex->GetBlockHash().ToString());
return;
}
if (!WriteBlock(block, pindex)) {
FatalError("%s: Failed to write block %s to tx index database",
__func__, pindex->GetBlockHash().ToString());
return;
}
}
}
if (pindex) {
LogPrintf("txindex is enabled at height %d\n", pindex->nHeight);
} else {
LogPrintf("txindex is enabled\n");
}
}
bool TxIndex::WriteBlock(const CBlock &block, const CBlockIndex *pindex) {
CDiskTxPos pos(pindex->GetBlockPos(),
GetSizeOfCompactSize(block.vtx.size()));
std::vector> vPos;
vPos.reserve(block.vtx.size());
for (const auto &tx : block.vtx) {
vPos.emplace_back(tx->GetHash(), pos);
pos.nTxOffset += ::GetSerializeSize(*tx, SER_DISK, CLIENT_VERSION);
}
return m_db->WriteTxs(vPos);
}
bool TxIndex::WriteBestBlock(const CBlockIndex *block_index) {
LOCK(cs_main);
if (!m_db->WriteBestBlock(chainActive.GetLocator(block_index))) {
return error("%s: Failed to write locator to disk", __func__);
}
return true;
}
void TxIndex::BlockConnected(
const std::shared_ptr &block, const CBlockIndex *pindex,
const std::vector &txn_conflicted) {
if (!m_synced) {
return;
}
const CBlockIndex *best_block_index = m_best_block_index.load();
if (!best_block_index) {
if (pindex->nHeight != 0) {
FatalError("%s: First block connected is not the genesis block "
"(height=%d)",
__func__, pindex->nHeight);
return;
}
} else {
// Ensure block connects to an ancestor of the current best block. This
// should be the case most of the time, but may not be immediately after
// the the sync thread catches up and sets m_synced. Consider the case
// where there is a reorg and the blocks on the stale branch are in the
// ValidationInterface queue backlog even after the sync thread has
// caught up to the new chain tip. In this unlikely event, log a warning
// and let the queue clear.
if (best_block_index->GetAncestor(pindex->nHeight - 1) !=
pindex->pprev) {
LogPrintf("%s: WARNING: Block %s does not connect to an ancestor "
"of known best chain (tip=%s); not updating txindex\n",
__func__, pindex->GetBlockHash().ToString(),
best_block_index->GetBlockHash().ToString());
return;
}
}
if (WriteBlock(*block, pindex)) {
m_best_block_index = pindex;
} else {
FatalError("%s: Failed to write block %s to txindex", __func__,
pindex->GetBlockHash().ToString());
return;
}
}
void TxIndex::ChainStateFlushed(const CBlockLocator &locator) {
if (!m_synced) {
return;
}
const uint256 &locator_tip_hash = locator.vHave.front();
const CBlockIndex *locator_tip_index;
{
LOCK(cs_main);
locator_tip_index = LookupBlockIndex(locator_tip_hash);
}
if (!locator_tip_index) {
FatalError("%s: First block (hash=%s) in locator was not found",
__func__, locator_tip_hash.ToString());
return;
}
// This checks that ChainStateFlushed callbacks are received after
// BlockConnected. The check may fail immediately after the the sync thread
// catches up and sets m_synced. Consider the case where there is a reorg
// and the blocks on the stale branch are in the ValidationInterface queue
// backlog even after the sync thread has caught up to the new chain tip. In
// this unlikely event, log a warning and let the queue clear.
const CBlockIndex *best_block_index = m_best_block_index.load();
if (best_block_index->GetAncestor(locator_tip_index->nHeight) !=
locator_tip_index) {
LogPrintf("%s: WARNING: Locator contains block (hash=%s) not on known "
"best chain (tip=%s); not writing txindex locator\n",
__func__, locator_tip_hash.ToString(),
best_block_index->GetBlockHash().ToString());
return;
}
if (!m_db->WriteBestBlock(locator)) {
error("%s: Failed to write locator to disk", __func__);
}
}
bool TxIndex::BlockUntilSyncedToCurrentChain() {
AssertLockNotHeld(cs_main);
if (!m_synced) {
return false;
}
{
// Skip the queue-draining stuff if we know we're caught up with
// chainActive.Tip().
LOCK(cs_main);
const CBlockIndex *chain_tip = chainActive.Tip();
const CBlockIndex *best_block_index = m_best_block_index.load();
if (best_block_index->GetAncestor(chain_tip->nHeight) == chain_tip) {
return true;
}
}
LogPrintf("%s: txindex is catching up on block notifications\n", __func__);
SyncWithValidationInterfaceQueue();
return true;
}
-bool TxIndex::FindTx(const uint256 &txid, CDiskTxPos &pos) const {
- return m_db->ReadTxPos(txid, pos);
+bool TxIndex::FindTx(const uint256 &tx_hash, uint256 &block_hash,
+ CTransactionRef &tx) const {
+ CDiskTxPos postx;
+ if (!m_db->ReadTxPos(tx_hash, postx)) {
+ return false;
+ }
+
+ CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION);
+ if (file.IsNull()) {
+ return error("%s: OpenBlockFile failed", __func__);
+ }
+ CBlockHeader header;
+ try {
+ file >> header;
+ fseek(file.Get(), postx.nTxOffset, SEEK_CUR);
+ file >> tx;
+ } catch (const std::exception &e) {
+ return error("%s: Deserialize or I/O error - %s", __func__, e.what());
+ }
+ if (tx->GetHash() != tx_hash) {
+ return error("%s: txid mismatch", __func__);
+ }
+ block_hash = header.GetHash();
+ return true;
}
void TxIndex::Interrupt() {
m_interrupt();
}
void TxIndex::Start() {
// Need to register this ValidationInterface before running Init(), so that
// callbacks are not missed if Init sets m_synced to true.
RegisterValidationInterface(this);
if (!Init()) {
FatalError("%s: txindex failed to initialize", __func__);
return;
}
m_thread_sync = std::thread(&TraceThread>, "txindex",
std::bind(&TxIndex::ThreadSync, this));
}
void TxIndex::Stop() {
UnregisterValidationInterface(this);
if (m_thread_sync.joinable()) {
m_thread_sync.join();
}
}
diff --git a/src/index/txindex.h b/src/index/txindex.h
index 43db34e5ce..22db753a20 100644
--- a/src/index/txindex.h
+++ b/src/index/txindex.h
@@ -1,87 +1,98 @@
// Copyright (c) 2017-2018 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_INDEX_TXINDEX_H
#define BITCOIN_INDEX_TXINDEX_H
#include
+#include
#include
#include
#include
#include
class CBlockIndex;
/**
* TxIndex is used to look up transactions included in the blockchain by hash.
* The index is written to a LevelDB database and records the filesystem
* location of each transaction by transaction hash.
*/
class TxIndex final : public CValidationInterface {
private:
const std::unique_ptr m_db;
/// Whether the index is in sync with the main chain. The flag is flipped
/// from false to true once, after which point this starts processing
/// ValidationInterface notifications to stay in sync.
std::atomic m_synced;
/// The last block in the chain that the TxIndex is in sync with.
std::atomic m_best_block_index;
std::thread m_thread_sync;
CThreadInterrupt m_interrupt;
/// Initialize internal state from the database and block index.
bool Init();
/// Sync the tx index with the block index starting from the current best
/// block. Intended to be run in its own thread, m_thread_sync, and can be
/// interrupted with m_interrupt. Once the txindex gets in sync, the
/// m_synced flag is set and the BlockConnected ValidationInterface callback
/// takes over and the sync thread exits.
void ThreadSync();
/// Write update index entries for a newly connected block.
bool WriteBlock(const CBlock &block, const CBlockIndex *pindex);
/// Write the current chain block locator to the DB.
bool WriteBestBlock(const CBlockIndex *block_index);
protected:
void
BlockConnected(const std::shared_ptr &block,
const CBlockIndex *pindex,
const std::vector &txn_conflicted) override;
void ChainStateFlushed(const CBlockLocator &locator) override;
public:
/// Constructs the TxIndex, which becomes available to be queried.
explicit TxIndex(std::unique_ptr db);
/// Destructor interrupts sync thread if running and blocks until it exits.
~TxIndex();
/// Blocks the current thread until the transaction index is caught up to
/// the current state of the block chain. This only blocks if the index has
/// gotten in sync once and only needs to process blocks in the
/// ValidationInterface queue. If the index is catching up from far behind,
/// this method does not block and immediately returns false.
bool BlockUntilSyncedToCurrentChain();
- /// Look up the on-disk location of a transaction by hash.
- bool FindTx(const uint256 &txid, CDiskTxPos &pos) const;
+ /// Look up a transaction by hash.
+ ///
+ /// @param[in] tx_hash The hash of the transaction to be returned.
+ /// @param[out] block_hash The hash of the block the transaction is found
+ /// in.
+ /// @param[out] tx The transaction itself.
+ /// @return true if transaction is found, false otherwise
+ bool FindTx(const uint256 &tx_hash, uint256 &block_hash,
+ CTransactionRef &tx) const;
void Interrupt();
/// Start initializes the sync state and registers the instance as a
/// ValidationInterface so that it stays in sync with blockchain updates.
void Start();
/// Stops the instance from staying in sync with blockchain updates.
void Stop();
};
+/// The global transaction index, used in GetTransaction. May be null.
+extern std::unique_ptr g_txindex;
+
#endif // BITCOIN_INDEX_TXINDEX_H
diff --git a/src/init.cpp b/src/init.cpp
index 4ebb4c1449..13d59edbd9 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1,2455 +1,2467 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
#include
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
+#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include