Malleable keys: remove version byte
[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 = GetArgInt("-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 bool CTxDB::ReadModifierUpgradeTime(unsigned int& nUpgradeTime)
308 {
309     return Read(string("nUpgradeTime"), nUpgradeTime);
310 }
311
312 bool CTxDB::WriteModifierUpgradeTime(const unsigned int& nUpgradeTime)
313 {
314     return Write(string("nUpgradeTime"), nUpgradeTime);
315 }
316
317 static CBlockIndex *InsertBlockIndex(uint256 hash)
318 {
319     if (hash == 0)
320         return NULL;
321
322     // Return existing
323     map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
324     if (mi != mapBlockIndex.end())
325         return (*mi).second;
326
327     // Create new
328     CBlockIndex* pindexNew = new(nothrow) CBlockIndex();
329     if (!pindexNew)
330         throw runtime_error("LoadBlockIndex() : new CBlockIndex failed");
331     mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
332     pindexNew->phashBlock = &((*mi).first);
333
334     return pindexNew;
335 }
336
337 bool CTxDB::LoadBlockIndex()
338 {
339     if (mapBlockIndex.size() > 0) {
340         // Already loaded once in this session. It can happen during migration
341         // from BDB.
342         return true;
343     }
344     // The block index is an in-memory structure that maps hashes to on-disk
345     // locations where the contents of the block can be found. Here, we scan it
346     // out of the DB and into mapBlockIndex.
347     leveldb::Iterator *iterator = pdb->NewIterator(leveldb::ReadOptions());
348     // Seek to start key.
349     CDataStream ssStartKey(SER_DISK, CLIENT_VERSION);
350     ssStartKey << make_pair(string("blockindex"), uint256(0));
351     iterator->Seek(ssStartKey.str());
352     // Now read each entry.
353     while (iterator->Valid())
354     {
355         // Unpack keys and values.
356         CDataStream ssKey(SER_DISK, CLIENT_VERSION);
357         ssKey.write(iterator->key().data(), iterator->key().size());
358         CDataStream ssValue(SER_DISK, CLIENT_VERSION);
359         ssValue.write(iterator->value().data(), iterator->value().size());
360         string strType;
361         ssKey >> strType;
362         // Did we reach the end of the data to read?
363         if (fRequestShutdown || strType != "blockindex")
364             break;
365         CDiskBlockIndex diskindex;
366         ssValue >> diskindex;
367
368         uint256 blockHash = diskindex.GetBlockHash();
369
370         // Construct block index object
371         CBlockIndex* pindexNew    = InsertBlockIndex(blockHash);
372         pindexNew->pprev          = InsertBlockIndex(diskindex.hashPrev);
373         pindexNew->pnext          = InsertBlockIndex(diskindex.hashNext);
374         pindexNew->nFile          = diskindex.nFile;
375         pindexNew->nBlockPos      = diskindex.nBlockPos;
376         pindexNew->nHeight        = diskindex.nHeight;
377         pindexNew->nMint          = diskindex.nMint;
378         pindexNew->nMoneySupply   = diskindex.nMoneySupply;
379         pindexNew->nFlags         = diskindex.nFlags;
380         pindexNew->nStakeModifier = diskindex.nStakeModifier;
381         pindexNew->prevoutStake   = diskindex.prevoutStake;
382         pindexNew->nStakeTime     = diskindex.nStakeTime;
383         pindexNew->hashProofOfStake = diskindex.hashProofOfStake;
384         pindexNew->nVersion       = diskindex.nVersion;
385         pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
386         pindexNew->nTime          = diskindex.nTime;
387         pindexNew->nBits          = diskindex.nBits;
388         pindexNew->nNonce         = diskindex.nNonce;
389
390         // Watch for genesis block
391         if (pindexGenesisBlock == NULL && blockHash == (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet))
392             pindexGenesisBlock = pindexNew;
393
394         if (!pindexNew->CheckIndex()) {
395             delete iterator;
396             return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight);
397         }
398
399         // NovaCoin: build setStakeSeen
400         if (pindexNew->IsProofOfStake())
401             setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime));
402
403         iterator->Next();
404     }
405     delete iterator;
406
407     if (fRequestShutdown)
408         return true;
409
410     // Calculate nChainTrust
411     vector<pair<int, CBlockIndex*> > vSortedByHeight;
412     vSortedByHeight.reserve(mapBlockIndex.size());
413     BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex)
414     {
415         CBlockIndex* pindex = item.second;
416         vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex));
417     }
418     sort(vSortedByHeight.begin(), vSortedByHeight.end());
419     BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight)
420     {
421         CBlockIndex* pindex = item.second;
422         pindex->nChainTrust = (pindex->pprev ? pindex->pprev->nChainTrust : 0) + pindex->GetBlockTrust();
423         // NovaCoin: calculate stake modifier checksum
424         pindex->nStakeModifierChecksum = GetStakeModifierChecksum(pindex);
425         if (!CheckStakeModifierCheckpoints(pindex->nHeight, pindex->nStakeModifierChecksum))
426             return error("CTxDB::LoadBlockIndex() : Failed stake modifier checkpoint height=%d, modifier=0x%016" PRIx64, pindex->nHeight, pindex->nStakeModifier);
427     }
428
429     // Load hashBestChain pointer to end of best chain
430     if (!ReadHashBestChain(hashBestChain))
431     {
432         if (pindexGenesisBlock == NULL)
433             return true;
434         return error("CTxDB::LoadBlockIndex() : hashBestChain not loaded");
435     }
436     if (!mapBlockIndex.count(hashBestChain))
437         return error("CTxDB::LoadBlockIndex() : hashBestChain not found in the block index");
438     pindexBest = mapBlockIndex[hashBestChain];
439     nBestHeight = pindexBest->nHeight;
440     nBestChainTrust = pindexBest->nChainTrust;
441
442     printf("LoadBlockIndex(): hashBestChain=%s  height=%d  trust=%s  date=%s\n",
443       hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, CBigNum(nBestChainTrust).ToString().c_str(),
444       DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());
445
446     // NovaCoin: load hashSyncCheckpoint
447     if (!ReadSyncCheckpoint(Checkpoints::hashSyncCheckpoint))
448         return error("CTxDB::LoadBlockIndex() : hashSyncCheckpoint not loaded");
449     printf("LoadBlockIndex(): synchronized checkpoint %s\n", Checkpoints::hashSyncCheckpoint.ToString().c_str());
450
451     // Load bnBestInvalidTrust, OK if it doesn't exist
452     CBigNum bnBestInvalidTrust;
453     ReadBestInvalidTrust(bnBestInvalidTrust);
454     nBestInvalidTrust = bnBestInvalidTrust.getuint256();
455
456     // Verify blocks in the best chain
457     int nCheckLevel = GetArgInt("-checklevel", 1);
458     int nCheckDepth = GetArgInt( "-checkblocks", 2500);
459     if (nCheckDepth == 0)
460         nCheckDepth = 1000000000; // suffices until the year 19000
461     if (nCheckDepth > nBestHeight)
462         nCheckDepth = nBestHeight;
463     printf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
464     CBlockIndex* pindexFork = NULL;
465     map<pair<unsigned int, unsigned int>, CBlockIndex*> mapBlockPos;
466     for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
467     {
468         if (fRequestShutdown || pindex->nHeight < nBestHeight-nCheckDepth)
469             break;
470         CBlock block;
471         if (!block.ReadFromDisk(pindex))
472             return error("LoadBlockIndex() : block.ReadFromDisk failed");
473         // check level 1: verify block validity
474         // check level 7: verify block signature too
475         if (nCheckLevel>0 && !block.CheckBlock(true, true, (nCheckLevel>6)))
476         {
477             printf("LoadBlockIndex() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
478             pindexFork = pindex->pprev;
479         }
480         // check level 2: verify transaction index validity
481         if (nCheckLevel>1)
482         {
483             pair<unsigned int, unsigned int> pos = make_pair(pindex->nFile, pindex->nBlockPos);
484             mapBlockPos[pos] = pindex;
485             BOOST_FOREACH(const CTransaction &tx, block.vtx)
486             {
487                 uint256 hashTx = tx.GetHash();
488                 CTxIndex txindex;
489                 if (ReadTxIndex(hashTx, txindex))
490                 {
491                     // check level 3: checker transaction hashes
492                     if (nCheckLevel>2 || pindex->nFile != txindex.pos.nFile || pindex->nBlockPos != txindex.pos.nBlockPos)
493                     {
494                         // either an error or a duplicate transaction
495                         CTransaction txFound;
496                         if (!txFound.ReadFromDisk(txindex.pos))
497                         {
498                             printf("LoadBlockIndex() : *** cannot read mislocated transaction %s\n", hashTx.ToString().c_str());
499                             pindexFork = pindex->pprev;
500                         }
501                         else
502                             if (txFound.GetHash() != hashTx) // not a duplicate tx
503                             {
504                                 printf("LoadBlockIndex(): *** invalid tx position for %s\n", hashTx.ToString().c_str());
505                                 pindexFork = pindex->pprev;
506                             }
507                     }
508                     // check level 4: check whether spent txouts were spent within the main chain
509                     unsigned int nOutput = 0;
510                     if (nCheckLevel>3)
511                     {
512                         BOOST_FOREACH(const CDiskTxPos &txpos, txindex.vSpent)
513                         {
514                             if (!txpos.IsNull())
515                             {
516                                 pair<unsigned int, unsigned int> posFind = make_pair(txpos.nFile, txpos.nBlockPos);
517                                 if (!mapBlockPos.count(posFind))
518                                 {
519                                     printf("LoadBlockIndex(): *** found bad spend at %d, hashBlock=%s, hashTx=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str(), hashTx.ToString().c_str());
520                                     pindexFork = pindex->pprev;
521                                 }
522                                 // check level 6: check whether spent txouts were spent by a valid transaction that consume them
523                                 if (nCheckLevel>5)
524                                 {
525                                     CTransaction txSpend;
526                                     if (!txSpend.ReadFromDisk(txpos))
527                                     {
528                                         printf("LoadBlockIndex(): *** cannot read spending transaction of %s:%i from disk\n", hashTx.ToString().c_str(), nOutput);
529                                         pindexFork = pindex->pprev;
530                                     }
531                                     else if (!txSpend.CheckTransaction())
532                                     {
533                                         printf("LoadBlockIndex(): *** spending transaction of %s:%i is invalid\n", hashTx.ToString().c_str(), nOutput);
534                                         pindexFork = pindex->pprev;
535                                     }
536                                     else
537                                     {
538                                         bool fFound = false;
539                                         BOOST_FOREACH(const CTxIn &txin, txSpend.vin)
540                                             if (txin.prevout.hash == hashTx && txin.prevout.n == nOutput)
541                                                 fFound = true;
542                                         if (!fFound)
543                                         {
544                                             printf("LoadBlockIndex(): *** spending transaction of %s:%i does not spend it\n", hashTx.ToString().c_str(), nOutput);
545                                             pindexFork = pindex->pprev;
546                                         }
547                                     }
548                                 }
549                             }
550                             nOutput++;
551                         }
552                     }
553                 }
554                 // check level 5: check whether all prevouts are marked spent
555                 if (nCheckLevel>4)
556                 {
557                      BOOST_FOREACH(const CTxIn &txin, tx.vin)
558                      {
559                           CTxIndex txindex;
560                           if (ReadTxIndex(txin.prevout.hash, txindex))
561                               if (txindex.vSpent.size()-1 < txin.prevout.n || txindex.vSpent[txin.prevout.n].IsNull())
562                               {
563                                   printf("LoadBlockIndex(): *** found unspent prevout %s:%i in %s\n", txin.prevout.hash.ToString().c_str(), txin.prevout.n, hashTx.ToString().c_str());
564                                   pindexFork = pindex->pprev;
565                               }
566                      }
567                 }
568             }
569         }
570     }
571     if (pindexFork && !fRequestShutdown)
572     {
573         // Reorg back to the fork
574         printf("LoadBlockIndex() : *** moving best chain pointer back to block %d\n", pindexFork->nHeight);
575         CBlock block;
576         if (!block.ReadFromDisk(pindexFork))
577             return error("LoadBlockIndex() : block.ReadFromDisk failed");
578         CTxDB txdb;
579         block.SetBestChain(txdb, pindexFork);
580     }
581
582     return true;
583 }