36 explicit CoinEntry(
const COutPoint* ptr) : outpoint(const_cast<COutPoint*>(ptr)), key(
DB_COIN) {}
46 m_is_memory(fMemory) { }
53 m_db = MakeUnique<CDBWrapper>(
58 return m_db->Read(CoinEntry(&outpoint), coin);
62 return m_db->Exists(CoinEntry(&outpoint));
73 std::vector<uint256> vhashHeadBlocks;
75 return std::vector<uint256>();
77 return vhashHeadBlocks;
85 int crash_simulate =
gArgs.
GetArg(
"-dbcrashratio", 0);
89 if (old_tip.IsNull()) {
92 if (old_heads.size() == 2) {
93 assert(old_heads[0] == hashBlock);
94 old_tip = old_heads[1];
105 for (CCoinsMap::iterator
it = mapCoins.begin();
it != mapCoins.end();) {
107 CoinEntry entry(&
it->first);
108 if (
it->second.coin.IsSpent())
111 batch.
Write(entry,
it->second.coin);
115 CCoinsMap::iterator itOld =
it++;
116 mapCoins.erase(itOld);
119 m_db->WriteBatch(batch);
121 if (crash_simulate) {
123 if (rng.
randrange(crash_simulate) == 0) {
124 LogPrintf(
"Simulating a crash. Goodbye.\n");
136 bool ret =
m_db->WriteBatch(batch);
137 LogPrint(
BCLog::COINDB,
"Committed %u changed transaction outputs (out of %u) to coin database...\n", (
unsigned int)changed, (
unsigned int)count);
177 CoinEntry entry(&i->
keyTmp.second);
179 i->
keyTmp.first = entry.key;
198 return pcursor->GetValue(coin);
203 return pcursor->GetValueSize();
208 return keyTmp.first ==
DB_COIN;
214 CoinEntry entry(&keyTmp.second);
215 if (!pcursor->Valid() || !pcursor->GetKey(entry)) {
218 keyTmp.first = entry.key;
222 bool CBlockTreeDB::WriteBatchSync(
const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo,
int nLastFile,
const std::vector<const CBlockIndex*>& blockinfo) {
224 for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator
it=fileInfo.begin();
it != fileInfo.end();
it++) {
228 for (std::vector<const CBlockIndex*>::const_iterator
it=blockinfo.begin();
it != blockinfo.end();
it++) {
235 return Write(std::make_pair(
DB_FLAG, name), fValue ?
'1' :
'0');
248 std::unique_ptr<CDBIterator> pcursor(
NewIterator());
253 while (pcursor->Valid()) {
255 std::pair<char, uint256> key;
258 if (pcursor->GetValue(diskindex)) {
272 pindexNew->
nTx = diskindex.
nTx;
275 return error(
"%s: CheckProofOfWork failed: %s", __func__, pindexNew->
ToString());
279 return error(
"%s: failed to read value", __func__);
299 std::vector<CTxOut> vout;
305 CCoins() : fCoinBase(
false), vout(0),
nHeight(0) { }
307 template<
typename Stream>
309 unsigned int nCode = 0;
311 unsigned int nVersionDummy;
315 fCoinBase = nCode & 1;
316 std::vector<bool> vAvail(2,
false);
317 vAvail[0] = (nCode & 2) != 0;
318 vAvail[1] = (nCode & 4) != 0;
319 unsigned int nMaskCode = (nCode / 8) + ((nCode & 6) != 0 ? 0 : 1);
321 while (nMaskCode > 0) {
322 unsigned char chAvail = 0;
324 for (
unsigned int p = 0; p < 8; p++) {
325 bool f = (chAvail & (1 << p)) != 0;
332 vout.assign(vAvail.size(),
CTxOut());
333 for (
unsigned int i = 0; i < vAvail.size(); i++) {
349 std::unique_ptr<CDBIterator> pcursor(m_db->NewIterator());
351 if (!pcursor->Valid()) {
356 LogPrintf(
"Upgrading utxo-set database...\n");
358 uiInterface.ShowProgress(
_(
"Upgrading UTXO database").translated, 0,
true);
359 size_t batch_size = 1 << 24;
362 std::pair<unsigned char, uint256> key;
364 while (pcursor->Valid()) {
368 if (pcursor->GetKey(key) && key.first ==
DB_COINS) {
369 if (count++ % 256 == 0) {
370 uint32_t high = 0x100 * *key.second.
begin() + *(key.second.begin() + 1);
371 int percentageDone = (int)(high * 100.0 / 65536.0 + 0.5);
372 uiInterface.ShowProgress(
_(
"Upgrading UTXO database").translated, percentageDone,
true);
373 if (reportDone < percentageDone/10) {
376 reportDone = percentageDone/10;
380 if (!pcursor->GetValue(old_coins)) {
381 return error(
"%s: cannot parse CCoins record", __func__);
384 for (
size_t i = 0; i < old_coins.vout.size(); ++i) {
385 if (!old_coins.vout[i].IsNull() && !old_coins.vout[i].scriptPubKey.IsUnspendable()) {
386 Coin newcoin(std::move(old_coins.vout[i]), old_coins.nHeight, old_coins.fCoinBase);
388 CoinEntry entry(&outpoint);
389 batch.
Write(entry, newcoin);
394 m_db->WriteBatch(batch);
396 m_db->CompactRange(prev_key, key);
404 m_db->WriteBatch(batch);
bool Exists(const K &key) const
bool GetValue(Coin &coin) const override
static const char DB_LAST_BLOCK
bool GetCoin(const COutPoint &outpoint, Coin &coin) const override
Retrieve the Coin (unspent transaction output) for a given outpoint.
std::string ToString() const
bool ShutdownRequested()
Returns true if a shutdown is requested, false otherwise.
std::deque< CInv >::iterator it
bool Upgrade()
Attempt to update from an older database format. Returns whether an error occurred.
#define LogPrint(category,...)
Specialization of CCoinsViewCursor to iterate over a CCoinsViewDB.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Batch of changes queued to be written to a CDBWrapper.
uint32_t nStatus
Verification status of this block. See enum BlockStatus.
static const char DB_BEST_BLOCK
bool ReadLastBlockFile(int &nFile)
CCoinsViewDB(fs::path ldb_path, size_t nCacheSize, bool fMemory, bool fWipe)
std::unique_ptr< CDBIterator > pcursor
void ReadReindexing(bool &fReindexing)
static const char DB_COIN
void ResizeCache(size_t new_cache_size) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Dynamically alter the underlying leveldb cache size.
static void LogPrintf(const char *fmt, const Args &... args)
std::unique_ptr< T > MakeUnique(Args &&... args)
Substitute for C++14 std::make_unique.
int nFile
Which # file this block is stored in (blk?????.dat)
bool GetKey(COutPoint &key) const override
bool WriteReindexing(bool fReindexing)
CDBIterator * NewIterator()
DIRTY means the CCoinsCacheEntry is potentially different from the version in the parent cache...
std::vector< typename std::common_type< Args... >::type > Vector(Args &&... args)
Construct a vector with the specified elements.
uint256 GetBlockHash() const
static const char DB_BLOCK_FILES
#define VARINT_MODE(obj, mode)
bool Erase(const K &key, bool fSync=false)
static const char DB_FLAG
unsigned int nDataPos
Byte offset within blk?????.dat where this block's data is stored.
bilingual_str _(const char *psz)
Translation function.
const fs::path & GetDataDir(bool fNetSpecific)
std::unordered_map< COutPoint, CCoinsCacheEntry, SaltedOutpointHasher > CCoinsMap
void Write(const K &key, const V &value)
size_t SizeEstimate() const
An output of a transaction.
Used to marshal pointers into hashes for db storage.
static const int64_t nDefaultDbBatchSize
-dbbatchsize default (bytes)
size_t EstimateSize() const override
Estimate database size (0 if not implemented)
Parameters that influence chain consensus.
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.
An outpoint - a combination of a transaction hash and an index n into its vout.
std::pair< char, COutPoint > keyTmp
bool Read(const K &key, V &value) const
bool HaveCoin(const COutPoint &outpoint) const override
Just check whether a given outpoint is unspent.
bool ReadFlag(const std::string &name, bool &fValue)
CBlockTreeDB(size_t nCacheSize, bool fMemory=false, bool fWipe=false)
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)
unsigned int nUndoPos
Byte offset within rev?????.dat where this block's undo data is stored.
uint256 GetBestBlock() const override
Retrieve the block hash whose state this CCoinsView currently represents.
int32_t nVersion
block header
static const char DB_BLOCK_INDEX
bool Write(const K &key, const V &value, bool fSync=false)
The block chain is a tree shaped structure starting with the genesis block at the root...
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
void Unserialize(Stream &s, char &a)
bool LoadBlockIndexGuts(const Consensus::Params &consensusParams, std::function< CBlockIndex *(const uint256 &)> insertBlockIndex)
bool WriteFlag(const std::string &name, bool fValue)
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override
Do a bulk modification (multiple Coin changes + BestBlock change).
CCoinsViewCursor * Cursor() const override
Get a cursor to iterate over the whole state.
bool WriteBatch(CDBBatch &batch, bool fSync=false)
bool Valid() const override
CClientUIInterface uiInterface
int nHeight
height of the entry in the chain. The genesis block has height 0
uint256 GetBlockHash() const
static const char DB_REINDEX_FLAG
unsigned int GetValueSize() const override
static const char DB_COINS
static const char DB_HEAD_BLOCKS
SERIALIZE_METHODS(CService, obj)
bool error(const char *fmt, const Args &... args)
std::vector< uint256 > GetHeadBlocks() const override
Retrieve the range of blocks that may have been only partially written.
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
unsigned int nTx
Number of transactions in this block.
std::unique_ptr< CDBWrapper > m_db
Cursor for iterating over CoinsView state.