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