39 return _(
"The -txindex upgrade started by a previous version can not be completed. Restart with the previous version or run a full -reindex.");
41 bool txindex_legacy_flag{
false};
42 block_tree_db.
ReadFlag(
"txindex", txindex_legacy_flag);
43 if (txindex_legacy_flag) {
45 if (!block_tree_db.
WriteFlag(
"txindex",
false)) {
46 return Untranslated(
"Failed to write block index db flag 'txindex'='0'");
48 return _(
"The block index db contains a legacy 'txindex'. To clear the occupied disk space, run a full -reindex, otherwise ignore this error. This error message will not be displayed again.");
66 m_db(std::make_unique<
CDBWrapper>(ldb_path, nCacheSize, fMemory, fWipe, true)),
68 m_is_memory(fMemory) { }
78 m_db = std::make_unique<CDBWrapper>(
84 return m_db->Read(CoinEntry(&outpoint), coin);
88 return m_db->Exists(CoinEntry(&outpoint));
99 std::vector<uint256> vhashHeadBlocks;
101 return std::vector<uint256>();
103 return vhashHeadBlocks;
118 if (old_heads.size() == 2) {
119 assert(old_heads[0] == hashBlock);
120 old_tip = old_heads[1];
131 for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
133 CoinEntry entry(&it->first);
134 if (it->second.coin.IsSpent())
137 batch.
Write(entry, it->second.coin);
141 CCoinsMap::iterator itOld = it++;
142 mapCoins.erase(itOld);
145 m_db->WriteBatch(batch);
147 if (crash_simulate) {
149 if (rng.
randrange(crash_simulate) == 0) {
150 LogPrintf(
"Simulating a crash. Goodbye.\n");
162 bool ret =
m_db->WriteBatch(batch);
163 LogPrint(
BCLog::COINDB,
"Committed %u changed transaction outputs (out of %u) to coin database...\n", (
unsigned int)changed, (
unsigned int)
count);
208 bool Valid()
const override;
209 void Next()
override;
220 auto i = std::make_unique<CCoinsViewDBCursor>(
227 if (i->pcursor->Valid()) {
228 CoinEntry entry(&i->keyTmp.second);
229 i->pcursor->GetKey(entry);
230 i->keyTmp.first = entry.key;
249 return pcursor->GetValue(coin);
254 return pcursor->GetValueSize();
265 CoinEntry entry(&
keyTmp.second);
273bool CBlockTreeDB::WriteBatchSync(
const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo,
int nLastFile,
const std::vector<const CBlockIndex*>& blockinfo) {
275 for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
279 for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
286 return Write(std::make_pair(
DB_FLAG,
name), fValue ? uint8_t{
'1'} : uint8_t{
'0'});
293 fValue = ch == uint8_t{
'1'};
299 std::unique_ptr<CDBIterator> pcursor(
NewIterator());
304 while (pcursor->Valid()) {
306 std::pair<uint8_t, uint256> key;
309 if (pcursor->GetValue(diskindex)) {
323 pindexNew->
nTx = diskindex.
nTx;
326 return error(
"%s: CheckProofOfWork failed: %s", __func__, pindexNew->
ToString());
330 return error(
"%s: failed to read value", __func__);
350 std::vector<CTxOut> vout;
356 CCoins() : fCoinBase(false), vout(0),
nHeight(0) { }
358 template<
typename Stream>
360 unsigned int nCode = 0;
362 unsigned int nVersionDummy;
366 fCoinBase = nCode & 1;
367 std::vector<bool> vAvail(2,
false);
368 vAvail[0] = (nCode & 2) != 0;
369 vAvail[1] = (nCode & 4) != 0;
370 unsigned int nMaskCode = (nCode / 8) + ((nCode & 6) != 0 ? 0 : 1);
372 while (nMaskCode > 0) {
373 unsigned char chAvail = 0;
375 for (
unsigned int p = 0; p < 8; p++) {
376 bool f = (chAvail & (1 << p)) != 0;
383 vout.assign(vAvail.size(),
CTxOut());
384 for (
unsigned int i = 0; i < vAvail.size(); i++) {
400 std::unique_ptr<CDBIterator> pcursor(
m_db->NewIterator());
402 if (!pcursor->Valid()) {
407 LogPrintf(
"Upgrading utxo-set database...\n");
409 uiInterface.ShowProgress(
_(
"Upgrading UTXO database").translated, 0,
true);
410 size_t batch_size = 1 << 24;
413 std::pair<unsigned char, uint256> key;
415 while (pcursor->Valid()) {
419 if (pcursor->GetKey(key) && key.first ==
DB_COINS) {
420 if (
count++ % 256 == 0) {
421 uint32_t high = 0x100 * *key.second.
begin() + *(key.second.begin() + 1);
422 int percentageDone = (int)(high * 100.0 / 65536.0 + 0.5);
424 if (reportDone < percentageDone/10) {
427 reportDone = percentageDone/10;
431 if (!pcursor->GetValue(old_coins)) {
432 return error(
"%s: cannot parse CCoins record", __func__);
435 for (
size_t i = 0; i < old_coins.vout.size(); ++i) {
436 if (!old_coins.vout[i].IsNull() && !old_coins.vout[i].scriptPubKey.IsUnspendable()) {
437 Coin newcoin(std::move(old_coins.vout[i]), old_coins.nHeight, old_coins.fCoinBase);
439 CoinEntry entry(&outpoint);
440 batch.
Write(entry, newcoin);
445 m_db->WriteBatch(batch);
447 m_db->CompactRange(prev_key, key);
455 m_db->WriteBatch(batch);
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
int nFile
Which # file this block is stored in (blk?????.dat)
unsigned int nUndoPos
Byte offset within rev?????.dat where this block's undo data is stored.
uint256 GetBlockHash() const
unsigned int nTx
Number of transactions in this block.
int32_t nVersion
block header
int nHeight
height of the entry in the chain. The genesis block has height 0
uint32_t nStatus
Verification status of this block.
unsigned int nDataPos
Byte offset within blk?????.dat where this block's data is stored.
Access to the block database (blocks/index/)
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &info)
CBlockTreeDB(size_t nCacheSize, bool fMemory=false, bool fWipe=false)
bool WriteReindexing(bool fReindexing)
void ReadReindexing(bool &fReindexing)
bool WriteBatchSync(const std::vector< std::pair< int, const CBlockFileInfo * > > &fileInfo, int nLastFile, const std::vector< const CBlockIndex * > &blockinfo)
bool ReadFlag(const std::string &name, bool &fValue)
bool LoadBlockIndexGuts(const Consensus::Params &consensusParams, std::function< CBlockIndex *(const uint256 &)> insertBlockIndex)
bool ReadLastBlockFile(int &nFile)
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
CCoinsViewDBCursor(CDBIterator *pcursorIn, const uint256 &hashBlockIn)
bool Valid() const override
unsigned int GetValueSize() const override
std::pair< char, COutPoint > keyTmp
CCoinsView backed by the coin database (chainstate/)
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. Returns whether an error occurred.
CCoinsViewDB(fs::path ldb_path, size_t nCacheSize, bool fMemory, bool fWipe)
uint256 GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
std::unique_ptr< CCoinsViewCursor > Cursor() const override
Get a cursor to iterate over the whole state.
void ResizeCache(size_t new_cache_size) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Dynamically alter the underlying leveldb cache size.
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override
Do a bulk modification (multiple Coin changes + BestBlock change).
std::vector< uint256 > GetHeadBlocks() const override
Retrieve the range of blocks that may have been only partially written.
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)
bool WriteBatch(CDBBatch &batch, bool fSync=false)
bool Read(const K &key, V &value) const
CDBIterator * NewIterator()
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.
uint256 GetBlockHash() const
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 prepare application code for transition from boost::filesystem library to std::...
std::unordered_map< COutPoint, CCoinsCacheEntry, SaltedOutpointHasher > CCoinsMap
#define LogPrint(category,...)
bool CheckProofOfWork(uint256 hash, unsigned int 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)
bool ShutdownRequested()
Returns true if a shutdown is requested, false otherwise.
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.
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 constexpr uint8_t DB_LAST_BLOCK
std::optional< bilingual_str > CheckLegacyTxindex(CBlockTreeDB &block_tree_db)
static constexpr uint8_t DB_HEAD_BLOCKS
static constexpr uint8_t DB_REINDEX_FLAG
static constexpr uint8_t DB_BEST_BLOCK
static constexpr uint8_t DB_COIN
static constexpr uint8_t DB_FLAG
static constexpr uint8_t DB_COINS
static constexpr uint8_t DB_BLOCK_FILES
static constexpr uint8_t DB_BLOCK_INDEX
static const int64_t nDefaultDbBatchSize
-dbbatchsize default (bytes)
CClientUIInterface uiInterface
std::vector< typename std::common_type< Args... >::type > Vector(Args &&... args)
Construct a vector with the specified elements.