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