mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-21 15:50:07 +01:00
This is a commit in preparation for the next few commits. The functions are moved to methods to avoid their re-declaration for the purpose of passing in BlockManager options. The functions that were now moved into the BlockManager should no longer use the params as an argument, but instead use the member variable. In the moved ReadBlockFromDisk and UndoReadFromDisk, change the function signature to accept a reference to a CBlockIndex instead of a raw pointer. The pointer is expected to be non-null, so reflect that in the type. To allow for the move of functions to BlockManager methods all call sites require an instantiated BlockManager, or a callback to one.
101 lines
3.2 KiB
C++
101 lines
3.2 KiB
C++
// Copyright (c) 2017-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 <index/txindex.h>
|
|
|
|
#include <common/args.h>
|
|
#include <index/disktxpos.h>
|
|
#include <logging.h>
|
|
#include <node/blockstorage.h>
|
|
#include <validation.h>
|
|
|
|
constexpr uint8_t DB_TXINDEX{'t'};
|
|
|
|
std::unique_ptr<TxIndex> g_txindex;
|
|
|
|
|
|
/** Access to the txindex database (indexes/txindex/) */
|
|
class TxIndex::DB : public BaseIndex::DB
|
|
{
|
|
public:
|
|
explicit DB(size_t n_cache_size, bool f_memory = false, bool f_wipe = false);
|
|
|
|
/// Read the disk location of the transaction data with the given hash. Returns false if the
|
|
/// transaction hash is not indexed.
|
|
bool ReadTxPos(const uint256& txid, CDiskTxPos& pos) const;
|
|
|
|
/// Write a batch of transaction positions to the DB.
|
|
bool WriteTxs(const std::vector<std::pair<uint256, CDiskTxPos>>& v_pos);
|
|
};
|
|
|
|
TxIndex::DB::DB(size_t n_cache_size, bool f_memory, bool f_wipe) :
|
|
BaseIndex::DB(gArgs.GetDataDirNet() / "indexes" / "txindex", n_cache_size, f_memory, f_wipe)
|
|
{}
|
|
|
|
bool TxIndex::DB::ReadTxPos(const uint256 &txid, CDiskTxPos& pos) const
|
|
{
|
|
return Read(std::make_pair(DB_TXINDEX, txid), pos);
|
|
}
|
|
|
|
bool TxIndex::DB::WriteTxs(const std::vector<std::pair<uint256, CDiskTxPos>>& v_pos)
|
|
{
|
|
CDBBatch batch(*this);
|
|
for (const auto& tuple : v_pos) {
|
|
batch.Write(std::make_pair(DB_TXINDEX, tuple.first), tuple.second);
|
|
}
|
|
return WriteBatch(batch);
|
|
}
|
|
|
|
TxIndex::TxIndex(std::unique_ptr<interfaces::Chain> chain, size_t n_cache_size, bool f_memory, bool f_wipe)
|
|
: BaseIndex(std::move(chain), "txindex"), m_db(std::make_unique<TxIndex::DB>(n_cache_size, f_memory, f_wipe))
|
|
{}
|
|
|
|
TxIndex::~TxIndex() = default;
|
|
|
|
bool TxIndex::CustomAppend(const interfaces::BlockInfo& block)
|
|
{
|
|
// Exclude genesis block transaction because outputs are not spendable.
|
|
if (block.height == 0) return true;
|
|
|
|
assert(block.data);
|
|
CDiskTxPos pos({block.file_number, block.data_pos}, GetSizeOfCompactSize(block.data->vtx.size()));
|
|
std::vector<std::pair<uint256, CDiskTxPos>> vPos;
|
|
vPos.reserve(block.data->vtx.size());
|
|
for (const auto& tx : block.data->vtx) {
|
|
vPos.emplace_back(tx->GetHash(), pos);
|
|
pos.nTxOffset += ::GetSerializeSize(*tx, CLIENT_VERSION);
|
|
}
|
|
return m_db->WriteTxs(vPos);
|
|
}
|
|
|
|
BaseIndex::DB& TxIndex::GetDB() const { return *m_db; }
|
|
|
|
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(m_chainstate->m_blockman.OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION);
|
|
if (file.IsNull()) {
|
|
return error("%s: OpenBlockFile failed", __func__);
|
|
}
|
|
CBlockHeader header;
|
|
try {
|
|
file >> header;
|
|
if (fseek(file.Get(), postx.nTxOffset, SEEK_CUR)) {
|
|
return error("%s: fseek(...) failed", __func__);
|
|
}
|
|
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;
|
|
}
|