PRCYCoin  2.0.0.7rc1
P2P Digital Currency
txdb.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin developers
3 // Copyright (c) 2015-2018 The PIVX developers
4 // Copyright (c) 2018-2020 The DAPS Project developers
5 // Distributed under the MIT/X11 software license, see the accompanying
6 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 
8 #include "txdb.h"
9 
10 #include "main.h"
11 #include "poa.h"
12 #include "uint256.h"
13 
14 #include <stdint.h>
15 
16 #include <boost/thread.hpp>
17 
18 static const char DB_COINS = 'c';
19 static const char DB_BLOCK_FILES = 'f';
20 static const char DB_TXINDEX = 't';
21 static const char DB_BLOCK_INDEX = 'b';
22 
23 static const char DB_BEST_BLOCK = 'B';
24 static const char DB_FLAG = 'F';
25 static const char DB_REINDEX_FLAG = 'R';
26 static const char DB_LAST_BLOCK = 'l';
27 static const char DB_INT = 'I';
28 static const char DB_KEYIMAGE = 'k';
29 
30 
31 CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe)
32 {
33 }
34 
35 bool CCoinsViewDB::GetCoins(const uint256& txid, CCoins& coins) const
36 {
37  return db.Read(std::make_pair(DB_COINS, txid), coins);
38 }
39 
40 bool CCoinsViewDB::HaveCoins(const uint256& txid) const
41 {
42  return db.Exists(std::make_pair(DB_COINS, txid));
43 }
44 
46 {
47  uint256 hashBestChain;
48  if (!db.Read(DB_BEST_BLOCK, hashBestChain))
49  return UINT256_ZERO;
50  return hashBestChain;
51 }
52 
53 bool CCoinsViewDB::BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock)
54 {
55  CDBBatch batch;
56  size_t count = 0;
57  size_t changed = 0;
58  for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
59  if (it->second.flags & CCoinsCacheEntry::DIRTY) {
60  if (it->second.coins.IsPruned())
61  batch.Erase(std::make_pair(DB_COINS, it->first));
62  else
63  batch.Write(std::make_pair(DB_COINS, it->first), it->second.coins);
64  changed++;
65  }
66  count++;
67  CCoinsMap::iterator itOld = it++;
68  mapCoins.erase(itOld);
69  }
70  if (!hashBlock.IsNull())
71  batch.Write(DB_BEST_BLOCK, hashBlock);
72 
73  LogPrint(BCLog::COINDB, "Committing %u changed transactions (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
74  return db.WriteBatch(batch);
75 }
76 
77 CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe)
78 {
79 }
80 
82 {
83  return Write(std::make_pair(DB_BLOCK_INDEX, blockindex.GetBlockHash()), blockindex);
84 }
85 
86 
88 {
89  return Read(std::make_pair(DB_BLOCK_FILES, nFile), info);
90 }
91 
92 bool CBlockTreeDB::WriteReindexing(bool fReindexing)
93 {
94  if (fReindexing)
95  return Write(DB_REINDEX_FLAG, '1');
96  else
97  return Erase(DB_REINDEX_FLAG);
98 }
99 
100 bool CBlockTreeDB::ReadReindexing(bool& fReindexing)
101 {
102  fReindexing = Exists(DB_REINDEX_FLAG);
103  return true;
104 }
105 
107 {
108  return Read(DB_LAST_BLOCK, nFile);
109 }
110 
112 {
113  /* It seems that there are no "const iterators" for LevelDB. Since we
114  only need read operations on it, use a const-cast to get around
115  that restriction. */
116  boost::scoped_ptr<CDBIterator> pcursor(const_cast<CDBWrapper*>(&db)->NewIterator());
117  pcursor->Seek(DB_COINS);
118 
119  CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
120  stats.hashBlock = GetBestBlock();
121  ss << stats.hashBlock;
122  CAmount nTotalAmount = 0;
123  while (pcursor->Valid()) {
124  boost::this_thread::interruption_point();
125  std::pair<char, uint256> key;
126  CCoins coins;
127  if (pcursor->GetKey(key) && key.first == DB_COINS) {
128  if (pcursor->GetValue(coins)) {
129  stats.nTransactions++;
130  for (unsigned int i = 0; i < coins.vout.size(); i++) {
131  const CTxOut& out = coins.vout[i];
132  if (!out.IsNull()) {
133  stats.nTransactionOutputs++;
134  ss << VARINT(i + 1);
135  ss << out;
136  nTotalAmount += out.nValue;
137  }
138  }
139  stats.nSerializedSize += 32 + pcursor->GetValueSize();
140  ss << VARINT(0);
141  } else {
142  return error("CCoinsViewDB::GetStats() : unable to read value");
143  }
144  } else {
145  break;
146  }
147  pcursor->Next();
148  }
149 
150  stats.nHeight = WITH_LOCK(cs_main, return mapBlockIndex.find(stats.hashBlock)->second->nHeight;);
151  stats.hashSerialized = ss.GetHash();
152  stats.nTotalAmount = nTotalAmount;
153  return true;
154 }
155 
156 bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
157  CDBBatch batch;
158  for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
159  batch.Write(std::make_pair(DB_BLOCK_FILES, it->first), *it->second);
160  }
161  batch.Write(DB_LAST_BLOCK, nLastFile);
162  for (std::vector<const CBlockIndex*>::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) {
163  batch.Write(std::make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it));
164  }
165  return WriteBatch(batch, true);
166 }
167 
169 {
170  return Read(std::make_pair(DB_TXINDEX, txid), pos);
171 }
172 
173 bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >& vect)
174 {
175  CDBBatch batch;
176  for (std::vector<std::pair<uint256, CDiskTxPos> >::const_iterator it = vect.begin(); it != vect.end(); it++) {
177  batch.Write(std::make_pair(DB_TXINDEX, it->first), it->second);
178  }
179  return WriteBatch(batch);
180 }
181 
182 
183 bool CBlockTreeDB::ReadKeyImage(const std::string& keyImage, uint256& bh)
184 {
185  return Read(std::make_pair(DB_KEYIMAGE, keyImage), bh);
186 }
187 
188 bool CBlockTreeDB::ReadKeyImages(const std::string& keyImage, std::vector<uint256>& bhs)
189 {
190  uint256 bh;
191  if (!Read(std::make_pair(DB_KEYIMAGE, keyImage), bh)) return false;
192  bhs.push_back(bh);
193  int i = 1;
194  while(ReadKeyImage(keyImage + std::to_string(i), bh)) {
195  bhs.push_back(bh);
196  i++;
197  }
198  return true;
199 }
200 
201 bool CBlockTreeDB::WriteKeyImage(const std::string& keyImage, const uint256& bh)
202 {
203  uint256 blockHash;
204  if (!ReadKeyImage(keyImage, blockHash)) {
205  return Write(std::make_pair(DB_KEYIMAGE, keyImage), bh);
206  }
207  int i = 1;
208  while (ReadKeyImage(keyImage + std::to_string(i), blockHash)) {
209  i++;
210  }
211  return Write(std::make_pair(DB_KEYIMAGE, keyImage + std::to_string(i)), bh);
212 }
213 
214 bool CBlockTreeDB::WriteFlag(const std::string& name, bool fValue)
215 {
216  return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
217 }
218 
219 bool CBlockTreeDB::ReadFlag(const std::string& name, bool& fValue)
220 {
221  char ch;
222  if (!Read(std::make_pair(DB_FLAG, name), ch))
223  return false;
224  fValue = ch == '1';
225  return true;
226 }
227 
228 bool CBlockTreeDB::WriteInt(const std::string& name, int nValue)
229 {
230  return Write(std::make_pair(DB_INT, name), nValue);
231 }
232 
233 bool CBlockTreeDB::ReadInt(const std::string& name, int& nValue)
234 {
235  return Read(std::make_pair(DB_INT, name), nValue);
236 }
237 
239 {
240  boost::scoped_ptr<CDBIterator> pcursor(NewIterator());
241 
242  pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, UINT256_ZERO));
243 
244  // Load mapBlockIndex
245  uint256 nPreviousCheckpoint;
246  while (pcursor->Valid()) {
247  boost::this_thread::interruption_point();
248  std::pair<char, uint256> key;
249  if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) {
250  CDiskBlockIndex diskindex;
251  if (pcursor->GetValue(diskindex)) {
252  // Construct block index object
253  CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
254  pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev);
255  pindexNew->pnext = InsertBlockIndex(diskindex.hashNext);
256  pindexNew->nHeight = diskindex.nHeight;
257  pindexNew->nFile = diskindex.nFile;
258  pindexNew->nDataPos = diskindex.nDataPos;
259  pindexNew->nUndoPos = diskindex.nUndoPos;
260  pindexNew->nVersion = diskindex.nVersion;
261  pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
262  pindexNew->nTime = diskindex.nTime;
263  pindexNew->nBits = diskindex.nBits;
264  pindexNew->nNonce = diskindex.nNonce;
265  pindexNew->nStatus = diskindex.nStatus;
266  pindexNew->nTx = diskindex.nTx;
267 
268  //Proof of Audit
269  pindexNew->hashPoAMerkleRoot = diskindex.hashPoAMerkleRoot;
270  pindexNew->hashPrevPoABlock = diskindex.hashPrevPoABlock;
271  pindexNew->minedHash = diskindex.minedHash;
272 
273  //Proof Of Stake
274  pindexNew->nMint = diskindex.nMint;
275  pindexNew->nMoneySupply = diskindex.nMoneySupply;
276  pindexNew->nFlags = diskindex.nFlags;
277  pindexNew->nStakeModifier = diskindex.nStakeModifier;
278  pindexNew->prevoutStake = diskindex.prevoutStake;
279  pindexNew->nStakeTime = diskindex.nStakeTime;
280  pindexNew->hashProofOfStake = diskindex.hashProofOfStake;
281 
282  if (pindexNew->nHeight <= Params().LAST_POW_BLOCK()) {
283  if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits))
284  return error("LoadBlockIndex() : CheckProofOfWork failed: %s", pindexNew->ToString());
285  }
286 
287  //populate accumulator checksum map in memory
288  if(pindexNew->nAccumulatorCheckpoint != 0 && pindexNew->nAccumulatorCheckpoint != nPreviousCheckpoint) {
289  nPreviousCheckpoint = pindexNew->nAccumulatorCheckpoint;
290  }
291 
292  pcursor->Next();
293  } else {
294  return error("%s : failed to read value", __func__);
295  }
296  } else {
297  break;
298  }
299  }
300 
301  return true;
302 }
CBlockIndex::minedHash
uint256 minedHash
Definition: chain.h:235
CCoinsViewDB::GetCoins
bool GetCoins(const uint256 &txid, CCoins &coins) const
Retrieve the CCoins (unspent transaction outputs) for a given txid.
Definition: txdb.cpp:35
CBlockIndex::pnext
CBlockIndex * pnext
pointer to the index of the next block
Definition: chain.h:172
UINT256_ZERO
const uint256 UINT256_ZERO
constant uint256 instances
Definition: uint256.h:129
CBlockTreeDB::WriteInt
bool WriteInt(const std::string &name, int nValue)
Definition: txdb.cpp:228
CBlockIndex::nFile
int nFile
Which # file this block is stored in (blk?????.dat)
Definition: chain.h:184
CBlockIndex::nMint
int64_t nMint
Definition: chain.h:222
SER_GETHASH
@ SER_GETHASH
Definition: serialize.h:161
CCoinsViewDB::GetStats
bool GetStats(CCoinsStats &stats) const
Calculate statistics about the unspent transaction output set.
Definition: txdb.cpp:111
CDBBatch
Batch of changes queued to be written to a CDBWrapper.
Definition: dbwrapper.h:39
CBlockIndex::nTx
unsigned int nTx
Number of transactions in this block.
Definition: chain.h:197
CBlockTreeDB::LoadBlockIndexGuts
bool LoadBlockIndexGuts()
Definition: txdb.cpp:238
CBlockIndex::nMoneySupply
int64_t nMoneySupply
Definition: chain.h:223
CBlockIndex::nNonce
unsigned int nNonce
Definition: chain.h:230
uint256.h
CCoinsStats::nTransactions
uint64_t nTransactions
Definition: coins.h:335
CBlockIndex::pprev
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:169
CBlockIndex::nStakeTime
unsigned int nStakeTime
Definition: chain.h:220
CBlockIndex::nHeight
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:181
CCoinsStats
Definition: coins.h:332
CBlockIndex::ToString
std::string ToString() const
Definition: chain.h:445
CBlockIndex::nBits
unsigned int nBits
Definition: chain.h:229
WITH_LOCK
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:209
CDiskTxPos
Definition: txdb.h:29
CDBWrapper::Read
bool Read(const K &key, V &value) const
Definition: dbwrapper.h:169
CBlockIndex::nDataPos
unsigned int nDataPos
Byte offset within blk?????.dat where this block's data is stored.
Definition: chain.h:187
CDiskBlockIndex
Used to marshal pointers into hashes for db storage.
Definition: chain.h:485
CBlockIndex::nStatus
unsigned int nStatus
Verification status of this block. See enum BlockStatus.
Definition: chain.h:205
CDiskBlockIndex::hashNext
uint256 hashNext
Definition: chain.h:489
CBlockTreeDB::ReadReindexing
bool ReadReindexing(bool &fReindex)
Definition: txdb.cpp:100
CBlockIndex::nFlags
unsigned int nFlags
Definition: chain.h:207
CDBBatch::Write
void Write(const K &key, const V &value)
Definition: dbwrapper.h:49
CBlockIndex::nTime
unsigned int nTime
Definition: chain.h:228
CTxOut::nValue
CAmount nValue
Definition: transaction.h:167
cs_main
RecursiveMutex cs_main
Global state.
Definition: main.cpp:65
CTxOut::IsNull
bool IsNull() const
Definition: transaction.h:209
CCoins::vout
std::vector< CTxOut > vout
unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are d...
Definition: coins.h:85
CDBWrapper::NewIterator
CDBIterator * NewIterator()
Definition: dbwrapper.h:243
CBlockTreeDB::WriteBlockIndex
bool WriteBlockIndex(const CDiskBlockIndex &blockindex)
Definition: txdb.cpp:81
CBlockIndex::hashPrevPoABlock
uint256 hashPrevPoABlock
Definition: chain.h:236
CTxOut
An output of a transaction.
Definition: transaction.h:164
CCoinsViewDB::HaveCoins
bool HaveCoins(const uint256 &txid) const
Just check whether we have data for a given txid.
Definition: txdb.cpp:40
CCoinsStats::hashBlock
uint256 hashBlock
Definition: coins.h:334
CBlockTreeDB::WriteBatchSync
bool WriteBatchSync(const std::vector< std::pair< int, const CBlockFileInfo * > > &fileInfo, int nLastFile, const std::vector< const CBlockIndex * > &blockinfo)
Definition: txdb.cpp:156
VARINT
#define VARINT(obj)
Definition: serialize.h:366
CBlockTreeDB::ReadBlockFileInfo
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &fileinfo)
Definition: txdb.cpp:87
CBlockIndex::hashMerkleRoot
uint256 hashMerkleRoot
Definition: chain.h:227
CAmount
int64_t CAmount
Amount in PRCY (Can be negative)
Definition: amount.h:17
CBlockIndex::nStakeModifier
uint64_t nStakeModifier
Definition: chain.h:217
CBlockIndex::prevoutStake
COutPoint prevoutStake
Definition: chain.h:219
uint256
256-bit unsigned big integer.
Definition: uint256.h:38
CBlockTreeDB::ReadFlag
bool ReadFlag(const std::string &name, bool &fValue)
Definition: txdb.cpp:219
CBlockIndex::nVersion
int nVersion
block header
Definition: chain.h:226
CDBWrapper::Erase
bool Erase(const K &key, bool fSync=false)
Definition: dbwrapper.h:221
CCoinsViewDB::GetBestBlock
uint256 GetBestBlock() const
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: txdb.cpp:45
LogPrint
#define LogPrint(category,...)
Definition: logging.h:162
CCoinsViewDB::db
CDBWrapper db
Definition: txdb.h:61
base_uint::IsNull
bool IsNull() const
Definition: arith_uint256.h:312
CCoinsViewDB::CCoinsViewDB
CCoinsViewDB(size_t nCacheSize, bool fMemory=false, bool fWipe=false)
Definition: txdb.cpp:31
CheckProofOfWork
bool CheckProofOfWork(uint256 hash, unsigned int nBits)
Check whether a block hash satisfies the proof-of-work requirement specified by nBits.
Definition: poa.cpp:145
CBlockIndex::GetBlockHash
uint256 GetBlockHash() const
Definition: chain.h:359
CCoinsViewDB::BatchWrite
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock)
Do a bulk modification (multiple CCoins changes + BestBlock change).
Definition: txdb.cpp:53
CBlockTreeDB::ReadInt
bool ReadInt(const std::string &name, int &nValue)
Definition: txdb.cpp:233
CCoinsStats::nSerializedSize
uint64_t nSerializedSize
Definition: coins.h:337
CBlockIndex::nAccumulatorCheckpoint
uint256 nAccumulatorCheckpoint
Definition: chain.h:231
CBlockTreeDB::WriteTxIndex
bool WriteTxIndex(const std::vector< std::pair< uint256, CDiskTxPos > > &list)
Definition: txdb.cpp:173
name
const char * name
Definition: rest.cpp:34
poa.h
CDBWrapper
Definition: dbwrapper.h:134
CBlockTreeDB::WriteReindexing
bool WriteReindexing(bool fReindex)
Definition: txdb.cpp:92
CBlockTreeDB::WriteFlag
bool WriteFlag(const std::string &name, bool fValue)
Definition: txdb.cpp:214
CCoinsStats::nHeight
int nHeight
Definition: coins.h:333
BCLog::COINDB
@ COINDB
Definition: logging.h:58
CBlockTreeDB::ReadTxIndex
bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos)
Definition: txdb.cpp:168
CCoinsStats::nTransactionOutputs
uint64_t nTransactionOutputs
Definition: coins.h:336
main.h
CBlockIndex::nUndoPos
unsigned int nUndoPos
Byte offset within rev?????.dat where this block's undo data is stored.
Definition: chain.h:190
key
CKey key
Definition: bip38tooldialog.cpp:173
CBlockFileInfo
Definition: chain.h:18
CDBBatch::Erase
void Erase(const K &key)
Definition: dbwrapper.h:65
CHashWriter
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:259
CCoinsStats::nTotalAmount
CAmount nTotalAmount
Definition: coins.h:339
GetDataDir
const fs::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:349
CBlockTreeDB::CBlockTreeDB
CBlockTreeDB(size_t nCacheSize, bool fMemory=false, bool fWipe=false)
Definition: txdb.cpp:77
Params
const CChainParams & Params()
Return the currently selected parameters.
Definition: chainparams.cpp:463
CCoinsMap
boost::unordered_map< uint256, CCoinsCacheEntry, CCoinsKeyHasher > CCoinsMap
Definition: coins.h:330
InsertBlockIndex
CBlockIndex * InsertBlockIndex(uint256 hash)
Create a new block index entry for a given block hash.
Definition: main.cpp:5165
CBlockIndex::hashPoAMerkleRoot
uint256 hashPoAMerkleRoot
PoA block header.
Definition: chain.h:234
CDiskBlockIndex::hashPrev
uint256 hashPrev
Definition: chain.h:488
CCoinsStats::hashSerialized
uint256 hashSerialized
Definition: coins.h:338
CDiskBlockIndex::GetBlockHash
uint256 GetBlockHash() const
Definition: chain.h:555
CCoins
Definition: coins.h:77
CDBWrapper::Write
bool Write(const K &key, const V &value, bool fSync=false)
Definition: dbwrapper.h:194
CDBWrapper::Exists
bool Exists(const K &key) const
Definition: dbwrapper.h:202
CBlockIndex::hashProofOfStake
uint256 hashProofOfStake
Definition: chain.h:221
CBlockTreeDB::ReadKeyImages
bool ReadKeyImages(const std::string &keyImage, std::vector< uint256 > &bhs)
Definition: txdb.cpp:188
CCoinsCacheEntry::DIRTY
@ DIRTY
Definition: coins.h:323
CHashWriter::GetHash
uint256 GetHash()
Definition: hash.h:277
CBlockIndex
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:162
CDBWrapper::WriteBatch
bool WriteBatch(CDBBatch &batch, bool fSync=false)
Definition: dbwrapper.cpp:96
CBlockTreeDB::WriteKeyImage
bool WriteKeyImage(const std::string &keyImage, const uint256 &height)
Definition: txdb.cpp:201
txdb.h
error
bool error(const char *fmt, const Args &... args)
Definition: util.h:61
mapBlockIndex
BlockMap mapBlockIndex
Definition: main.cpp:67
CBlockTreeDB::ReadKeyImage
bool ReadKeyImage(const std::string &keyImage, uint256 &bh)
Definition: txdb.cpp:183
CBlockTreeDB::ReadLastBlockFile
bool ReadLastBlockFile(int &nFile)
Definition: txdb.cpp:106