13 #include <validation.h> 15 #include <boost/thread.hpp> 28 template <
typename Stream,
typename Operation>
56 explicit DB(
size_t n_cache_size,
bool f_memory =
false,
64 bool WriteTxs(
const std::vector<std::pair<TxId, CDiskTxPos>> &v_pos);
81 const std::vector<std::pair<TxId, CDiskTxPos>> &v_pos) {
83 for (
const auto &tuple : v_pos) {
97 const std::pair<uint8_t, TxId> &begin_key,
98 const std::pair<uint8_t, TxId> &end_key) {
124 bool f_legacy_flag =
false;
125 block_tree_db.
ReadFlag(
"txindex", f_legacy_flag);
128 return error(
"%s: cannot write block indicator", __func__);
130 if (!block_tree_db.
WriteFlag(
"txindex",
false)) {
131 return error(
"%s: cannot write block index db flag", __func__);
141 uiInterface.InitMessage(
_(
"Upgrading txindex database").translated);
142 LogPrintf(
"Upgrading txindex database... [0%%]\n");
143 uiInterface.ShowProgress(
_(
"Upgrading txindex database").translated, 0,
146 const size_t batch_size = 1 << 24;
149 CDBBatch batch_olddb(block_tree_db);
151 std::pair<uint8_t, TxId> key;
153 std::pair<uint8_t, TxId> prev_key = begin_key;
155 bool interrupted =
false;
156 std::unique_ptr<CDBIterator> cursor(block_tree_db.
NewIterator());
157 for (cursor->Seek(begin_key); cursor->Valid(); cursor->Next()) {
158 boost::this_thread::interruption_point();
164 if (!cursor->GetKey(key)) {
165 return error(
"%s: cannot get key from valid cursor", __func__);
172 if (++count % 256 == 0) {
176 const TxId &txid = key.second;
177 uint32_t high_nibble =
178 (
static_cast<uint32_t
>(*(txid.
begin() + 0)) << 8) +
179 (static_cast<uint32_t>(*(txid.
begin() + 1)) << 0);
180 int percentage_done = (int)(high_nibble * 100.0 / 65536.0 + 0.5);
182 uiInterface.ShowProgress(
_(
"Upgrading txindex database").translated,
183 percentage_done,
true);
184 if (report_done < percentage_done / 10) {
185 LogPrintf(
"Upgrading txindex database... [%d%%]\n",
187 report_done = percentage_done / 10;
192 if (!cursor->GetValue(value)) {
193 return error(
"%s: cannot parse txindex record", __func__);
195 batch_newdb.
Write(key, value);
196 batch_olddb.
Erase(key);
205 batch_olddb, prev_key, key);
259 std::vector<std::pair<TxId, CDiskTxPos>> vPos;
260 vPos.reserve(block.
vtx.size());
261 for (
const auto &tx : block.
vtx) {
262 vPos.emplace_back(tx->GetId(), pos);
265 return m_db->WriteTxs(vPos);
275 if (!
m_db->ReadTxPos(txid, postx)) {
281 return error(
"%s: OpenBlockFile failed", __func__);
287 return error(
"%s: fseek(...) failed", __func__);
290 }
catch (
const std::exception &e) {
291 return error(
"%s: Deserialize or I/O error - %s", __func__, e.what());
293 if (tx->GetId() != txid) {
294 return error(
"%s: txid mismatch", __func__);
std::shared_ptr< const CTransaction > CTransactionRef
void SerializationOp(Stream &s, Operation ser_action)
bool WriteBlock(const CBlock &block, const CBlockIndex *pindex) override
Write update index entries for a newly connected block.
virtual bool Init()
Initialize internal state from the database and block index.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
constexpr char DB_TXINDEX_BLOCK
Batch of changes queued to be written to a CDBWrapper.
bool WriteTxs(const std::vector< std::pair< TxId, CDiskTxPos >> &v_pos)
Write a batch of transaction positions to the DB.
constexpr char DB_TXINDEX
static void LogPrintf(const char *fmt, const Args &... args)
FlatFilePos GetBlockPos() const
const std::unique_ptr< DB > m_db
#define READWRITEAS(type, obj)
bool Init() override
Override base class init to migrate from old database.
CDBIterator * NewIterator()
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
Access to the txindex database (indexes/txindex/)
size_t GetSerializeSize(const T &t, int nVersion=0)
bool FindTx(const TxId &txid, BlockHash &block_hash, CTransactionRef &tx) const
Look up a transaction by identifier.
Base class for indices of blockchain data.
Access to the block database (blocks/index/)
CDiskTxPos(const FlatFilePos &blockIn, unsigned int nTxOffsetIn)
bool MigrateData(CBlockTreeDB &block_tree_db, const CBlockLocator &best_locator)
Migrate txindex data from the block tree DB, where it may be for older nodes that have not been upgra...
std::unique_ptr< TxIndex > g_txindex
The global transaction index, used in GetTransaction. May be null.
bilingual_str _(const char *psz)
Translation function.
const fs::path & GetDataDir(bool fNetSpecific)
FILE * OpenBlockFile(const FlatFilePos &pos, bool fReadOnly)
Open a block file (blk?????.dat).
RecursiveMutex cs_main
Global state.
void Write(const K &key, const V &value)
BaseIndex::DB & GetDB() const override
size_t SizeEstimate() const
bool Read(const K &key, V &value) const
bool ReadFlag(const std::string &name, bool &fValue)
TxIndex(size_t n_cache_size, bool f_memory=false, bool f_wipe=false)
Constructs the index, which becomes available to be queried.
virtual ~TxIndex() override
bool Write(const K &key, const V &value, bool fSync=false)
void CompactRange(const K &key_begin, const K &key_end) const
Compact a certain range of keys in the database.
std::vector< CTransactionRef > vtx
FILE * Get() const
Get wrapped FILE* without transfer of ownership.
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
A BlockHash is a unqiue identifier for a block.
The block chain is a tree shaped structure starting with the genesis block at the root...
A TxId is the identifier of a transaction.
DB(size_t n_cache_size, bool f_memory=false, bool f_wipe=false)
constexpr char DB_BEST_BLOCK
std::unique_ptr< CBlockTreeDB > pblocktree
Global variable that points to the active block tree (protected by cs_main)
uint32_t GetSizeOfCompactSize(uint64_t nSize)
Compact Size size < 253 – 1 byte size <= USHRT_MAX – 3 bytes (253 + 2 bytes) size <= UINT_MAX – 5 ...
bool WriteFlag(const std::string &name, bool fValue)
static void WriteTxIndexMigrationBatches(CDBWrapper &newdb, CDBWrapper &olddb, CDBBatch &batch_newdb, CDBBatch &batch_olddb, const std::pair< uint8_t, TxId > &begin_key, const std::pair< uint8_t, TxId > &end_key)
bool WriteBatch(CDBBatch &batch, bool fSync=false)
CClientUIInterface uiInterface
int nHeight
height of the entry in the chain. The genesis block has height 0
bool ReadTxPos(const TxId &txid, CDiskTxPos &pos) const
Read the disk location of the transaction data with the given ID.
bool error(const char *fmt, const Args &... args)
TxIndex is used to look up transactions included in the blockchain by ID.
Non-refcounted RAII wrapper for FILE*.