]> Git Repo - VerusCoin.git/blob - src/txdb.cpp
Cleanup code using forward declarations.
[VerusCoin.git] / src / txdb.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2013 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
43 CBlockIndex *CCoinsViewDB::GetBestBlock() {
44     uint256 hashBestChain;
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
53 bool CCoinsViewDB::SetBestBlock(CBlockIndex *pindex) {
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     LogPrint("coindb", "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) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
72 }
73
74 bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
75 {
76     return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
77 }
78
79 bool CBlockTreeDB::WriteBestInvalidWork(const CBigNum& bnBestInvalidWork)
80 {
81     // Obsolete; only written for backward compatibility.
82     return Write('I', bnBestInvalidWork);
83 }
84
85 bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) {
86     return Write(make_pair('f', nFile), info);
87 }
88
89 bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
90     return Read(make_pair('f', nFile), info);
91 }
92
93 bool CBlockTreeDB::WriteLastBlockFile(int nFile) {
94     return Write('l', nFile);
95 }
96
97 bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
98     if (fReindexing)
99         return Write('R', '1');
100     else
101         return Erase('R');
102 }
103
104 bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
105     fReindexing = Exists('R');
106     return true;
107 }
108
109 bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
110     return Read('l', nFile);
111 }
112
113 bool CCoinsViewDB::GetStats(CCoinsStats &stats) {
114     leveldb::Iterator *pcursor = db.NewIterator();
115     pcursor->SeekToFirst();
116
117     CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
118     stats.hashBlock = GetBestBlock()->GetBlockHash();
119     ss << stats.hashBlock;
120     int64_t nTotalAmount = 0;
121     while (pcursor->Valid()) {
122         boost::this_thread::interruption_point();
123         try {
124             leveldb::Slice slKey = pcursor->key();
125             CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
126             char chType;
127             ssKey >> chType;
128             if (chType == 'c') {
129                 leveldb::Slice slValue = pcursor->value();
130                 CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
131                 CCoins coins;
132                 ssValue >> coins;
133                 uint256 txhash;
134                 ssKey >> txhash;
135                 ss << txhash;
136                 ss << VARINT(coins.nVersion);
137                 ss << (coins.fCoinBase ? 'c' : 'n'); 
138                 ss << VARINT(coins.nHeight);
139                 stats.nTransactions++;
140                 for (unsigned int i=0; i<coins.vout.size(); i++) {
141                     const CTxOut &out = coins.vout[i];
142                     if (!out.IsNull()) {
143                         stats.nTransactionOutputs++;
144                         ss << VARINT(i+1);
145                         ss << out;
146                         nTotalAmount += out.nValue;
147                     }
148                 }
149                 stats.nSerializedSize += 32 + slValue.size();
150                 ss << VARINT(0);
151             }
152             pcursor->Next();
153         } catch (std::exception &e) {
154             return error("%s() : deserialize error", __PRETTY_FUNCTION__);
155         }
156     }
157     delete pcursor;
158     stats.nHeight = GetBestBlock()->nHeight;
159     stats.hashSerialized = ss.GetHash();
160     stats.nTotalAmount = nTotalAmount;
161     return true;
162 }
163
164 bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
165     return Read(make_pair('t', txid), pos);
166 }
167
168 bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
169     CLevelDBBatch batch;
170     for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
171         batch.Write(make_pair('t', it->first), it->second);
172     return WriteBatch(batch);
173 }
174
175 bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
176     return Write(std::make_pair('F', name), fValue ? '1' : '0');
177 }
178
179 bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
180     char ch;
181     if (!Read(std::make_pair('F', name), ch))
182         return false;
183     fValue = ch == '1';
184     return true;
185 }
186
187 bool CBlockTreeDB::LoadBlockIndexGuts()
188 {
189     leveldb::Iterator *pcursor = NewIterator();
190
191     CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
192     ssKeySet << make_pair('b', uint256(0));
193     pcursor->Seek(ssKeySet.str());
194
195     // Load mapBlockIndex
196     while (pcursor->Valid()) {
197         boost::this_thread::interruption_point();
198         try {
199             leveldb::Slice slKey = pcursor->key();
200             CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
201             char chType;
202             ssKey >> chType;
203             if (chType == 'b') {
204                 leveldb::Slice slValue = pcursor->value();
205                 CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
206                 CDiskBlockIndex diskindex;
207                 ssValue >> diskindex;
208
209                 // Construct block index object
210                 CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
211                 pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
212                 pindexNew->nHeight        = diskindex.nHeight;
213                 pindexNew->nFile          = diskindex.nFile;
214                 pindexNew->nDataPos       = diskindex.nDataPos;
215                 pindexNew->nUndoPos       = diskindex.nUndoPos;
216                 pindexNew->nVersion       = diskindex.nVersion;
217                 pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
218                 pindexNew->nTime          = diskindex.nTime;
219                 pindexNew->nBits          = diskindex.nBits;
220                 pindexNew->nNonce         = diskindex.nNonce;
221                 pindexNew->nStatus        = diskindex.nStatus;
222                 pindexNew->nTx            = diskindex.nTx;
223
224                 if (!pindexNew->CheckIndex())
225                     return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString().c_str());
226
227                 pcursor->Next();
228             } else {
229                 break; // if shutdown requested or finished loading block index
230             }
231         } catch (std::exception &e) {
232             return error("%s() : deserialize error", __PRETTY_FUNCTION__);
233         }
234     }
235     delete pcursor;
236
237     return true;
238 }
This page took 0.036326 seconds and 4 git commands to generate.