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