]> Git Repo - VerusCoin.git/blame - src/txdb.cpp
Merge pull request #2336 from petertodd/invalid-opcode-coverage
[VerusCoin.git] / src / txdb.cpp
CommitLineData
2d8a4829
PW
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
4ca60bba 6#include "txdb.h"
2d8a4829
PW
7#include "main.h"
8
9using namespace std;
10
11void 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
18void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) {
19 batch.Write('B', hash);
20}
21
8fdc94cc 22CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe) {
2d8a4829
PW
23}
24
f369d02c 25bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) {
2d8a4829
PW
26 return db.Read(make_pair('c', txid), coins);
27}
28
f369d02c 29bool CCoinsViewDB::SetCoins(const uint256 &txid, const CCoins &coins) {
2d8a4829
PW
30 CLevelDBBatch batch;
31 BatchWriteCoins(batch, txid, coins);
32 return db.WriteBatch(batch);
33}
34
f369d02c 35bool CCoinsViewDB::HaveCoins(const uint256 &txid) {
2d8a4829
PW
36 return db.Exists(make_pair('c', txid));
37}
38
39CBlockIndex *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
49bool CCoinsViewDB::SetBestBlock(CBlockIndex *pindex) {
50 CLevelDBBatch batch;
51 BatchWriteHashBestChain(batch, pindex->GetBlockHash());
52 return db.WriteBatch(batch);
53}
54
55bool 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);
0b297a61
PW
61 if (pindex)
62 BatchWriteHashBestChain(batch, pindex->GetBlockHash());
2d8a4829
PW
63
64 return db.WriteBatch(batch);
65}
66
8fdc94cc 67CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDB(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
e1bfbab8
PW
68}
69
2d8a4829
PW
70bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
71{
72 return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
73}
74
75bool CBlockTreeDB::ReadBestInvalidWork(CBigNum& bnBestInvalidWork)
76{
77 return Read('I', bnBestInvalidWork);
78}
79
80bool CBlockTreeDB::WriteBestInvalidWork(const CBigNum& bnBestInvalidWork)
81{
82 return Write('I', bnBestInvalidWork);
83}
84
85bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) {
86 return Write(make_pair('f', nFile), info);
87}
88
89bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
90 return Read(make_pair('f', nFile), info);
91}
92
93bool CBlockTreeDB::WriteLastBlockFile(int nFile) {
94 return Write('l', nFile);
95}
96
7fea4846
PW
97bool CBlockTreeDB::WriteReindexing(bool fReindexing) {
98 if (fReindexing)
99 return Write('R', '1');
100 else
101 return Erase('R');
102}
103
104bool CBlockTreeDB::ReadReindexing(bool &fReindexing) {
105 fReindexing = Exists('R');
106 return true;
107}
108
2d8a4829
PW
109bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
110 return Read('l', nFile);
111}
112
beeb5761
PW
113bool 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
2d1fa42e
PW
148bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
149 return Read(make_pair('t', txid), pos);
150}
151
152bool 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
159bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) {
160 return Write(std::make_pair('F', name), fValue ? '1' : '0');
161}
162
163bool 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
2d8a4829
PW
171bool 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.051946 seconds and 4 git commands to generate.