43 m_db(
std::make_unique<
CDBWrapper>(ldb_path, nCacheSize, fMemory, fWipe, true)),
45 m_is_memory(fMemory) { }
55 m_db = std::make_unique<CDBWrapper>(
61 return m_db->Read(CoinEntry(&outpoint), coin);
65 return m_db->Exists(CoinEntry(&outpoint));
76 std::vector<uint256> vhashHeadBlocks;
78 return std::vector<uint256>();
80 return vhashHeadBlocks;
88 int crash_simulate =
gArgs.
GetArg(
"-dbcrashratio", 0);
92 if (old_tip.IsNull()) {
95 if (old_heads.size() == 2) {
96 assert(old_heads[0] == hashBlock);
97 old_tip = old_heads[1];
108 for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
110 CoinEntry entry(&it->first);
111 if (it->second.coin.IsSpent())
114 batch.
Write(entry, it->second.coin);
118 CCoinsMap::iterator itOld = it++;
119 mapCoins.erase(itOld);
122 m_db->WriteBatch(batch);
124 if (crash_simulate) {
126 if (rng.
randrange(crash_simulate) == 0) {
127 LogPrintf(
"Simulating a crash. Goodbye.\n");
139 bool ret =
m_db->WriteBatch(batch);
140 LogPrint(
BCLog::COINDB,
"Committed %u changed transaction outputs (out of %u) to coin database...\n", (
unsigned int)changed, (
unsigned int)
count);
185 bool Valid()
const override;
186 void Next()
override;
197 auto i = std::make_unique<CCoinsViewDBCursor>(
204 if (i->pcursor->Valid()) {
205 CoinEntry entry(&i->keyTmp.second);
206 i->pcursor->GetKey(entry);
207 i->keyTmp.first = entry.key;
226 return pcursor->GetValue(coin);
231 return pcursor->GetValueSize();
242 CoinEntry entry(&
keyTmp.second);
250 bool CBlockTreeDB::WriteBatchSync(
const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo,
int nLastFile,
const std::vector<const CBlockIndex*>& blockinfo) {
252 for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
256 for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
263 return Write(std::make_pair(
DB_FLAG,
name), fValue ? uint8_t{
'1'} : uint8_t{
'0'});
270 fValue = ch == uint8_t{
'1'};
276 std::unique_ptr<CDBIterator> pcursor(
NewIterator());
281 while (pcursor->Valid()) {
283 std::pair<uint8_t, uint256> key;
286 if (pcursor->GetValue(diskindex)) {
300 pindexNew->
nTx = diskindex.
nTx;
303 return error(
"%s: CheckProofOfWork failed: %s", __func__, pindexNew->
ToString());
307 return error(
"%s: failed to read value", __func__);
327 std::vector<CTxOut> vout;
333 CCoins() : fCoinBase(false), vout(0),
nHeight(0) { }
335 template<
typename Stream>
337 unsigned int nCode = 0;
339 unsigned int nVersionDummy;
343 fCoinBase = nCode & 1;
344 std::vector<bool> vAvail(2,
false);
345 vAvail[0] = (nCode & 2) != 0;
346 vAvail[1] = (nCode & 4) != 0;
347 unsigned int nMaskCode = (nCode / 8) + ((nCode & 6) != 0 ? 0 : 1);
349 while (nMaskCode > 0) {
350 unsigned char chAvail = 0;
352 for (
unsigned int p = 0; p < 8; p++) {
353 bool f = (chAvail & (1 << p)) != 0;
360 vout.assign(vAvail.size(),
CTxOut());
361 for (
unsigned int i = 0; i < vAvail.size(); i++) {
377 std::unique_ptr<CDBIterator> pcursor(
m_db->NewIterator());
379 if (!pcursor->Valid()) {
384 LogPrintf(
"Upgrading utxo-set database...\n");
386 uiInterface.ShowProgress(
_(
"Upgrading UTXO database").translated, 0,
true);
387 size_t batch_size = 1 << 24;
390 std::pair<unsigned char, uint256> key;
392 while (pcursor->Valid()) {
396 if (pcursor->GetKey(key) && key.first ==
DB_COINS) {
397 if (
count++ % 256 == 0) {
398 uint32_t high = 0x100 * *key.second.
begin() + *(key.second.begin() + 1);
399 int percentageDone = (int)(high * 100.0 / 65536.0 + 0.5);
400 uiInterface.ShowProgress(
_(
"Upgrading UTXO database").translated, percentageDone,
true);
401 if (reportDone < percentageDone/10) {
404 reportDone = percentageDone/10;
408 if (!pcursor->GetValue(old_coins)) {
409 return error(
"%s: cannot parse CCoins record", __func__);
412 for (
size_t i = 0; i < old_coins.vout.size(); ++i) {
413 if (!old_coins.vout[i].IsNull() && !old_coins.vout[i].scriptPubKey.IsUnspendable()) {
414 Coin newcoin(std::move(old_coins.vout[i]), old_coins.nHeight, old_coins.fCoinBase);
416 CoinEntry entry(&outpoint);
417 batch.
Write(entry, newcoin);
422 m_db->WriteBatch(batch);
424 m_db->CompactRange(prev_key, key);
432 m_db->WriteBatch(batch);
bool Exists(const K &key) const
bool GetValue(Coin &coin) const override
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::unique_ptr< CCoinsViewCursor > Cursor() const override
Get a cursor to iterate over the whole state.
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.
static constexpr uint8_t DB_BLOCK_INDEX
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)
void ResizeCache(size_t new_cache_size) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Dynamically alter the underlying leveldb cache size.
static constexpr uint8_t DB_BEST_BLOCK
int nFile
Which # file this block is stored in (blk?????.dat)
static constexpr uint8_t DB_HEAD_BLOCKS
bool GetKey(COutPoint &key) const override
static constexpr uint8_t DB_LAST_BLOCK
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 constexpr uint8_t DB_FLAG
#define VARINT_MODE(obj, mode)
bool Erase(const K &key, bool fSync=false)
unsigned int nDataPos
Byte offset within blk?????.dat where this block's data is stored.
static constexpr uint8_t DB_REINDEX_FLAG
bilingual_str _(const char *psz)
Translation function.
std::unordered_map< COutPoint, CCoinsCacheEntry, SaltedOutpointHasher > CCoinsMap
static constexpr uint8_t DB_COINS
void Write(const K &key, const V &value)
size_t SizeEstimate() const
CCoinsViewDBCursor(CDBIterator *pcursorIn, const uint256 &hashBlockIn)
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)
#define SERIALIZE_METHODS(cls, obj)
Implement the Serialize and Unserialize methods by delegating to a single templated static method tha...
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
bool Write(const K &key, const V &value, bool fSync=false)
static constexpr uint8_t DB_COIN
The block chain is a tree shaped structure starting with the genesis block at the root...
CCoinsView backed by the coin database (chainstate/)
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).
bool WriteBatch(CDBBatch &batch, bool fSync=false)
static constexpr uint8_t DB_BLOCK_FILES
bool Valid() const override
CClientUIInterface uiInterface
int nHeight
height of the entry in the chain. The genesis block has height 0
uint256 GetBlockHash() const
unsigned int GetValueSize() const override
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.