mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-10 22:18:54 +01:00
move-only: Move CBlockTreeDB to node/blockstorage
The block index (CBlockTreeDB) is required to write and read blocks, so move it to blockstorage. This allows to drop the txdb.h include from `node/blockstorage.h`. Can be reviewed with: --color-moved=dimmed-zebra --color-moved-ws=ignore-all-space
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
#include <clientversion.h>
|
#include <clientversion.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
|
#include <dbwrapper.h>
|
||||||
#include <flatfile.h>
|
#include <flatfile.h>
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
#include <kernel/chainparams.h>
|
#include <kernel/chainparams.h>
|
||||||
@@ -15,15 +16,116 @@
|
|||||||
#include <reverse_iterator.h>
|
#include <reverse_iterator.h>
|
||||||
#include <signet.h>
|
#include <signet.h>
|
||||||
#include <streams.h>
|
#include <streams.h>
|
||||||
|
#include <sync.h>
|
||||||
#include <undo.h>
|
#include <undo.h>
|
||||||
#include <util/batchpriority.h>
|
#include <util/batchpriority.h>
|
||||||
#include <util/fs.h>
|
#include <util/fs.h>
|
||||||
#include <util/signalinterrupt.h>
|
#include <util/signalinterrupt.h>
|
||||||
|
#include <util/translation.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace kernel {
|
||||||
|
static constexpr uint8_t DB_BLOCK_FILES{'f'};
|
||||||
|
static constexpr uint8_t DB_BLOCK_INDEX{'b'};
|
||||||
|
static constexpr uint8_t DB_FLAG{'F'};
|
||||||
|
static constexpr uint8_t DB_REINDEX_FLAG{'R'};
|
||||||
|
static constexpr uint8_t DB_LAST_BLOCK{'l'};
|
||||||
|
// Keys used in previous version that might still be found in the DB:
|
||||||
|
// CBlockTreeDB::DB_TXINDEX_BLOCK{'T'};
|
||||||
|
// CBlockTreeDB::DB_TXINDEX{'t'}
|
||||||
|
// CBlockTreeDB::ReadFlag("txindex")
|
||||||
|
|
||||||
|
bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
|
||||||
|
return Read(std::make_pair(DB_BLOCK_FILES, nFile), info);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
|
||||||
|
if (fReindexing)
|
||||||
|
return Write(DB_REINDEX_FLAG, uint8_t{'1'});
|
||||||
|
else
|
||||||
|
return Erase(DB_REINDEX_FLAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBlockTreeDB::ReadReindexing(bool &fReindexing) {
|
||||||
|
fReindexing = Exists(DB_REINDEX_FLAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
|
||||||
|
return Read(DB_LAST_BLOCK, nFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
|
||||||
|
CDBBatch batch(*this);
|
||||||
|
for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
|
||||||
|
batch.Write(std::make_pair(DB_BLOCK_FILES, it->first), *it->second);
|
||||||
|
}
|
||||||
|
batch.Write(DB_LAST_BLOCK, nLastFile);
|
||||||
|
for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
|
||||||
|
batch.Write(std::make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
|
||||||
|
}
|
||||||
|
return WriteBatch(batch, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
|
||||||
|
return Write(std::make_pair(DB_FLAG, name), fValue ? uint8_t{'1'} : uint8_t{'0'});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
|
||||||
|
uint8_t ch;
|
||||||
|
if (!Read(std::make_pair(DB_FLAG, name), ch))
|
||||||
|
return false;
|
||||||
|
fValue = ch == uint8_t{'1'};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex, const util::SignalInterrupt& interrupt)
|
||||||
|
{
|
||||||
|
AssertLockHeld(::cs_main);
|
||||||
|
std::unique_ptr<CDBIterator> pcursor(NewIterator());
|
||||||
|
pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, uint256()));
|
||||||
|
|
||||||
|
// Load m_block_index
|
||||||
|
while (pcursor->Valid()) {
|
||||||
|
if (interrupt) return false;
|
||||||
|
std::pair<uint8_t, uint256> key;
|
||||||
|
if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) {
|
||||||
|
CDiskBlockIndex diskindex;
|
||||||
|
if (pcursor->GetValue(diskindex)) {
|
||||||
|
// Construct block index object
|
||||||
|
CBlockIndex* pindexNew = insertBlockIndex(diskindex.ConstructBlockHash());
|
||||||
|
pindexNew->pprev = insertBlockIndex(diskindex.hashPrev);
|
||||||
|
pindexNew->nHeight = diskindex.nHeight;
|
||||||
|
pindexNew->nFile = diskindex.nFile;
|
||||||
|
pindexNew->nDataPos = diskindex.nDataPos;
|
||||||
|
pindexNew->nUndoPos = diskindex.nUndoPos;
|
||||||
|
pindexNew->nVersion = diskindex.nVersion;
|
||||||
|
pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
|
||||||
|
pindexNew->nTime = diskindex.nTime;
|
||||||
|
pindexNew->nBits = diskindex.nBits;
|
||||||
|
pindexNew->nNonce = diskindex.nNonce;
|
||||||
|
pindexNew->nStatus = diskindex.nStatus;
|
||||||
|
pindexNew->nTx = diskindex.nTx;
|
||||||
|
|
||||||
|
if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, consensusParams)) {
|
||||||
|
return error("%s: CheckProofOfWork failed: %s", __func__, pindexNew->ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
pcursor->Next();
|
||||||
|
} else {
|
||||||
|
return error("%s: failed to read value", __func__);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // namespace kernel
|
||||||
|
|
||||||
namespace node {
|
namespace node {
|
||||||
std::atomic_bool fReindex(false);
|
std::atomic_bool fReindex(false);
|
||||||
|
|
||||||
|
|||||||
@@ -7,17 +7,25 @@
|
|||||||
|
|
||||||
#include <attributes.h>
|
#include <attributes.h>
|
||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
|
#include <dbwrapper.h>
|
||||||
#include <kernel/blockmanager_opts.h>
|
#include <kernel/blockmanager_opts.h>
|
||||||
#include <kernel/chainparams.h>
|
#include <kernel/chainparams.h>
|
||||||
#include <kernel/cs_main.h>
|
#include <kernel/cs_main.h>
|
||||||
#include <protocol.h>
|
#include <protocol.h>
|
||||||
#include <sync.h>
|
#include <sync.h>
|
||||||
#include <txdb.h>
|
|
||||||
#include <util/fs.h>
|
#include <util/fs.h>
|
||||||
|
#include <util/hasher.h>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
#include <limits>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class BlockValidationState;
|
class BlockValidationState;
|
||||||
@@ -36,7 +44,26 @@ namespace util {
|
|||||||
class SignalInterrupt;
|
class SignalInterrupt;
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
||||||
|
namespace kernel {
|
||||||
|
/** Access to the block database (blocks/index/) */
|
||||||
|
class CBlockTreeDB : public CDBWrapper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using CDBWrapper::CDBWrapper;
|
||||||
|
bool WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*>>& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo);
|
||||||
|
bool ReadBlockFileInfo(int nFile, CBlockFileInfo& info);
|
||||||
|
bool ReadLastBlockFile(int& nFile);
|
||||||
|
bool WriteReindexing(bool fReindexing);
|
||||||
|
void ReadReindexing(bool& fReindexing);
|
||||||
|
bool WriteFlag(const std::string& name, bool fValue);
|
||||||
|
bool ReadFlag(const std::string& name, bool& fValue);
|
||||||
|
bool LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex, const util::SignalInterrupt& interrupt)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||||
|
};
|
||||||
|
} // namespace kernel
|
||||||
|
|
||||||
namespace node {
|
namespace node {
|
||||||
|
using kernel::CBlockTreeDB;
|
||||||
|
|
||||||
/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
|
/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
|
||||||
static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
|
static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
|
||||||
|
|||||||
@@ -63,6 +63,7 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
using kernel::CBlockTreeDB;
|
||||||
using kernel::ValidationCacheSizes;
|
using kernel::ValidationCacheSizes;
|
||||||
using node::ApplyArgsManOptions;
|
using node::ApplyArgsManOptions;
|
||||||
using node::BlockAssembler;
|
using node::BlockAssembler;
|
||||||
|
|||||||
104
src/txdb.cpp
104
src/txdb.cpp
@@ -5,40 +5,25 @@
|
|||||||
|
|
||||||
#include <txdb.h>
|
#include <txdb.h>
|
||||||
|
|
||||||
#include <chain.h>
|
|
||||||
#include <coins.h>
|
#include <coins.h>
|
||||||
#include <dbwrapper.h>
|
#include <dbwrapper.h>
|
||||||
#include <kernel/cs_main.h>
|
|
||||||
#include <logging.h>
|
#include <logging.h>
|
||||||
#include <pow.h>
|
|
||||||
#include <primitives/transaction.h>
|
#include <primitives/transaction.h>
|
||||||
#include <random.h>
|
#include <random.h>
|
||||||
#include <serialize.h>
|
#include <serialize.h>
|
||||||
#include <sync.h>
|
|
||||||
#include <uint256.h>
|
#include <uint256.h>
|
||||||
#include <util/signalinterrupt.h>
|
|
||||||
#include <util/translation.h>
|
|
||||||
#include <util/vector.h>
|
#include <util/vector.h>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
static constexpr uint8_t DB_COIN{'C'};
|
static constexpr uint8_t DB_COIN{'C'};
|
||||||
static constexpr uint8_t DB_BLOCK_FILES{'f'};
|
|
||||||
static constexpr uint8_t DB_BLOCK_INDEX{'b'};
|
|
||||||
|
|
||||||
static constexpr uint8_t DB_BEST_BLOCK{'B'};
|
static constexpr uint8_t DB_BEST_BLOCK{'B'};
|
||||||
static constexpr uint8_t DB_HEAD_BLOCKS{'H'};
|
static constexpr uint8_t DB_HEAD_BLOCKS{'H'};
|
||||||
static constexpr uint8_t DB_FLAG{'F'};
|
|
||||||
static constexpr uint8_t DB_REINDEX_FLAG{'R'};
|
|
||||||
static constexpr uint8_t DB_LAST_BLOCK{'l'};
|
|
||||||
|
|
||||||
// Keys used in previous version that might still be found in the DB:
|
// Keys used in previous version that might still be found in the DB:
|
||||||
static constexpr uint8_t DB_COINS{'c'};
|
static constexpr uint8_t DB_COINS{'c'};
|
||||||
// CBlockTreeDB::DB_TXINDEX_BLOCK{'T'};
|
|
||||||
// CBlockTreeDB::DB_TXINDEX{'t'}
|
|
||||||
// CBlockTreeDB::ReadFlag("txindex")
|
|
||||||
|
|
||||||
bool CCoinsViewDB::NeedsUpgrade()
|
bool CCoinsViewDB::NeedsUpgrade()
|
||||||
{
|
{
|
||||||
@@ -166,25 +151,6 @@ size_t CCoinsViewDB::EstimateSize() const
|
|||||||
return m_db->EstimateSize(DB_COIN, uint8_t(DB_COIN + 1));
|
return m_db->EstimateSize(DB_COIN, uint8_t(DB_COIN + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
|
|
||||||
return Read(std::make_pair(DB_BLOCK_FILES, nFile), info);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
|
|
||||||
if (fReindexing)
|
|
||||||
return Write(DB_REINDEX_FLAG, uint8_t{'1'});
|
|
||||||
else
|
|
||||||
return Erase(DB_REINDEX_FLAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBlockTreeDB::ReadReindexing(bool &fReindexing) {
|
|
||||||
fReindexing = Exists(DB_REINDEX_FLAG);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
|
|
||||||
return Read(DB_LAST_BLOCK, nFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Specialization of CCoinsViewCursor to iterate over a CCoinsViewDB */
|
/** Specialization of CCoinsViewCursor to iterate over a CCoinsViewDB */
|
||||||
class CCoinsViewDBCursor: public CCoinsViewCursor
|
class CCoinsViewDBCursor: public CCoinsViewCursor
|
||||||
{
|
{
|
||||||
@@ -257,71 +223,3 @@ void CCoinsViewDBCursor::Next()
|
|||||||
keyTmp.first = entry.key;
|
keyTmp.first = entry.key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
|
|
||||||
CDBBatch batch(*this);
|
|
||||||
for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
|
|
||||||
batch.Write(std::make_pair(DB_BLOCK_FILES, it->first), *it->second);
|
|
||||||
}
|
|
||||||
batch.Write(DB_LAST_BLOCK, nLastFile);
|
|
||||||
for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
|
|
||||||
batch.Write(std::make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
|
|
||||||
}
|
|
||||||
return WriteBatch(batch, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
|
|
||||||
return Write(std::make_pair(DB_FLAG, name), fValue ? uint8_t{'1'} : uint8_t{'0'});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
|
|
||||||
uint8_t ch;
|
|
||||||
if (!Read(std::make_pair(DB_FLAG, name), ch))
|
|
||||||
return false;
|
|
||||||
fValue = ch == uint8_t{'1'};
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex, const util::SignalInterrupt& interrupt)
|
|
||||||
{
|
|
||||||
AssertLockHeld(::cs_main);
|
|
||||||
std::unique_ptr<CDBIterator> pcursor(NewIterator());
|
|
||||||
pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, uint256()));
|
|
||||||
|
|
||||||
// Load m_block_index
|
|
||||||
while (pcursor->Valid()) {
|
|
||||||
if (interrupt) return false;
|
|
||||||
std::pair<uint8_t, uint256> key;
|
|
||||||
if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) {
|
|
||||||
CDiskBlockIndex diskindex;
|
|
||||||
if (pcursor->GetValue(diskindex)) {
|
|
||||||
// Construct block index object
|
|
||||||
CBlockIndex* pindexNew = insertBlockIndex(diskindex.ConstructBlockHash());
|
|
||||||
pindexNew->pprev = insertBlockIndex(diskindex.hashPrev);
|
|
||||||
pindexNew->nHeight = diskindex.nHeight;
|
|
||||||
pindexNew->nFile = diskindex.nFile;
|
|
||||||
pindexNew->nDataPos = diskindex.nDataPos;
|
|
||||||
pindexNew->nUndoPos = diskindex.nUndoPos;
|
|
||||||
pindexNew->nVersion = diskindex.nVersion;
|
|
||||||
pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
|
|
||||||
pindexNew->nTime = diskindex.nTime;
|
|
||||||
pindexNew->nBits = diskindex.nBits;
|
|
||||||
pindexNew->nNonce = diskindex.nNonce;
|
|
||||||
pindexNew->nStatus = diskindex.nStatus;
|
|
||||||
pindexNew->nTx = diskindex.nTx;
|
|
||||||
|
|
||||||
if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, consensusParams)) {
|
|
||||||
return error("%s: CheckProofOfWork failed: %s", __func__, pindexNew->ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
pcursor->Next();
|
|
||||||
} else {
|
|
||||||
return error("%s: failed to read value", __func__);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|||||||
27
src/txdb.h
27
src/txdb.h
@@ -14,23 +14,12 @@
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class CBlockFileInfo;
|
|
||||||
class CBlockIndex;
|
|
||||||
class COutPoint;
|
class COutPoint;
|
||||||
class uint256;
|
class uint256;
|
||||||
namespace Consensus {
|
|
||||||
struct Params;
|
|
||||||
};
|
|
||||||
namespace util {
|
|
||||||
class SignalInterrupt;
|
|
||||||
} // namespace util
|
|
||||||
|
|
||||||
//! -dbcache default (MiB)
|
//! -dbcache default (MiB)
|
||||||
static const int64_t nDefaultDbCache = 450;
|
static const int64_t nDefaultDbCache = 450;
|
||||||
@@ -88,20 +77,4 @@ public:
|
|||||||
std::optional<fs::path> StoragePath() { return m_db->StoragePath(); }
|
std::optional<fs::path> StoragePath() { return m_db->StoragePath(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Access to the block database (blocks/index/) */
|
|
||||||
class CBlockTreeDB : public CDBWrapper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using CDBWrapper::CDBWrapper;
|
|
||||||
bool WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo);
|
|
||||||
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &info);
|
|
||||||
bool ReadLastBlockFile(int &nFile);
|
|
||||||
bool WriteReindexing(bool fReindexing);
|
|
||||||
void ReadReindexing(bool &fReindexing);
|
|
||||||
bool WriteFlag(const std::string &name, bool fValue);
|
|
||||||
bool ReadFlag(const std::string &name, bool &fValue);
|
|
||||||
bool LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex, const util::SignalInterrupt& interrupt)
|
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // BITCOIN_TXDB_H
|
#endif // BITCOIN_TXDB_H
|
||||||
|
|||||||
@@ -47,7 +47,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class Chainstate;
|
class Chainstate;
|
||||||
class CBlockTreeDB;
|
|
||||||
class CTxMemPool;
|
class CTxMemPool;
|
||||||
class ChainstateManager;
|
class ChainstateManager;
|
||||||
struct ChainTxData;
|
struct ChainTxData;
|
||||||
|
|||||||
Reference in New Issue
Block a user