Dogecoin Core  1.14.2
P2P Digital Currency
txdb.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include "txdb.h"
7 
8 #include "chainparams.h"
9 #include "hash.h"
10 #include "pow.h"
11 #include "uint256.h"
12 
13 #include <stdint.h>
14 
15 #include <boost/thread.hpp>
16 
17 static const char DB_COINS = 'c';
18 static const char DB_BLOCK_FILES = 'f';
19 static const char DB_TXINDEX = 't';
20 static const char DB_BLOCK_INDEX = 'b';
21 
22 static const char DB_BEST_BLOCK = 'B';
23 static const char DB_FLAG = 'F';
24 static const char DB_REINDEX_FLAG = 'R';
25 static const char DB_LAST_BLOCK = 'l';
26 
27 
28 CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe, true)
29 {
30 }
31 
32 bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) const {
33  return db.Read(std::make_pair(DB_COINS, txid), coins);
34 }
35 
36 bool CCoinsViewDB::HaveCoins(const uint256 &txid) const {
37  return db.Exists(std::make_pair(DB_COINS, txid));
38 }
39 
41  uint256 hashBestChain;
42  if (!db.Read(DB_BEST_BLOCK, hashBestChain))
43  return uint256();
44  return hashBestChain;
45 }
46 
47 bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
48  CDBBatch batch(db);
49  size_t count = 0;
50  size_t changed = 0;
51  for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
52  if (it->second.flags & CCoinsCacheEntry::DIRTY) {
53  if (it->second.coins.IsPruned())
54  batch.Erase(std::make_pair(DB_COINS, it->first));
55  else
56  batch.Write(std::make_pair(DB_COINS, it->first), it->second.coins);
57  changed++;
58  }
59  count++;
60  CCoinsMap::iterator itOld = it++;
61  mapCoins.erase(itOld);
62  }
63  if (!hashBlock.IsNull())
64  batch.Write(DB_BEST_BLOCK, hashBlock);
65 
66  LogPrint("coindb", "Committing %u changed transactions (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
67  return db.WriteBatch(batch);
68 }
69 
70 CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
71 }
72 
74  return Read(std::make_pair(DB_BLOCK_FILES, nFile), info);
75 }
76 
77 bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
78  if (fReindexing)
79  return Write(DB_REINDEX_FLAG, '1');
80  else
81  return Erase(DB_REINDEX_FLAG);
82 }
83 
84 bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
85  fReindexing = Exists(DB_REINDEX_FLAG);
86  return true;
87 }
88 
90  return Read(DB_LAST_BLOCK, nFile);
91 }
92 
94 {
95  CCoinsViewDBCursor *i = new CCoinsViewDBCursor(const_cast<CDBWrapper*>(&db)->NewIterator(), GetBestBlock());
96  /* It seems that there are no "const iterators" for LevelDB. Since we
97  only need read operations on it, use a const-cast to get around
98  that restriction. */
99  i->pcursor->Seek(DB_COINS);
100  // Cache key of first record
101  if (i->pcursor->Valid()) {
102  i->pcursor->GetKey(i->keyTmp);
103  } else {
104  i->keyTmp.first = 0; // Make sure Valid() and GetKey() return false
105  }
106  return i;
107 }
108 
110 {
111  // Return cached key
112  if (keyTmp.first == DB_COINS) {
113  key = keyTmp.second;
114  return true;
115  }
116  return false;
117 }
118 
120 {
121  return pcursor->GetValue(coins);
122 }
123 
125 {
126  return pcursor->GetValueSize();
127 }
128 
130 {
131  return keyTmp.first == DB_COINS;
132 }
133 
135 {
136  pcursor->Next();
137  if (!pcursor->Valid() || !pcursor->GetKey(keyTmp))
138  keyTmp.first = 0; // Invalidate cached key after last record so that Valid() and GetKey() return false
139 }
140 
141 bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
142  CDBBatch batch(*this);
143  for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
144  batch.Write(std::make_pair(DB_BLOCK_FILES, it->first), *it->second);
145  }
146  batch.Write(DB_LAST_BLOCK, nLastFile);
147  for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
148  batch.Write(std::make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
149  }
150  return WriteBatch(batch, true);
151 }
152 
154  return Read(std::make_pair(DB_TXINDEX, txid), pos);
155 }
156 
157 bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
158  CDBBatch batch(*this);
159  for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
160  batch.Write(std::make_pair(DB_TXINDEX, it->first), it->second);
161  return WriteBatch(batch);
162 }
163 
164 bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
165  return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
166 }
167 
168 bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
169  char ch;
170  if (!Read(std::make_pair(DB_FLAG, name), ch))
171  return false;
172  fValue = ch == '1';
173  return true;
174 }
175 
176 bool CBlockTreeDB::LoadBlockIndexGuts(boost::function<CBlockIndex*(const uint256&)> insertBlockIndex)
177 {
178  std::unique_ptr<CDBIterator> pcursor(NewIterator());
179 
180  pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, uint256()));
181 
182  // Load mapBlockIndex
183  while (pcursor->Valid()) {
184  boost::this_thread::interruption_point();
185  std::pair<char, uint256> key;
186  if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) {
187  CDiskBlockIndex diskindex;
188  if (pcursor->GetValue(diskindex)) {
189  // Construct block index object
190  CBlockIndex* pindexNew = insertBlockIndex(diskindex.GetBlockHash());
191  pindexNew->pprev = insertBlockIndex(diskindex.hashPrev);
192  pindexNew->nHeight = diskindex.nHeight;
193  pindexNew->nFile = diskindex.nFile;
194  pindexNew->nDataPos = diskindex.nDataPos;
195  pindexNew->nUndoPos = diskindex.nUndoPos;
196  pindexNew->nVersion = diskindex.nVersion;
197  pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
198  pindexNew->nTime = diskindex.nTime;
199  pindexNew->nBits = diskindex.nBits;
200  pindexNew->nNonce = diskindex.nNonce;
201  pindexNew->nStatus = diskindex.nStatus;
202  pindexNew->nTx = diskindex.nTx;
203 
204  /* Bitcoin checks the PoW here. We don't do this because
205  the CDiskBlockIndex does not contain the auxpow.
206  This check isn't important, since the data on disk should
207  already be valid and can be trusted. */
208 
209  pcursor->Next();
210  } else {
211  return error("LoadBlockIndex() : failed to read value");
212  }
213  } else {
214  break;
215  }
216  }
217 
218  return true;
219 }
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:158
uint256 hashMerkleRoot
Definition: chain.h:198
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:164
unsigned int nBits
Definition: chain.h:200
int nFile
Which # file this block is stored in (blk?????.dat)
Definition: chain.h:173
int nVersion
block header
Definition: chain.h:197
unsigned int nTime
Definition: chain.h:199
unsigned int nNonce
Definition: chain.h:201
unsigned int nUndoPos
Byte offset within rev?????.dat where this block's undo data is stored.
Definition: chain.h:179
unsigned int nStatus
Verification status of this block. See enum BlockStatus.
Definition: chain.h:194
unsigned int nTx
Number of transactions in this block.
Definition: chain.h:186
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:170
unsigned int nDataPos
Byte offset within blk?????.dat where this block's data is stored.
Definition: chain.h:176
bool ReadReindexing(bool &fReindex)
Definition: txdb.cpp:84
bool WriteTxIndex(const std::vector< std::pair< uint256, CDiskTxPos > > &list)
Definition: txdb.cpp:157
CBlockTreeDB(size_t nCacheSize, bool fMemory=false, bool fWipe=false)
Definition: txdb.cpp:70
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &fileinfo)
Definition: txdb.cpp:73
bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos)
Definition: txdb.cpp:153
bool LoadBlockIndexGuts(boost::function< CBlockIndex *(const uint256 &)> insertBlockIndex)
Definition: txdb.cpp:176
bool WriteReindexing(bool fReindex)
Definition: txdb.cpp:77
bool WriteBatchSync(const std::vector< std::pair< int, const CBlockFileInfo * > > &fileInfo, int nLastFile, const std::vector< const CBlockIndex * > &blockinfo)
Definition: txdb.cpp:141
bool ReadFlag(const std::string &name, bool &fValue)
Definition: txdb.cpp:168
bool ReadLastBlockFile(int &nFile)
Definition: txdb.cpp:89
bool WriteFlag(const std::string &name, bool fValue)
Definition: txdb.cpp:164
Pruned version of CTransaction: only retains metadata and unspent transaction outputs.
Definition: coins.h:75
Cursor for iterating over CoinsView state.
Definition: coins.h:286
Specialization of CCoinsViewCursor to iterate over a CCoinsViewDB.
Definition: txdb.h:87
std::unique_ptr< CDBIterator > pcursor
Definition: txdb.h:101
bool Valid() const
Definition: txdb.cpp:129
bool GetValue(CCoins &coins) const
Definition: txdb.cpp:119
bool GetKey(uint256 &key) const
Definition: txdb.cpp:109
unsigned int GetValueSize() const
Definition: txdb.cpp:124
std::pair< char, uint256 > keyTmp
Definition: txdb.h:102
CCoinsViewDB(size_t nCacheSize, bool fMemory=false, bool fWipe=false)
Definition: txdb.cpp:28
CCoinsViewCursor * Cursor() const
Get a cursor to iterate over the whole state.
Definition: txdb.cpp:93
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock)
Do a bulk modification (multiple CCoins changes + BestBlock change).
Definition: txdb.cpp:47
CDBWrapper db
Definition: txdb.h:74
bool GetCoins(const uint256 &txid, CCoins &coins) const
Retrieve the CCoins (unspent transaction outputs) for a given txid.
Definition: txdb.cpp:32
uint256 GetBestBlock() const
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: txdb.cpp:40
bool HaveCoins(const uint256 &txid) const
Just check whether we have data for a given txid.
Definition: txdb.cpp:36
Batch of changes queued to be written to a CDBWrapper.
Definition: dbwrapper.h:49
void Erase(const K &key)
Definition: dbwrapper.h:83
void Write(const K &key, const V &value)
Definition: dbwrapper.h:66
CDBIterator * NewIterator()
Definition: dbwrapper.h:280
bool WriteBatch(CDBBatch &batch, bool fSync=false)
Definition: dbwrapper.cpp:91
bool Read(const K &key, V &value) const
Definition: dbwrapper.h:206
bool Erase(const K &key, bool fSync=false)
Definition: dbwrapper.h:259
bool Write(const K &key, const V &value, bool fSync=false)
Definition: dbwrapper.h:232
bool Exists(const K &key) const
Definition: dbwrapper.h:240
Used to marshal pointers into hashes for db storage.
Definition: chain.h:368
uint256 hashPrev
Definition: chain.h:370
uint256 GetBlockHash() const
Definition: chain.h:407
bool IsNull() const
Definition: uint256.h:32
256-bit opaque blob.
Definition: uint256.h:123
boost::unordered_map< uint256, CCoinsCacheEntry, SaltedTxidHasher > CCoinsMap
Definition: coins.h:282
@ DIRTY
Definition: coins.h:270
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:513
#define LogPrint(category,...)
Definition: util.h:76
bool error(const char *fmt, const Args &... args)
Definition: util.h:87