]> Git Repo - VerusCoin.git/blob - src/txdb.cpp
Merge pull request #2299 from gavinandresen/localsocketuri
[VerusCoin.git] / src / txdb.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 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 #include "main.h"
8
9 using namespace std;
10
11 void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) {
12     if (coins.IsPruned())
13         batch.Erase(make_pair('c', hash));
14     else
15         batch.Write(make_pair('c', hash), coins);
16 }
17
18 void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) {
19     batch.Write('B', hash);
20 }
21
22 CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe) {
23 }
24
25 bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) { 
26     return db.Read(make_pair('c', txid), coins); 
27 }
28
29 bool CCoinsViewDB::SetCoins(const uint256 &txid, const CCoins &coins) {
30     CLevelDBBatch batch;
31     BatchWriteCoins(batch, txid, coins);
32     return db.WriteBatch(batch);
33 }
34
35 bool CCoinsViewDB::HaveCoins(const uint256 &txid) {
36     return db.Exists(make_pair('c', txid)); 
37 }
38
39 CBlockIndex *CCoinsViewDB::GetBestBlock() {
40     uint256 hashBestChain;
41     if (!db.Read('B', hashBestChain))
42         return NULL;
43     std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(hashBestChain);
44     if (it == mapBlockIndex.end())
45         return NULL;
46     return it->second;
47 }
48
49 bool CCoinsViewDB::SetBestBlock(CBlockIndex *pindex) {
50     CLevelDBBatch batch;
51     BatchWriteHashBestChain(batch, pindex->GetBlockHash()); 
52     return db.WriteBatch(batch);
53 }
54
55 bool CCoinsViewDB::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) {
56     printf("Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size());
57
58     CLevelDBBatch batch;
59     for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++)
60         BatchWriteCoins(batch, it->first, it->second);
61     if (pindex)
62         BatchWriteHashBestChain(batch, pindex->GetBlockHash());
63
64     return db.WriteBatch(batch);
65 }
66
67 CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDB(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
68 }
69
70 bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
71 {
72     return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
73 }
74
75 bool CBlockTreeDB::ReadBestInvalidWork(CBigNum& bnBestInvalidWork)
76 {
77     return Read('I', bnBestInvalidWork);
78 }
79
80 bool CBlockTreeDB::WriteBestInvalidWork(const CBigNum& bnBestInvalidWork)
81 {
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     while (pcursor->Valid()) {
118         try {
119             leveldb::Slice slKey = pcursor->key();
120             CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
121             char chType;
122             ssKey >> chType;
123             if (chType == 'c' && !fRequestShutdown) {
124                 leveldb::Slice slValue = pcursor->value();
125                 CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
126                 CCoins coins;
127                 ssValue >> coins;
128                 uint256 txhash;
129                 ssKey >> txhash;
130
131                 stats.nTransactions++;
132                 BOOST_FOREACH(const CTxOut &out, coins.vout) {
133                     if (!out.IsNull())
134                         stats.nTransactionOutputs++;
135                 }
136                 stats.nSerializedSize += 32 + slValue.size();
137             }
138             pcursor->Next();
139         } catch (std::exception &e) {
140             return error("%s() : deserialize error", __PRETTY_FUNCTION__);
141         }
142     }
143     delete pcursor;
144     stats.nHeight = GetBestBlock()->nHeight;
145     return true;
146 }
147
148 bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
149     return Read(make_pair('t', txid), pos);
150 }
151
152 bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
153     CLevelDBBatch batch;
154     for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
155         batch.Write(make_pair('t', it->first), it->second);
156     return WriteBatch(batch);
157 }
158
159 bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
160     return Write(std::make_pair('F', name), fValue ? '1' : '0');
161 }
162
163 bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
164     char ch;
165     if (!Read(std::make_pair('F', name), ch))
166         return false;
167     fValue = ch == '1';
168     return true;
169 }
170
171 bool CBlockTreeDB::LoadBlockIndexGuts()
172 {
173     leveldb::Iterator *pcursor = NewIterator();
174
175     CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
176     ssKeySet << make_pair('b', uint256(0));
177     pcursor->Seek(ssKeySet.str());
178
179     // Load mapBlockIndex
180     while (pcursor->Valid()) {
181         try {
182             leveldb::Slice slKey = pcursor->key();
183             CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
184             char chType;
185             ssKey >> chType;
186             if (chType == 'b' && !fRequestShutdown) {
187                 leveldb::Slice slValue = pcursor->value();
188                 CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
189                 CDiskBlockIndex diskindex;
190                 ssValue >> diskindex;
191
192                 // Construct block index object
193                 CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
194                 pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
195                 pindexNew->nHeight        = diskindex.nHeight;
196                 pindexNew->nFile          = diskindex.nFile;
197                 pindexNew->nDataPos       = diskindex.nDataPos;
198                 pindexNew->nUndoPos       = diskindex.nUndoPos;
199                 pindexNew->nVersion       = diskindex.nVersion;
200                 pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
201                 pindexNew->nTime          = diskindex.nTime;
202                 pindexNew->nBits          = diskindex.nBits;
203                 pindexNew->nNonce         = diskindex.nNonce;
204                 pindexNew->nStatus        = diskindex.nStatus;
205                 pindexNew->nTx            = diskindex.nTx;
206
207                 // Watch for genesis block
208                 if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
209                     pindexGenesisBlock = pindexNew;
210
211                 if (!pindexNew->CheckIndex())
212                     return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString().c_str());
213
214                 pcursor->Next();
215             } else {
216                 break; // if shutdown requested or finished loading block index
217             }
218         } catch (std::exception &e) {
219             return error("%s() : deserialize error", __PRETTY_FUNCTION__);
220         }
221     }
222     delete pcursor;
223
224     return true;
225 }
This page took 0.033954 seconds and 4 git commands to generate.