Stake miner status icon
[novacoin.git] / src / txdb-leveldb.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 license.txt or http://www.opensource.org/licenses/mit-license.php.
5
6 #include <map>
7
8 #include <boost/version.hpp>
9 #include <boost/filesystem.hpp>
10 #include <boost/filesystem/fstream.hpp>
11
12 #include <leveldb/env.h>
13 #include <leveldb/cache.h>
14 #include <leveldb/filter_policy.h>
15 #include <memenv/memenv.h>
16
17 #include "kernel.h"
18 #include "checkpoints.h"
19 #include "txdb.h"
20 #include "util.h"
21 #include "main.h"
22
23 using namespace std;
24 using namespace boost;
25
26 leveldb::DB *txdb; // global pointer for LevelDB object instance
27
28 static leveldb::Options GetOptions() {
29     leveldb::Options options;
30     int nCacheSizeMB = GetArg("-dbcache", 25);
31     options.block_cache = leveldb::NewLRUCache(nCacheSizeMB * 1048576);
32     options.filter_policy = leveldb::NewBloomFilterPolicy(10);
33     return options;
34 }
35
36 void init_blockindex(leveldb::Options& options, bool fRemoveOld = false) {
37     // First time init.
38     filesystem::path directory = GetDataDir() / "txleveldb";
39
40     if (fRemoveOld) {
41         filesystem::remove_all(directory); // remove directory
42         unsigned int nFile = 1;
43
44         while (true)
45         {
46             filesystem::path strBlockFile = GetDataDir() / strprintf("blk%04u.dat", nFile);
47
48             // Break if no such file
49             if( !filesystem::exists( strBlockFile ) )
50                 break;
51
52             filesystem::remove(strBlockFile);
53
54             nFile++;
55         }
56     }
57
58     filesystem::create_directory(directory);
59     printf("Opening LevelDB in %s\n", directory.string().c_str());
60     leveldb::Status status = leveldb::DB::Open(options, directory.string(), &txdb);
61     if (!status.ok()) {
62         throw runtime_error(strprintf("init_blockindex(): error opening database environment %s", status.ToString().c_str()));
63     }
64 }
65
66 // CDB subclasses are created and destroyed VERY OFTEN. That's why
67 // we shouldn't treat this as a free operations.
68 CTxDB::CTxDB(const char* pszMode)
69 {
70     assert(pszMode);
71     activeBatch = NULL;
72     fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
73
74     if (txdb) {
75         pdb = txdb;
76         return;
77     }
78
79     bool fCreate = strchr(pszMode, 'c');
80
81     options = GetOptions();
82     options.create_if_missing = fCreate;
83     options.filter_policy = leveldb::NewBloomFilterPolicy(10);
84
85     init_blockindex(options); // Init directory
86     pdb = txdb;
87
88     if (Exists(string("version")))
89     {
90         ReadVersion(nVersion);
91         printf("Transaction index version is %d\n", nVersion);
92
93         if (nVersion < DATABASE_VERSION)
94         {
95             printf("Required index version is %d, removing old database\n", DATABASE_VERSION);
96
97             // Leveldb instance destruction
98             delete txdb;
99             txdb = pdb = NULL;
100             delete activeBatch;
101             activeBatch = NULL;
102
103             init_blockindex(options, true); // Remove directory and create new database
104             pdb = txdb;
105
106             bool fTmp = fReadOnly;
107             fReadOnly = false;
108             WriteVersion(DATABASE_VERSION); // Save transaction index version
109             fReadOnly = fTmp;
110         }
111     }
112     else if (fCreate)
113     {
114         bool fTmp = fReadOnly;
115         fReadOnly = false;
116         WriteVersion(DATABASE_VERSION);
117         fReadOnly = fTmp;
118     }
119
120     printf("Opened LevelDB successfully\n");
121 }
122
123 void CTxDB::Close()
124 {
125     delete txdb;
126     txdb = pdb = NULL;
127     delete options.filter_policy;
128     options.filter_policy = NULL;
129     delete options.block_cache;
130     options.block_cache = NULL;
131     delete activeBatch;
132     activeBatch = NULL;
133 }
134
135 bool CTxDB::TxnBegin()
136 {
137     assert(!activeBatch);
138     activeBatch = new leveldb::WriteBatch();
139     return true;
140 }
141
142 bool CTxDB::TxnCommit()
143 {
144     assert(activeBatch);
145     leveldb::Status status = pdb->Write(leveldb::WriteOptions(), activeBatch);
146     delete activeBatch;
147     activeBatch = NULL;
148     if (!status.ok()) {
149         printf("LevelDB batch commit failure: %s\n", status.ToString().c_str());
150         return false;
151     }
152     return true;
153 }
154
155 class CBatchScanner : public leveldb::WriteBatch::Handler {
156 public:
157     std::string needle;
158     bool *deleted;
159     std::string *foundValue;
160     bool foundEntry;
161
162     CBatchScanner() : foundEntry(false) {}
163
164     virtual void Put(const leveldb::Slice& key, const leveldb::Slice& value) {
165         if (key.ToString() == needle) {
166             foundEntry = true;
167             *deleted = false;
168             *foundValue = value.ToString();
169         }
170     }
171
172     virtual void Delete(const leveldb::Slice& key) {
173         if (key.ToString() == needle) {
174             foundEntry = true;
175             *deleted = true;
176         }
177     }
178 };
179
180 // When performing a read, if we have an active batch we need to check it first
181 // before reading from the database, as the rest of the code assumes that once
182 // a database transaction begins reads are consistent with it. It would be good
183 // to change that assumption in future and avoid the performance hit, though in
184 // practice it does not appear to be large.
185 bool CTxDB::ScanBatch(const CDataStream &key, string *value, bool *deleted) const {
186     assert(activeBatch);
187     *deleted = false;
188     CBatchScanner scanner;
189     scanner.needle = key.str();
190     scanner.deleted = deleted;
191     scanner.foundValue = value;
192     leveldb::Status status = activeBatch->Iterate(&scanner);
193     if (!status.ok()) {
194         throw runtime_error(status.ToString());
195     }
196     return scanner.foundEntry;
197 }
198
199 bool CTxDB::ReadTxIndex(uint256 hash, CTxIndex& txindex)
200 {
201     assert(!fClient);
202     txindex.SetNull();
203     return Read(make_pair(string("tx"), hash), txindex);
204 }
205
206 bool CTxDB::UpdateTxIndex(uint256 hash, const CTxIndex& txindex)
207 {
208     assert(!fClient);
209     return Write(make_pair(string("tx"), hash), txindex);
210 }
211
212 bool CTxDB::AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight)
213 {
214     assert(!fClient);
215
216     // Add to tx index
217     uint256 hash = tx.GetHash();
218     CTxIndex txindex(pos, tx.vout.size());
219     return Write(make_pair(string("tx"), hash), txindex);
220 }
221
222 bool CTxDB::EraseTxIndex(const CTransaction& tx)
223 {
224     assert(!fClient);
225     uint256 hash = tx.GetHash();
226
227     return Erase(make_pair(string("tx"), hash));
228 }
229
230 bool CTxDB::ContainsTx(uint256 hash)
231 {
232     assert(!fClient);
233     return Exists(make_pair(string("tx"), hash));
234 }
235
236 bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex)
237 {
238     assert(!fClient);
239     tx.SetNull();
240     if (!ReadTxIndex(hash, txindex))
241         return false;
242     return (tx.ReadFromDisk(txindex.pos));
243 }
244
245 bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx)
246 {
247     CTxIndex txindex;
248     return ReadDiskTx(hash, tx, txindex);
249 }
250
251 bool CTxDB::ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex)
252 {
253     return ReadDiskTx(outpoint.hash, tx, txindex);
254 }
255
256 bool CTxDB::ReadDiskTx(COutPoint outpoint, CTransaction& tx)
257 {
258     CTxIndex txindex;
259     return ReadDiskTx(outpoint.hash, tx, txindex);
260 }
261
262 bool CTxDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
263 {
264     return Write(make_pair(string("blockindex"), blockindex.GetBlockHash()), blockindex);
265 }
266
267 bool CTxDB::ReadHashBestChain(uint256& hashBestChain)
268 {
269     return Read(string("hashBestChain"), hashBestChain);
270 }
271
272 bool CTxDB::WriteHashBestChain(uint256 hashBestChain)
273 {
274     return Write(string("hashBestChain"), hashBestChain);
275 }
276
277 bool CTxDB::ReadBestInvalidTrust(CBigNum& bnBestInvalidTrust)
278 {
279     return Read(string("bnBestInvalidTrust"), bnBestInvalidTrust);
280 }
281
282 bool CTxDB::WriteBestInvalidTrust(CBigNum bnBestInvalidTrust)
283 {
284     return Write(string("bnBestInvalidTrust"), bnBestInvalidTrust);
285 }
286
287 bool CTxDB::ReadSyncCheckpoint(uint256& hashCheckpoint)
288 {
289     return Read(string("hashSyncCheckpoint"), hashCheckpoint);
290 }
291
292 bool CTxDB::WriteSyncCheckpoint(uint256 hashCheckpoint)
293 {
294     return Write(string("hashSyncCheckpoint"), hashCheckpoint);
295 }
296
297 bool CTxDB::ReadCheckpointPubKey(string& strPubKey)
298 {
299     return Read(string("strCheckpointPubKey"), strPubKey);
300 }
301
302 bool CTxDB::WriteCheckpointPubKey(const string& strPubKey)
303 {
304     return Write(string("strCheckpointPubKey"), strPubKey);
305 }
306
307 static CBlockIndex *InsertBlockIndex(uint256 hash)
308 {
309     if (hash == 0)
310         return NULL;
311
312     // Return existing
313     map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
314     if (mi != mapBlockIndex.end())
315         return (*mi).second;
316
317     // Create new
318     CBlockIndex* pindexNew = new CBlockIndex();
319     if (!pindexNew)
320         throw runtime_error("LoadBlockIndex() : new CBlockIndex failed");
321     mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
322     pindexNew->phashBlock = &((*mi).first);
323
324     return pindexNew;
325 }
326
327 bool CTxDB::LoadBlockIndex()
328 {
329     if (mapBlockIndex.size() > 0) {
330         // Already loaded once in this session. It can happen during migration
331         // from BDB.
332         return true;
333     }
334     // The block index is an in-memory structure that maps hashes to on-disk
335     // locations where the contents of the block can be found. Here, we scan it
336     // out of the DB and into mapBlockIndex.
337     leveldb::Iterator *iterator = pdb->NewIterator(leveldb::ReadOptions());
338     // Seek to start key.
339     CDataStream ssStartKey(SER_DISK, CLIENT_VERSION);
340     ssStartKey << make_pair(string("blockindex"), uint256(0));
341     iterator->Seek(ssStartKey.str());
342     // Now read each entry.
343     while (iterator->Valid())
344     {
345         // Unpack keys and values.
346         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
347         ssKey.write(iterator->key().data(), iterator->key().size());
348         CDataStream ssValue(SER_DISK, CLIENT_VERSION);
349         ssValue.write(iterator->value().data(), iterator->value().size());
350         string strType;
351         ssKey >> strType;
352         // Did we reach the end of the data to read?
353         if (fRequestShutdown || strType != "blockindex")
354             break;
355         CDiskBlockIndex diskindex;
356         ssValue >> diskindex;
357
358         uint256 blockHash = diskindex.GetBlockHash();
359
360         // Construct block index object
361         CBlockIndex* pindexNew    = InsertBlockIndex(blockHash);
362         pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
363         pindexNew->pnext          = InsertBlockIndex(diskindex.hashNext);
364         pindexNew->nFile          = diskindex.nFile;
365         pindexNew->nBlockPos      = diskindex.nBlockPos;
366         pindexNew->nHeight        = diskindex.nHeight;
367         pindexNew->nMint          = diskindex.nMint;
368         pindexNew->nMoneySupply   = diskindex.nMoneySupply;
369         pindexNew->nFlags         = diskindex.nFlags;
370         pindexNew->nStakeModifier = diskindex.nStakeModifier;
371         pindexNew->prevoutStake   = diskindex.prevoutStake;
372         pindexNew->nStakeTime     = diskindex.nStakeTime;
373         pindexNew->hashProofOfStake = diskindex.hashProofOfStake;
374         pindexNew->nVersion       = diskindex.nVersion;
375         pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
376         pindexNew->nTime          = diskindex.nTime;
377         pindexNew->nBits          = diskindex.nBits;
378         pindexNew->nNonce         = diskindex.nNonce;
379
380         // Watch for genesis block
381         if (pindexGenesisBlock == NULL && blockHash == (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet))
382             pindexGenesisBlock = pindexNew;
383
384         if (!pindexNew->CheckIndex()) {
385             delete iterator;
386             return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight);
387         }
388
389         // NovaCoin: build setStakeSeen
390         if (pindexNew->IsProofOfStake())
391             setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime));
392
393         iterator->Next();
394     }
395     delete iterator;
396
397     if (fRequestShutdown)
398         return true;
399
400     // Calculate nChainTrust
401     vector<pair<int, CBlockIndex*> > vSortedByHeight;
402     vSortedByHeight.reserve(mapBlockIndex.size());
403     BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex)
404     {
405         CBlockIndex* pindex = item.second;
406         vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex));
407     }
408     sort(vSortedByHeight.begin(), vSortedByHeight.end());
409     BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight)
410     {
411         CBlockIndex* pindex = item.second;
412         pindex->nChainTrust = (pindex->pprev ? pindex->pprev->nChainTrust : 0) + pindex->GetBlockTrust();
413         // NovaCoin: calculate stake modifier checksum
414         pindex->nStakeModifierChecksum = GetStakeModifierChecksum(pindex);
415         if (!CheckStakeModifierCheckpoints(pindex->nHeight, pindex->nStakeModifierChecksum))
416             return error("CTxDB::LoadBlockIndex() : Failed stake modifier checkpoint height=%d, modifier=0x%016"PRI64x, pindex->nHeight, pindex->nStakeModifier);
417     }
418
419     // Load hashBestChain pointer to end of best chain
420     if (!ReadHashBestChain(hashBestChain))
421     {
422         if (pindexGenesisBlock == NULL)
423             return true;
424         return error("CTxDB::LoadBlockIndex() : hashBestChain not loaded");
425     }
426     if (!mapBlockIndex.count(hashBestChain))
427         return error("CTxDB::LoadBlockIndex() : hashBestChain not found in the block index");
428     pindexBest = mapBlockIndex[hashBestChain];
429     nBestHeight = pindexBest->nHeight;
430     nBestChainTrust = pindexBest->nChainTrust;
431
432     printf("LoadBlockIndex(): hashBestChain=%s  height=%d  trust=%s  date=%s\n",
433       hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, CBigNum(nBestChainTrust).ToString().c_str(),
434       DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());
435
436     // NovaCoin: load hashSyncCheckpoint
437     if (!ReadSyncCheckpoint(Checkpoints::hashSyncCheckpoint))
438         return error("CTxDB::LoadBlockIndex() : hashSyncCheckpoint not loaded");
439     printf("LoadBlockIndex(): synchronized checkpoint %s\n", Checkpoints::hashSyncCheckpoint.ToString().c_str());
440
441     // Load bnBestInvalidTrust, OK if it doesn't exist
442     CBigNum bnBestInvalidTrust;
443     ReadBestInvalidTrust(bnBestInvalidTrust);
444     nBestInvalidTrust = bnBestInvalidTrust.getuint256();
445
446     // Verify blocks in the best chain
447     int nCheckLevel = GetArg("-checklevel", 1);
448     int nCheckDepth = GetArg( "-checkblocks", 2500);
449     if (nCheckDepth == 0)
450         nCheckDepth = 1000000000; // suffices until the year 19000
451     if (nCheckDepth > nBestHeight)
452         nCheckDepth = nBestHeight;
453     printf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
454     CBlockIndex* pindexFork = NULL;
455     map<pair<unsigned int, unsigned int>, CBlockIndex*> mapBlockPos;
456     for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
457     {
458         if (fRequestShutdown || pindex->nHeight < nBestHeight-nCheckDepth)
459             break;
460         CBlock block;
461         if (!block.ReadFromDisk(pindex))
462             return error("LoadBlockIndex() : block.ReadFromDisk failed");
463         // check level 1: verify block validity
464         // check level 7: verify block signature too
465         if (nCheckLevel>0 && !block.CheckBlock(true, true, (nCheckLevel>6)))
466         {
467             printf("LoadBlockIndex() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
468             pindexFork = pindex->pprev;
469         }
470         // check level 2: verify transaction index validity
471         if (nCheckLevel>1)
472         {
473             pair<unsigned int, unsigned int> pos = make_pair(pindex->nFile, pindex->nBlockPos);
474             mapBlockPos[pos] = pindex;
475             BOOST_FOREACH(const CTransaction &tx, block.vtx)
476             {
477                 uint256 hashTx = tx.GetHash();
478                 CTxIndex txindex;
479                 if (ReadTxIndex(hashTx, txindex))
480                 {
481                     // check level 3: checker transaction hashes
482                     if (nCheckLevel>2 || pindex->nFile != txindex.pos.nFile || pindex->nBlockPos != txindex.pos.nBlockPos)
483                     {
484                         // either an error or a duplicate transaction
485                         CTransaction txFound;
486                         if (!txFound.ReadFromDisk(txindex.pos))
487                         {
488                             printf("LoadBlockIndex() : *** cannot read mislocated transaction %s\n", hashTx.ToString().c_str());
489                             pindexFork = pindex->pprev;
490                         }
491                         else
492                             if (txFound.GetHash() != hashTx) // not a duplicate tx
493                             {
494                                 printf("LoadBlockIndex(): *** invalid tx position for %s\n", hashTx.ToString().c_str());
495                                 pindexFork = pindex->pprev;
496                             }
497                     }
498                     // check level 4: check whether spent txouts were spent within the main chain
499                     unsigned int nOutput = 0;
500                     if (nCheckLevel>3)
501                     {
502                         BOOST_FOREACH(const CDiskTxPos &txpos, txindex.vSpent)
503                         {
504                             if (!txpos.IsNull())
505                             {
506                                 pair<unsigned int, unsigned int> posFind = make_pair(txpos.nFile, txpos.nBlockPos);
507                                 if (!mapBlockPos.count(posFind))
508                                 {
509                                     printf("LoadBlockIndex(): *** found bad spend at %d, hashBlock=%s, hashTx=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str(), hashTx.ToString().c_str());
510                                     pindexFork = pindex->pprev;
511                                 }
512                                 // check level 6: check whether spent txouts were spent by a valid transaction that consume them
513                                 if (nCheckLevel>5)
514                                 {
515                                     CTransaction txSpend;
516                                     if (!txSpend.ReadFromDisk(txpos))
517                                     {
518                                         printf("LoadBlockIndex(): *** cannot read spending transaction of %s:%i from disk\n", hashTx.ToString().c_str(), nOutput);
519                                         pindexFork = pindex->pprev;
520                                     }
521                                     else if (!txSpend.CheckTransaction())
522                                     {
523                                         printf("LoadBlockIndex(): *** spending transaction of %s:%i is invalid\n", hashTx.ToString().c_str(), nOutput);
524                                         pindexFork = pindex->pprev;
525                                     }
526                                     else
527                                     {
528                                         bool fFound = false;
529                                         BOOST_FOREACH(const CTxIn &txin, txSpend.vin)
530                                             if (txin.prevout.hash == hashTx && txin.prevout.n == nOutput)
531                                                 fFound = true;
532                                         if (!fFound)
533                                         {
534                                             printf("LoadBlockIndex(): *** spending transaction of %s:%i does not spend it\n", hashTx.ToString().c_str(), nOutput);
535                                             pindexFork = pindex->pprev;
536                                         }
537                                     }
538                                 }
539                             }
540                             nOutput++;
541                         }
542                     }
543                 }
544                 // check level 5: check whether all prevouts are marked spent
545                 if (nCheckLevel>4)
546                 {
547                      BOOST_FOREACH(const CTxIn &txin, tx.vin)
548                      {
549                           CTxIndex txindex;
550                           if (ReadTxIndex(txin.prevout.hash, txindex))
551                               if (txindex.vSpent.size()-1 < txin.prevout.n || txindex.vSpent[txin.prevout.n].IsNull())
552                               {
553                                   printf("LoadBlockIndex(): *** found unspent prevout %s:%i in %s\n", txin.prevout.hash.ToString().c_str(), txin.prevout.n, hashTx.ToString().c_str());
554                                   pindexFork = pindex->pprev;
555                               }
556                      }
557                 }
558             }
559         }
560     }
561     if (pindexFork && !fRequestShutdown)
562     {
563         // Reorg back to the fork
564         printf("LoadBlockIndex() : *** moving best chain pointer back to block %d\n", pindexFork->nHeight);
565         CBlock block;
566         if (!block.ReadFromDisk(pindexFork))
567             return error("LoadBlockIndex() : block.ReadFromDisk failed");
568         CTxDB txdb;
569         block.SetBestChain(txdb, pindexFork);
570     }
571
572     return true;
573 }