40 _(
"The -txindex upgrade started by a previous version can not "
41 "be completed. Restart with the previous version or run a "
44 bool txindex_legacy_flag{
false};
45 block_tree_db.
ReadFlag(
"txindex", txindex_legacy_flag);
46 if (txindex_legacy_flag) {
48 if (!block_tree_db.
WriteFlag(
"txindex",
false)) {
50 "Failed to write block index db flag 'txindex'='0'")};
53 _(
"The block index db contains a legacy 'txindex'. To clear the "
54 "occupied disk space, run a full -reindex, otherwise ignore "
55 "this error. This error message will not be displayed again.")};
69 TxId id = obj.outpoint->GetTxId();
70 uint32_t n = obj.outpoint->GetN();
79 : m_db(
std::make_unique<
CDBWrapper>(ldb_path, nCacheSize, fMemory, fWipe,
81 m_ldb_path(ldb_path), m_is_memory(fMemory) {}
97 return m_db->Read(CoinEntry(&outpoint), coin);
101 return m_db->Exists(CoinEntry(&outpoint));
109 return hashBestChain;
113 std::vector<BlockHash> vhashHeadBlocks;
115 return std::vector<BlockHash>();
117 return vhashHeadBlocks;
133 if (old_heads.size() == 2) {
134 assert(old_heads[0] == hashBlock);
135 old_tip = old_heads[1];
146 for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
148 CoinEntry entry(&it->first);
149 if (it->second.coin.IsSpent()) {
152 batch.
Write(entry, it->second.coin);
157 CCoinsMap::iterator itOld = it++;
158 mapCoins.erase(itOld);
162 m_db->WriteBatch(batch);
164 if (crash_simulate) {
166 if (rng.
randrange(crash_simulate) == 0) {
167 LogPrintf(
"Simulating a crash. Goodbye.\n");
180 bool ret =
m_db->WriteBatch(batch);
182 "Committed %u changed transaction outputs (out of "
183 "%u) to coin database...\n",
184 (
unsigned int)changed, (
unsigned int)
count);
227 CoinEntry entry(&i->
keyTmp.second);
229 i->
keyTmp.first = entry.key;
247 return pcursor->GetValue(coin);
251 return pcursor->GetValueSize();
260 CoinEntry entry(&
keyTmp.second);
271 const std::vector<std::pair<int, const CBlockFileInfo *>> &fileInfo,
272 int nLastFile,
const std::vector<const CBlockIndex *> &blockinfo) {
274 for (std::vector<std::pair<int, const CBlockFileInfo *>>::const_iterator
275 it = fileInfo.begin();
276 it != fileInfo.end(); it++) {
280 for (std::vector<const CBlockIndex *>::const_iterator it =
282 it != blockinfo.end(); it++) {
306 std::unique_ptr<CDBIterator> pcursor(
NewIterator());
308 uint64_t version = 0;
309 pcursor->Seek(
"version");
310 if (pcursor->Valid()) {
311 pcursor->GetValue(version);
315 return error(
"%s: Invalid block index database version: %s", __func__,
322 while (pcursor->Valid()) {
326 std::pair<char, uint256> key;
332 if (!pcursor->GetValue(diskindex)) {
333 return error(
"%s : failed to read value", __func__);
340 pindexNew->nFile = diskindex.nFile;
341 pindexNew->nDataPos = diskindex.nDataPos;
342 pindexNew->nUndoPos = diskindex.nUndoPos;
348 pindexNew->nStatus = diskindex.nStatus;
349 pindexNew->
nTx = diskindex.
nTx;
353 return error(
"%s: CheckProofOfWork failed: %s", __func__,
372 std::vector<CTxOut> vout;
378 CCoins() : fCoinBase(false), vout(0),
nHeight(0) {}
380 template <
typename Stream>
void Unserialize(Stream &s) {
383 unsigned int nVersionDummy = 0;
387 fCoinBase = nCode & 1;
388 std::vector<bool> vAvail(2,
false);
389 vAvail[0] = (nCode & 2) != 0;
390 vAvail[1] = (nCode & 4) != 0;
391 uint32_t nMaskCode = (nCode / 8) + ((nCode & 6) != 0 ? 0 : 1);
393 while (nMaskCode > 0) {
396 for (
unsigned int p = 0; p < 8; p++) {
397 bool f = (chAvail & (1 << p)) != 0;
405 vout.assign(vAvail.size(),
CTxOut());
406 for (
size_t i = 0; i < vAvail.size(); i++) {
423 std::unique_ptr<CDBIterator> pcursor(
m_db->NewIterator());
425 if (!pcursor->Valid()) {
430 LogPrintf(
"Upgrading utxo-set database...\n");
431 size_t batch_size = 1 << 24;
434 std::pair<uint8_t, uint256> key;
436 while (pcursor->Valid()) {
441 if (!pcursor->GetKey(key) || key.first !=
DB_COINS) {
445 if (
count++ % 256 == 0) {
447 0x100 * *key.second.
begin() + *(key.second.begin() + 1);
448 int percentageDone = (int)(high * 100.0 / 65536.0 + 0.5);
450 percentageDone,
true);
451 if (reportDone < percentageDone / 10) {
454 reportDone = percentageDone / 10;
459 if (!pcursor->GetValue(old_coins)) {
460 return error(
"%s: cannot parse CCoins record", __func__);
463 const TxId id(key.second);
464 for (
size_t i = 0; i < old_coins.vout.size(); ++i) {
465 if (!old_coins.vout[i].IsNull() &&
466 !old_coins.vout[i].scriptPubKey.IsUnspendable()) {
467 Coin newcoin(std::move(old_coins.vout[i]), old_coins.nHeight,
468 old_coins.fCoinBase);
470 CoinEntry entry(&outpoint);
471 batch.
Write(entry, newcoin);
477 m_db->WriteBatch(batch);
479 m_db->CompactRange(prev_key, key);
486 m_db->WriteBatch(batch);
497 std::unique_ptr<CDBIterator> pcursor(
NewIterator());
499 uint64_t version = 0;
500 pcursor->Seek(
"version");
501 if (pcursor->Valid()) {
502 pcursor->GetValue(version);
516 "\nThe database is too old. The block index cannot be upgraded "
517 "and reindexing is required.\n");
524 LogPrintf(
"Updating the block index database version to %d\n",
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
The block chain is a tree shaped structure starting with the genesis block at the root,...
std::string ToString() const
CBlockIndex * pprev
pointer to the index of the predecessor of this block
unsigned int nTx
Number of transactions in this block.
int32_t nVersion
block header
BlockHash GetBlockHash() const
int nHeight
height of the entry in the chain. The genesis block has height 0
Access to the block database (blocks/index/)
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &info)
bool WriteBatchSync(const std::vector< std::pair< int, const CBlockFileInfo * >> &fileInfo, int nLastFile, const std::vector< const CBlockIndex * > &blockinfo)
CBlockTreeDB(size_t nCacheSize, bool fMemory=false, bool fWipe=false)
bool Upgrade()
Attempt to update from an older database format.
bool WriteReindexing(bool fReindexing)
bool IsReindexing() const
bool ReadFlag(const std::string &name, bool &fValue)
bool ReadLastBlockFile(int &nFile)
bool LoadBlockIndexGuts(const Consensus::Params ¶ms, std::function< CBlockIndex *(const BlockHash &)> insertBlockIndex) EXCLUSIVE_LOCKS_REQUIRED(
bool WriteFlag(const std::string &name, bool fValue)
Cursor for iterating over CoinsView state.
Specialization of CCoinsViewCursor to iterate over a CCoinsViewDB.
std::unique_ptr< CDBIterator > pcursor
bool GetKey(COutPoint &key) const override
bool GetValue(Coin &coin) const override
bool Valid() const override
unsigned int GetValueSize() const override
std::pair< char, COutPoint > keyTmp
BlockHash GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
std::vector< BlockHash > GetHeadBlocks() const override
Retrieve the range of blocks that may have been only partially written.
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether a given outpoint is unspent.
std::unique_ptr< CDBWrapper > m_db
bool Upgrade()
Attempt to update from an older database format.
bool BatchWrite(CCoinsMap &mapCoins, const BlockHash &hashBlock) override
Do a bulk modification (multiple Coin changes + BestBlock change).
CCoinsViewCursor * Cursor() const override
Get a cursor to iterate over the whole state.
CCoinsViewDB(fs::path ldb_path, size_t nCacheSize, bool fMemory, bool fWipe)
void ResizeCache(size_t new_cache_size) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Dynamically alter the underlying leveldb cache size.
size_t EstimateSize() const override
Estimate database size (0 if not implemented)
Batch of changes queued to be written to a CDBWrapper.
size_t SizeEstimate() const
void Write(const K &key, const V &value)
CDBIterator * NewIterator()
bool WriteBatch(CDBBatch &batch, bool fSync=false)
bool Read(const K &key, V &value) const
bool Erase(const K &key, bool fSync=false)
bool Write(const K &key, const V &value, bool fSync=false)
bool Exists(const K &key) const
Used to marshal pointers into hashes for db storage.
BlockHash GetBlockHash() const
static constexpr int TRACK_SIZE_VERSION
An outpoint - a combination of a transaction hash and an index n into its vout.
An output of a transaction.
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
std::unordered_map< COutPoint, CCoinsCacheEntry, SaltedOutpointHasher > CCoinsMap
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
#define LogPrint(category,...)
#define LogPrintfToBeContinued
These are aliases used to explicitly state that the message should not end with a newline character.
Implement std::hash so RCUPtr can be used as a key for maps or sets.
bool CheckProofOfWork(const BlockHash &hash, uint32_t nBits, const Consensus::Params ¶ms)
Check whether a block hash satisfies the proof-of-work requirement specified by nBits.
#define VARINT_MODE(obj, mode)
#define SERIALIZE_METHODS(cls, obj)
Implement the Serialize and Unserialize methods by delegating to a single templated static method tha...
void Unserialize(Stream &s, char &a)
#define SER_READ(obj, code)
bool ShutdownRequested()
Returns true if a shutdown is requested, false otherwise.
A BlockHash is a unqiue identifier for a block.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
@ DIRTY
DIRTY means the CCoinsCacheEntry is potentially different from the version in the parent cache.
Parameters that influence chain consensus.
A TxId is the identifier of a transaction.
bool error(const char *fmt, const Args &...args)
bilingual_str _(const char *psz)
Translation function.
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
static constexpr uint8_t DB_TXINDEX_BLOCK
static const char DB_BLOCK_FILES
static const char DB_REINDEX_FLAG
static const char DB_COINS
static const char DB_HEAD_BLOCKS
util::Result< void > CheckLegacyTxindex(CBlockTreeDB &block_tree_db)
static const char DB_LAST_BLOCK
static const char DB_BLOCK_INDEX
static const char DB_COIN
static const char DB_FLAG
static const char DB_BEST_BLOCK
static constexpr int64_t DEFAULT_DB_BATCH_SIZE
-dbbatchsize default (bytes)
CClientUIInterface uiInterface
std::vector< typename std::common_type< Args... >::type > Vector(Args &&...args)
Construct a vector with the specified elements.