Anoncoin  0.9.4
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) 2013-2014 The Anoncoin Core developers
4 // Distributed under the MIT/X11 software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 
7 #include "txdb.h"
8 
9 #include "core.h"
10 #include "uint256.h"
11 
12 #include <stdint.h>
13 
14 using namespace std;
15 
16 void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) {
17  if (coins.IsPruned())
18  batch.Erase(make_pair('c', hash));
19  else
20  batch.Write(make_pair('c', hash), coins);
21 }
22 
23 void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) {
24  batch.Write('B', hash);
25 }
26 
27 CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe) {
28 }
29 
30 bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) {
31  return db.Read(make_pair('c', txid), coins);
32 }
33 
34 bool CCoinsViewDB::SetCoins(const uint256 &txid, const CCoins &coins) {
35  CLevelDBBatch batch;
36  BatchWriteCoins(batch, txid, coins);
37  return db.WriteBatch(batch);
38 }
39 
40 bool CCoinsViewDB::HaveCoins(const uint256 &txid) {
41  return db.Exists(make_pair('c', txid));
42 }
43 
45  uint256 hashBestChain;
46  if (!db.Read('B', hashBestChain))
47  return uint256(0);
48  return hashBestChain;
49 }
50 
51 bool CCoinsViewDB::SetBestBlock(const uint256 &hashBlock) {
52  CLevelDBBatch batch;
53  BatchWriteHashBestChain(batch, hashBlock);
54  return db.WriteBatch(batch);
55 }
56 
57 bool CCoinsViewDB::BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock) {
58  LogPrint("coindb", "Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size());
59 
60  CLevelDBBatch batch;
61  for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++)
62  BatchWriteCoins(batch, it->first, it->second);
63  if (hashBlock != uint256(0))
64  BatchWriteHashBestChain(batch, hashBlock);
65 
66  return db.WriteBatch(batch);
67 }
68 
69 CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
70 }
71 
73 {
74  return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
75 }
76 
77 bool CBlockTreeDB::WriteBestInvalidWork(const CBigNum& bnBestInvalidWork)
78 {
79  // Obsolete; only written for backward compatibility.
80  return Write('I', bnBestInvalidWork);
81 }
82 
83 bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) {
84  return Write(make_pair('f', nFile), info);
85 }
86 
88  return Read(make_pair('f', nFile), info);
89 }
90 
92  return Write('l', nFile);
93 }
94 
95 bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
96  if (fReindexing)
97  return Write('R', '1');
98  else
99  return Erase('R');
100 }
101 
102 bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
103  fReindexing = Exists('R');
104  return true;
105 }
106 
108  return Read('l', nFile);
109 }
110 
112  leveldb::Iterator *pcursor = db.NewIterator();
113  pcursor->SeekToFirst();
114 
115  CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
116  stats.hashBlock = GetBestBlock();
117  ss << stats.hashBlock;
118  int64_t nTotalAmount = 0;
119  while (pcursor->Valid()) {
120  boost::this_thread::interruption_point();
121  try {
122  leveldb::Slice slKey = pcursor->key();
123  CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
124  char chType;
125  ssKey >> chType;
126  if (chType == 'c') {
127  leveldb::Slice slValue = pcursor->value();
128  CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
129  CCoins coins;
130  ssValue >> coins;
131  uint256 txhash;
132  ssKey >> txhash;
133  ss << txhash;
134  ss << VARINT(coins.nVersion);
135  ss << (coins.fCoinBase ? 'c' : 'n');
136  ss << VARINT(coins.nHeight);
137  stats.nTransactions++;
138  for (unsigned int i=0; i<coins.vout.size(); i++) {
139  const CTxOut &out = coins.vout[i];
140  if (!out.IsNull()) {
141  stats.nTransactionOutputs++;
142  ss << VARINT(i+1);
143  ss << out;
144  nTotalAmount += out.nValue;
145  }
146  }
147  stats.nSerializedSize += 32 + slValue.size();
148  ss << VARINT(0);
149  }
150  pcursor->Next();
151  } catch (std::exception &e) {
152  return error("%s : Deserialize or I/O error - %s", __func__, e.what());
153  }
154  }
155  delete pcursor;
156  stats.nHeight = mapBlockIndex.find(GetBestBlock())->second->nHeight;
157  stats.hashSerialized = ss.GetHash();
158  stats.nTotalAmount = nTotalAmount;
159  return true;
160 }
161 
163  return Read(make_pair('t', txid), pos);
164 }
165 
166 bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
167  CLevelDBBatch batch;
168  for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
169  batch.Write(make_pair('t', it->first), it->second);
170  return WriteBatch(batch);
171 }
172 
173 bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
174  return Write(std::make_pair('F', name), fValue ? '1' : '0');
175 }
176 
177 bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
178  char ch;
179  if (!Read(std::make_pair('F', name), ch))
180  return false;
181  fValue = ch == '1';
182  return true;
183 }
184 
186 {
187  leveldb::Iterator *pcursor = NewIterator();
188 
189  CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
190  ssKeySet << make_pair('b', uint256(0));
191  pcursor->Seek(ssKeySet.str());
192 
193  // Load mapBlockIndex
194  while (pcursor->Valid()) {
195  boost::this_thread::interruption_point();
196  try {
197  leveldb::Slice slKey = pcursor->key();
198  CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
199  char chType;
200  ssKey >> chType;
201  if (chType == 'b') {
202  leveldb::Slice slValue = pcursor->value();
203  CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
204  CDiskBlockIndex diskindex;
205  ssValue >> diskindex;
206 
207  // Construct block index object
208  CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
209  pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev);
210  pindexNew->nHeight = diskindex.nHeight;
211  pindexNew->nFile = diskindex.nFile;
212  pindexNew->nDataPos = diskindex.nDataPos;
213  pindexNew->nUndoPos = diskindex.nUndoPos;
214  pindexNew->nVersion = diskindex.nVersion;
215  pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
216  pindexNew->nTime = diskindex.nTime;
217  pindexNew->nBits = diskindex.nBits;
218  pindexNew->nNonce = diskindex.nNonce;
219  pindexNew->nStatus = diskindex.nStatus;
220  pindexNew->nTx = diskindex.nTx;
221 
222  if (!pindexNew->CheckIndex())
223  return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString());
224 
225  pcursor->Next();
226  } else {
227  break; // if shutdown requested or finished loading block index
228  }
229  } catch (std::exception &e) {
230  return error("%s : Deserialize or I/O error - %s", __func__, e.what());
231  }
232  }
233  delete pcursor;
234 
235  return true;
236 }
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:968
#define VARINT(obj)
Definition: serialize.h:319
uint64_t nTransactionOutputs
Definition: coins.h:249
int64_t nTotalAmount
Definition: coins.h:252
uint256 hashBlock
Definition: coins.h:247
CBlockIndex * pprev
Definition: main.h:705
bool Erase(const K &key, bool fSync=false)
int nHeight
Definition: coins.h:246
bool IsNull() const
Definition: core.h:146
bool ReadReindexing(bool &fReindex)
Definition: txdb.cpp:102
bool ReadLastBlockFile(int &nFile)
Definition: txdb.cpp:107
std::string ToString() const
Definition: main.h:866
uint64_t nTransactions
Definition: coins.h:248
bool WriteBlockIndex(const CDiskBlockIndex &blockindex)
Definition: txdb.cpp:72
bool Write(const K &key, const V &value, bool fSync=false)
bool GetCoins(const uint256 &txid, CCoins &coins)
Definition: txdb.cpp:30
Double ended buffer combining vector and stream-like interfaces.
Definition: serialize.h:848
int nFile
Definition: main.h:711
void Write(const K &key, const V &value)
pruned version of CTransaction: only retains metadata and unspent transaction outputs ...
Definition: coins.h:69
bool Exists(const K &key)
bool LoadBlockIndexGuts()
Definition: txdb.cpp:185
bool CheckIndex() const
Definition: main.h:834
uint256 hashSerialized
Definition: coins.h:251
std::string str() const
Definition: serialize.h:924
unsigned int nTime
Definition: main.h:735
unsigned int nStatus
Definition: main.h:730
unsigned int nDataPos
Definition: main.h:714
CLevelDBWrapper db
Definition: txdb.h:33
uint64_t nSerializedSize
Definition: coins.h:250
C++ wrapper for BIGNUM (OpenSSL bignum)
Definition: bignum.h:57
unsigned int nBits
Definition: main.h:736
uint256 hashMerkleRoot
Definition: main.h:734
bool WriteBlockFileInfo(int nFile, const CBlockFileInfo &fileinfo)
Definition: txdb.cpp:83
An output of a transaction.
Definition: core.h:121
Used to marshal pointers into hashes for db storage.
Definition: main.h:883
bool WriteLastBlockFile(int nFile)
Definition: txdb.cpp:91
bool Read(const K &key, V &value)
bool ReadFlag(const std::string &name, bool &fValue)
Definition: txdb.cpp:177
CBlockTreeDB(size_t nCacheSize, bool fMemory=false, bool fWipe=false)
Definition: txdb.cpp:69
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &fileinfo)
Definition: txdb.cpp:87
CBlockIndex * InsertBlockIndex(uint256 hash)
Create a new block index entry for a given block hash.
Definition: main.cpp:2737
bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos)
Definition: txdb.cpp:162
int nVersion
Definition: main.h:733
CCoinsViewDB(size_t nCacheSize, bool fMemory=false, bool fWipe=false)
Definition: txdb.cpp:27
unsigned int nUndoPos
Definition: main.h:717
uint256 GetHash()
Definition: hash.h:53
256-bit unsigned integer
Definition: uint256.h:532
bool BatchWrite(const std::map< uint256, CCoins > &mapCoins, const uint256 &hashBlock)
Definition: txdb.cpp:57
bool GetStats(CCoinsStats &stats)
Definition: txdb.cpp:111
bool SetBestBlock(const uint256 &hashBlock)
Definition: txdb.cpp:51
bool WriteBatch(CLevelDBBatch &batch, bool fSync=false)
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: main.h:698
bool IsPruned() const
Definition: coins.h:235
bool WriteTxIndex(const std::vector< std::pair< uint256, CDiskTxPos > > &list)
Definition: txdb.cpp:166
void Erase(const K &key)
bool WriteReindexing(bool fReindex)
Definition: txdb.cpp:95
bool HaveCoins(const uint256 &txid)
Definition: txdb.cpp:40
bool WriteFlag(const std::string &name, bool fValue)
Definition: txdb.cpp:173
int nHeight
Definition: main.h:708
leveldb::Iterator * NewIterator()
map< uint256, CBlockIndex * > mapBlockIndex
Definition: main.cpp:42
uint256 GetBestBlock()
Definition: txdb.cpp:44
unsigned int nNonce
Definition: main.h:737
unsigned int nTx
Definition: main.h:724
uint256 GetBlockHash() const
Definition: main.h:815
int64_t nValue
Definition: core.h:124
bool SetCoins(const uint256 &txid, const CCoins &coins)
Definition: txdb.cpp:34
bool WriteBestInvalidWork(const CBigNum &bnBestInvalidWork)
Definition: txdb.cpp:77