Feathercoin  0.5.0
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
txdb.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Copyright (c) 2011-2013 PPCoin developers
4 // Copyright (c) 2013 The Primecoin developers
5 // Copyright (c) 2013 The Feathercoin developers
6 // Distributed under the MIT/X11 software license, see the accompanying
7 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
8 
9 #include "txdb.h"
10 #include "main.h"
11 #include "hash.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 
45  if (!db.Read('B', hashBestChain))
46  return NULL;
47  std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(hashBestChain);
48  if (it == mapBlockIndex.end())
49  return NULL;
50  return it->second;
51 }
52 
54  CLevelDBBatch batch;
55  BatchWriteHashBestChain(batch, pindex->GetBlockHash());
56  return db.WriteBatch(batch);
57 }
58 
59 bool CCoinsViewDB::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) {
60  printf("Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size());
61 
62  CLevelDBBatch batch;
63  for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++)
64  BatchWriteCoins(batch, it->first, it->second);
65  if (pindex)
66  BatchWriteHashBestChain(batch, pindex->GetBlockHash());
67 
68  return db.WriteBatch(batch);
69 }
70 
71 CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDB(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
72 }
73 
75 {
76  return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
77 }
78 
80 {
81  return Read('I', bnBestInvalidWork);
82 }
83 
84 bool CBlockTreeDB::WriteBestInvalidWork(const CBigNum& bnBestInvalidWork)
85 {
86  return Write('I', bnBestInvalidWork);
87 }
88 
89 bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) {
90  return Write(make_pair('f', nFile), info);
91 }
92 
94  return Read(make_pair('f', nFile), info);
95 }
96 
98  return Write('l', nFile);
99 }
100 
101 bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
102  if (fReindexing)
103  return Write('R', '1');
104  else
105  return Erase('R');
106 }
107 
108 bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
109  fReindexing = Exists('R');
110  return true;
111 }
112 
114  return Read('l', nFile);
115 }
116 
118  leveldb::Iterator *pcursor = db.NewIterator();
119  pcursor->SeekToFirst();
120 
121  CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
122  stats.hashBlock = GetBestBlock()->GetBlockHash();
123  ss << stats.hashBlock;
124  int64 nTotalAmount = 0;
125  while (pcursor->Valid()) {
126  boost::this_thread::interruption_point();
127  try {
128  leveldb::Slice slKey = pcursor->key();
129  CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
130  char chType;
131  ssKey >> chType;
132  if (chType == 'c') {
133  leveldb::Slice slValue = pcursor->value();
134  CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
135  CCoins coins;
136  ssValue >> coins;
137  uint256 txhash;
138  ssKey >> txhash;
139  ss << txhash;
140  ss << VARINT(coins.nVersion);
141  ss << (coins.fCoinBase ? 'c' : 'n');
142  ss << VARINT(coins.nHeight);
143  stats.nTransactions++;
144  for (unsigned int i=0; i<coins.vout.size(); i++) {
145  const CTxOut &out = coins.vout[i];
146  if (!out.IsNull()) {
147  stats.nTransactionOutputs++;
148  ss << VARINT(i+1);
149  ss << out;
150  nTotalAmount += out.nValue;
151  }
152  }
153  stats.nSerializedSize += 32 + slValue.size();
154  ss << VARINT(0);
155  }
156  pcursor->Next();
157  } catch (std::exception &e) {
158  return error("%s() : deserialize error", __PRETTY_FUNCTION__);
159  }
160  }
161  delete pcursor;
162  stats.nHeight = GetBestBlock()->nHeight;
163  stats.hashSerialized = ss.GetHash();
164  stats.nTotalAmount = nTotalAmount;
165  return true;
166 }
167 
169  return Read(make_pair('t', txid), pos);
170 }
171 
172 bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
173  CLevelDBBatch batch;
174  for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
175  batch.Write(make_pair('t', it->first), it->second);
176  return WriteBatch(batch);
177 }
178 
179 bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
180  return Write(std::make_pair('F', name), fValue ? '1' : '0');
181 }
182 
183 bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
184  char ch;
185  if (!Read(std::make_pair('F', name), ch))
186  return false;
187  fValue = ch == '1';
188  return true;
189 }
190 
192 {
193  leveldb::Iterator *pcursor = NewIterator();
194 
195  CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
196  ssKeySet << make_pair('b', uint256(0));
197  pcursor->Seek(ssKeySet.str());
198 
199  // Load mapBlockIndex
200  while (pcursor->Valid()) {
201  boost::this_thread::interruption_point();
202  try {
203  leveldb::Slice slKey = pcursor->key();
204  CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
205  char chType;
206  ssKey >> chType;
207  if (chType == 'b') {
208  leveldb::Slice slValue = pcursor->value();
209  CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
210  CDiskBlockIndex diskindex;
211  ssValue >> diskindex;
212 
213  // Construct block index object
214  CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
215  pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev);
216  pindexNew->nHeight = diskindex.nHeight;
217  pindexNew->nFile = diskindex.nFile;
218  pindexNew->nDataPos = diskindex.nDataPos;
219  pindexNew->nUndoPos = diskindex.nUndoPos;
220  pindexNew->nVersion = diskindex.nVersion;
221  pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
222  pindexNew->nTime = diskindex.nTime;
223  pindexNew->nBits = diskindex.nBits;
224  pindexNew->nNonce = diskindex.nNonce;
225  pindexNew->nStatus = diskindex.nStatus;
226  pindexNew->nTx = diskindex.nTx;
227 
228  // Watch for genesis block
229  if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
230  pindexGenesisBlock = pindexNew;
231 
232  if (!pindexNew->CheckIndex())
233  return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString().c_str());
234 
235  pcursor->Next();
236  } else {
237  break; // if shutdown requested or finished loading block index
238  }
239  } catch (std::exception &e) {
240  return error("%s() : deserialize error", __PRETTY_FUNCTION__);
241  }
242  }
243  delete pcursor;
244 
245  return true;
246 }
247 
249 {
250  return Read(string("hashSyncCheckpoint"), hashCheckpoint);
251 }
252 
254 {
255  return Write(string("hashSyncCheckpoint"), hashCheckpoint);
256 }
257 
258 bool CBlockTreeDB::ReadCheckpointPubKey(string& strPubKey)
259 {
260  return Read(string("strCheckpointPubKey"), strPubKey);
261 }
262 
263 bool CBlockTreeDB::WriteCheckpointPubKey(const string& strPubKey)
264 {
265  return Write(string("strCheckpointPubKey"), strPubKey);
266 }
bool Read(const K &key, V &value)
Definition: leveldb.h:83
bool error(const char *format,...)
Definition: util.cpp:358
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:1060
bool SetBestBlock(CBlockIndex *pindex)
Definition: txdb.cpp:53
#define VARINT(obj)
Definition: serialize.h:305
bool Write(const K &key, const V &value, bool fSync=false)
Definition: leveldb.h:106
bool BatchWrite(const std::map< uint256, CCoins > &mapCoins, CBlockIndex *pindex)
Definition: txdb.cpp:59
uint256 hashBlock
Definition: main.h:2135
CBlockIndex * pprev
Definition: main.h:1633
int nHeight
Definition: main.h:2134
bool ReadCheckpointPubKey(std::string &strPubKey)
Definition: txdb.cpp:258
bool IsNull() const
Definition: main.h:429
const char * data() const
Definition: slice.h:40
bool WriteSyncCheckpoint(uint256 hashCheckpoint)
Definition: txdb.cpp:253
bool ReadReindexing(bool &fReindex)
Definition: txdb.cpp:108
bool ReadLastBlockFile(int &nFile)
Definition: txdb.cpp:113
bool WriteBatch(CLevelDBBatch &batch, bool fSync=false)
Definition: leveldb.cpp:73
std::string ToString() const
Definition: main.h:1810
bool WriteBlockIndex(const CDiskBlockIndex &blockindex)
Definition: txdb.cpp:74
bool GetCoins(const uint256 &txid, CCoins &coins)
Definition: txdb.cpp:29
Double ended buffer combining vector and stream-like interfaces.
Definition: serialize.h:799
int nFile
Definition: main.h:1642
void Write(const K &key, const V &value)
Definition: leveldb.h:31
pruned version of CTransaction: only retains metadata and unspent transaction outputs ...
Definition: main.h:896
bool LoadBlockIndexGuts()
Definition: txdb.cpp:191
bool Exists(const K &key)
Definition: leveldb.h:112
uint256 hashGenesisBlock("0x12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2")
bool CheckIndex() const
Definition: main.h:1768
virtual Slice value() const =0
virtual void Next()=0
CLevelDB db
Definition: txdb.h:18
uint256 hashSerialized
Definition: main.h:2139
std::string str() const
Definition: serialize.h:875
unsigned int nTime
Definition: main.h:1666
unsigned int nStatus
Definition: main.h:1661
bool Erase(const K &key, bool fSync=false)
Definition: leveldb.h:129
unsigned int nDataPos
Definition: main.h:1645
#define printf
Definition: rpcdump.cpp:12
size_t size() const
Definition: slice.h:43
bool ReadBestInvalidWork(CBigNum &bnBestInvalidWork)
Definition: txdb.cpp:79
C++ wrapper for BIGNUM (OpenSSL bignum)
Definition: bignum.h:51
unsigned int nBits
Definition: main.h:1667
virtual void Seek(const Slice &target)=0
uint256 hashMerkleRoot
Definition: main.h:1665
bool WriteBlockFileInfo(int nFile, const CBlockFileInfo &fileinfo)
Definition: txdb.cpp:89
virtual void SeekToFirst()=0
An output of a transaction.
Definition: main.h:400
Used to marshal pointers into hashes for db storage.
Definition: main.h:1840
bool ReadSyncCheckpoint(uint256 &hashCheckpoint)
Definition: txdb.cpp:248
bool WriteLastBlockFile(int nFile)
Definition: txdb.cpp:97
CBlockIndex * GetBestBlock()
Definition: txdb.cpp:43
bool ReadFlag(const std::string &name, bool &fValue)
Definition: txdb.cpp:183
CBlockTreeDB(size_t nCacheSize, bool fMemory=false, bool fWipe=false)
Definition: txdb.cpp:71
bool ReadBlockFileInfo(int nFile, CBlockFileInfo &fileinfo)
Definition: txdb.cpp:93
CBlockIndex * InsertBlockIndex(uint256 hash)
Create a new block index entry for a given block hash.
Definition: main.cpp:2637
bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos)
Definition: txdb.cpp:168
int nVersion
Definition: main.h:1664
CCoinsViewDB(size_t nCacheSize, bool fMemory=false, bool fWipe=false)
Definition: txdb.cpp:26
unsigned int nUndoPos
Definition: main.h:1648
uint256 GetHash()
Definition: hash.h:49
256-bit unsigned integer
Definition: uint256.h:537
CBlockIndex * pindexGenesisBlock
Definition: main.cpp:40
uint256 hashBestChain
Definition: main.cpp:44
bool GetStats(CCoinsStats &stats)
Definition: txdb.cpp:117
int64 nValue
Definition: main.h:403
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: main.h:1626
leveldb::Iterator * NewIterator()
Definition: leveldb.h:148
virtual bool Valid() const =0
bool IsPruned() const
Definition: main.h:1086
Stats stats
Definition: db_bench.cc:291
int64 nTotalAmount
Definition: main.h:2140
bool WriteTxIndex(const std::vector< std::pair< uint256, CDiskTxPos > > &list)
Definition: txdb.cpp:172
void Erase(const K &key)
Definition: leveldb.h:45
uint64 nTransactionOutputs
Definition: main.h:2137
bool WriteReindexing(bool fReindex)
Definition: txdb.cpp:101
bool HaveCoins(const uint256 &txid)
Definition: txdb.cpp:39
virtual Slice key() const =0
bool WriteFlag(const std::string &name, bool fValue)
Definition: txdb.cpp:179
uint64 nTransactions
Definition: main.h:2136
int nHeight
Definition: main.h:1639
uint64 nSerializedSize
Definition: main.h:2138
bool WriteCheckpointPubKey(const std::string &strPubKey)
Definition: txdb.cpp:263
map< uint256, CBlockIndex * > mapBlockIndex
Definition: main.cpp:37
uint32_t hash
Definition: cache.cc:34
unsigned int nNonce
Definition: main.h:1668
unsigned int nTx
Definition: main.h:1655
uint256 GetBlockHash() const
Definition: main.h:1744
const char * name
Definition: testharness.cc:18
bool SetCoins(const uint256 &txid, const CCoins &coins)
Definition: txdb.cpp:33
long long int64
Definition: serialize.h:25
bool WriteBestInvalidWork(const CBigNum &bnBestInvalidWork)
Definition: txdb.cpp:84