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