// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "db.h"
-#include "net.h"
-#include "checkpoints.h"
#include "util.h"
#include "main.h"
#include "kernel.h"
-#include "ui_interface.h"
+#include "checkpoints.h"
+#include <boost/version.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
if (ret != 0)
printf("EnvShutdown exception: %s (%d)\n", DbEnv::strerror(ret), ret);
if (!fMockDb)
- DbEnv(0).remove(strPath.c_str(), 0);
+ DbEnv(0).remove(GetDataDir().string().c_str(), 0);
}
CDBEnv::CDBEnv() : dbenv(DB_CXX_NO_EXCEPTIONS)
{
- fDbEnvInit = false;
- fMockDb = false;
}
CDBEnv::~CDBEnv()
pathEnv = pathEnv_;
filesystem::path pathDataDir = pathEnv;
- strPath = pathDataDir.string();
filesystem::path pathLogDir = pathDataDir / "database";
filesystem::create_directory(pathLogDir);
filesystem::path pathErrorFile = pathDataDir / "db.log";
dbenv.set_cachesize(nDbCache / 1024, (nDbCache % 1024)*1048576, 1);
dbenv.set_lg_bsize(1048576);
dbenv.set_lg_max(10485760);
-
- // Bugfix: Bump lk_max_locks default to 537000, to safely handle reorgs with up to 5 blocks reversed
- // dbenv.set_lk_max_locks(10000);
- dbenv.set_lk_max_locks(537000);
-
- dbenv.set_lk_max_objects(10000);
+ dbenv.set_lk_max_locks(40000);
+ dbenv.set_lk_max_objects(40000);
dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug
dbenv.set_flags(DB_AUTO_COMMIT, 1);
dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1);
+#ifdef DB_LOG_AUTO_REMOVE
dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1);
- int ret = dbenv.open(strPath.c_str(),
+#endif
+ int ret = dbenv.open(pathDataDir.string().c_str(),
DB_CREATE |
DB_INIT_LOCK |
DB_INIT_LOG |
fDbEnvInit = true;
fMockDb = false;
-
- // Check that the number of locks is sufficient (to prevent chain fork possibility, read http://bitcoin.org/may15 for more info)
- u_int32_t nMaxLocks;
- if (!dbenv.get_lk_max_locks(&nMaxLocks))
- {
- int nBlocks, nDeepReorg;
- std::string strMessage;
-
- nBlocks = nMaxLocks / 48768;
- nDeepReorg = (nBlocks - 1) / 2;
-
- printf("Final lk_max_locks is %lu, sufficient for (worst case) %d block%s in a single transaction (up to a %d-deep reorganization)\n", (unsigned long)nMaxLocks, nBlocks, (nBlocks == 1) ? "" : "s", nDeepReorg);
- if (nDeepReorg < 3)
- {
- if (nBlocks < 1)
- strMessage = strprintf(_("Warning: DB_CONFIG has set_lk_max_locks %lu, which may be too low for a single block. If this limit is reached, NovaCoin may stop working."), (unsigned long)nMaxLocks);
- else
- strMessage = strprintf(_("Warning: DB_CONFIG has set_lk_max_locks %lu, which may be too low for a common blockchain reorganization. If this limit is reached, NovaCoin may stop working."), (unsigned long)nMaxLocks);
-
- strMiscWarning = strMessage;
- printf("*** %s\n", strMessage.c_str());
- }
- }
-
return true;
}
dbenv.set_lk_max_locks(10000);
dbenv.set_lk_max_objects(10000);
dbenv.set_flags(DB_AUTO_COMMIT, 1);
+#ifdef DB_LOG_IN_MEMORY
dbenv.log_set_config(DB_LOG_IN_MEMORY, 1);
+#endif
int ret = dbenv.open(NULL,
DB_CREATE |
DB_INIT_LOCK |
ret = pdb->open(NULL, // Txn pointer
fMockDb ? NULL : pszFile, // Filename
- "main", // Logical db name
+ fMockDb ? pszFile : "main", // Logical db name
DB_BTREE, // Database type
nFlags, // Flags
0);
static bool IsChainFile(std::string strFile)
{
- if (strFile == "blkindex.dat")
+ if (strFile == "coins.dat" || strFile == "blktree.dat")
return true;
return false;
}
-void CDB::Close()
+void CDB::Flush()
{
- if (!pdb)
- return;
if (activeTxn)
- activeTxn->abort();
- activeTxn = NULL;
- pdb = NULL;
+ return;
// Flush database activity from memory pool to disk log
unsigned int nMinutes = 0;
nMinutes = 5;
bitdb.dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0);
+}
+
+void CDB::Close()
+{
+ if (!pdb)
+ return;
+ if (activeTxn)
+ activeTxn->abort();
+ activeTxn = NULL;
+ pdb = NULL;
+
+ Flush();
{
LOCK(bitdb.cs_db);
//
-// CTxDB
+// CBlockTreeDB and CCoinsDB
//
-bool CTxDB::ReadTxIndex(uint256 hash, CTxIndex& txindex)
-{
+bool CCoinsDB::HaveCoins(uint256 hash) {
assert(!fClient);
- txindex.SetNull();
- return Read(make_pair(string("tx"), hash), txindex);
+ return Exists(make_pair('c', hash));
}
-bool CTxDB::UpdateTxIndex(uint256 hash, const CTxIndex& txindex)
-{
+bool CCoinsDB::ReadCoins(uint256 hash, CCoins &coins) {
assert(!fClient);
- return Write(make_pair(string("tx"), hash), txindex);
+ return Read(make_pair('c', hash), coins);
}
-bool CTxDB::AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight)
-{
+bool CCoinsDB::WriteCoins(uint256 hash, const CCoins &coins) {
assert(!fClient);
-
- // Add to tx index
- uint256 hash = tx.GetHash();
- CTxIndex txindex(pos, tx.vout.size());
- return Write(make_pair(string("tx"), hash), txindex);
+ if (coins.IsPruned())
+ return Erase(make_pair('c', hash));
+ else
+ return Write(make_pair('c', hash), coins);
}
-bool CTxDB::EraseTxIndex(const CTransaction& tx)
+bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
{
- assert(!fClient);
- uint256 hash = tx.GetHash();
-
- return Erase(make_pair(string("tx"), hash));
+ return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
}
-bool CTxDB::ContainsTx(uint256 hash)
+bool CCoinsDB::ReadHashBestChain(uint256& hashBestChain)
{
- assert(!fClient);
- return Exists(make_pair(string("tx"), hash));
+ return Read('B', hashBestChain);
}
-bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex)
+bool CCoinsDB::WriteHashBestChain(uint256 hashBestChain)
{
- assert(!fClient);
- tx.SetNull();
- if (!ReadTxIndex(hash, txindex))
- return false;
- return (tx.ReadFromDisk(txindex.pos));
+ return Write('B', hashBestChain);
}
-bool CTxDB::ReadDiskTx(uint256 hash, CTransaction& tx)
+bool CBlockTreeDB::ReadBestInvalidTrust(CBigNum& bnBestInvalidTrust)
{
- CTxIndex txindex;
- return ReadDiskTx(hash, tx, txindex);
+ return Read('I', bnBestInvalidTrust);
}
-bool CTxDB::ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex)
+bool CBlockTreeDB::WriteBestInvalidTrust(CBigNum bnBestInvalidTrust)
{
- return ReadDiskTx(outpoint.hash, tx, txindex);
+ return Write('I', bnBestInvalidTrust);
}
-bool CTxDB::ReadDiskTx(COutPoint outpoint, CTransaction& tx)
-{
- CTxIndex txindex;
- return ReadDiskTx(outpoint.hash, tx, txindex);
+bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) {
+ return Write(make_pair('f', nFile), info);
}
-bool CTxDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
+bool CBlockTreeDB::ReadSyncCheckpoint(uint256& hashCheckpoint)
{
- return Write(make_pair(string("blockindex"), blockindex.GetBlockHash()), blockindex);
+ return Read('H', hashCheckpoint);
}
-bool CTxDB::ReadHashBestChain(uint256& hashBestChain)
+bool CBlockTreeDB::WriteSyncCheckpoint(uint256 hashCheckpoint)
{
- return Read(string("hashBestChain"), hashBestChain);
+ return Write('H', hashCheckpoint);
}
-bool CTxDB::WriteHashBestChain(uint256 hashBestChain)
+bool CBlockTreeDB::ReadCheckpointPubKey(string& strPubKey)
{
- return Write(string("hashBestChain"), hashBestChain);
+ return Read('K', strPubKey);
}
-bool CTxDB::ReadBestInvalidTrust(CBigNum& bnBestInvalidTrust)
+bool CBlockTreeDB::WriteCheckpointPubKey(const string& strPubKey)
{
- return Read(string("bnBestInvalidTrust"), bnBestInvalidTrust);
+ return Write('K', strPubKey);
}
-bool CTxDB::WriteBestInvalidTrust(CBigNum bnBestInvalidTrust)
-{
- return Write(string("bnBestInvalidTrust"), bnBestInvalidTrust);
+
+bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
+ return Read(make_pair('f', nFile), info);
}
-bool CTxDB::ReadSyncCheckpoint(uint256& hashCheckpoint)
-{
- return Read(string("hashSyncCheckpoint"), hashCheckpoint);
+bool CBlockTreeDB::WriteLastBlockFile(int nFile) {
+ return Write('l', nFile);
}
-bool CTxDB::WriteSyncCheckpoint(uint256 hashCheckpoint)
-{
- return Write(string("hashSyncCheckpoint"), hashCheckpoint);
+bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
+ return Read('l', nFile);
}
-bool CTxDB::ReadCheckpointPubKey(string& strPubKey)
-{
- return Read(string("strCheckpointPubKey"), strPubKey);
+CCoinsViewDB::CCoinsViewDB() : db("cr+") {}
+bool CCoinsViewDB::GetCoins(uint256 txid, CCoins &coins) { return db.ReadCoins(txid, coins); }
+bool CCoinsViewDB::SetCoins(uint256 txid, const CCoins &coins) { return db.WriteCoins(txid, coins); }
+bool CCoinsViewDB::HaveCoins(uint256 txid) { return db.HaveCoins(txid); }
+CBlockIndex *CCoinsViewDB::GetBestBlock() {
+ uint256 hashBestChain;
+ if (!db.ReadHashBestChain(hashBestChain))
+ return NULL;
+ std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(hashBestChain);
+ if (it == mapBlockIndex.end())
+ return NULL;
+ return it->second;
}
+bool CCoinsViewDB::SetBestBlock(CBlockIndex *pindex) { return db.WriteHashBestChain(pindex->GetBlockHash()); }
+bool CCoinsViewDB::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) {
+ printf("Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size());
-bool CTxDB::WriteCheckpointPubKey(const string& strPubKey)
-{
- return Write(string("strCheckpointPubKey"), strPubKey);
+ if (!db.TxnBegin())
+ return false;
+ bool fOk = true;
+ for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++) {
+ fOk = db.WriteCoins(it->first, it->second);
+ if (!fOk)
+ break;
+ }
+ if (fOk)
+ fOk = db.WriteHashBestChain(pindex->GetBlockHash());
+
+ if (!fOk)
+ db.TxnAbort();
+ else
+ fOk = db.TxnCommit();
+
+ return fOk;
}
CBlockIndex static * InsertBlockIndex(uint256 hash)
return pindexNew;
}
-bool CTxDB::LoadBlockIndex()
+bool LoadBlockIndexDB()
{
- if (!LoadBlockIndexGuts())
+ if (!pblocktree->LoadBlockIndexGuts())
return false;
if (fRequestShutdown)
{
CBlockIndex* pindex = item.second;
pindex->nChainTrust = (pindex->pprev ? pindex->pprev->nChainTrust : 0) + pindex->GetBlockTrust();
- // ppcoin: calculate stake modifier checksum
+ pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx;
+ if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS && !(pindex->nStatus & BLOCK_FAILED_MASK))
+ setBlockIndexValid.insert(pindex);
+
+ // Calculate stake modifier checksum
pindex->nStakeModifierChecksum = GetStakeModifierChecksum(pindex);
if (!CheckStakeModifierCheckpoints(pindex->nHeight, pindex->nStakeModifierChecksum))
return error("CTxDB::LoadBlockIndex() : Failed stake modifier checkpoint height=%d, modifier=0x%016"PRI64x, pindex->nHeight, pindex->nStakeModifier);
}
+ // Load block file info
+ pblocktree->ReadLastBlockFile(nLastBlockFile);
+ printf("LoadBlockIndex(): last block file = %i\n", nLastBlockFile);
+ if (pblocktree->ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile))
+ printf("LoadBlockIndex(): last block file: %s\n", infoLastBlockFile.ToString().c_str());
+
// Load hashBestChain pointer to end of best chain
- if (!ReadHashBestChain(hashBestChain))
+ pindexBest = pcoinsTip->GetBestBlock();
+ if (pindexBest == NULL)
{
if (pindexGenesisBlock == NULL)
return true;
return error("CTxDB::LoadBlockIndex() : hashBestChain not loaded");
}
- if (!mapBlockIndex.count(hashBestChain))
- return error("CTxDB::LoadBlockIndex() : hashBestChain not found in the block index");
- pindexBest = mapBlockIndex[hashBestChain];
+ hashBestChain = pindexBest->GetBlockHash();
nBestHeight = pindexBest->nHeight;
nBestChainTrust = pindexBest->nChainTrust;
- printf("LoadBlockIndex(): hashBestChain=%s height=%d trust=%s date=%s\n",
- hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, CBigNum(nBestChainTrust).ToString().c_str(),
- DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());
- // ppcoin: load hashSyncCheckpoint
- if (!ReadSyncCheckpoint(Checkpoints::hashSyncCheckpoint))
+ // set 'next' pointers in best chain
+ CBlockIndex *pindex = pindexBest;
+ while(pindex != NULL && pindex->pprev != NULL) {
+ CBlockIndex *pindexPrev = pindex->pprev;
+ pindexPrev->pnext = pindex;
+ pindex = pindexPrev;
+ }
+ printf("LoadBlockIndex(): hashBestChain=%s height=%d date=%s\n",
+ hashBestChain.ToString().substr(0,20).c_str(), nBestHeight,
+ DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());
+
+ // Load sync-checkpoint
+ if (!pblocktree->ReadSyncCheckpoint(Checkpoints::hashSyncCheckpoint))
return error("CTxDB::LoadBlockIndex() : hashSyncCheckpoint not loaded");
printf("LoadBlockIndex(): synchronized checkpoint %s\n", Checkpoints::hashSyncCheckpoint.ToString().c_str());
// Load bnBestInvalidTrust, OK if it doesn't exist
CBigNum bnBestInvalidTrust;
- ReadBestInvalidTrust(bnBestInvalidTrust);
+ pblocktree->ReadBestInvalidTrust(bnBestInvalidTrust);
nBestInvalidTrust = bnBestInvalidTrust.getuint256();
// Verify blocks in the best chain
nCheckDepth = nBestHeight;
printf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
CBlockIndex* pindexFork = NULL;
- map<pair<unsigned int, unsigned int>, CBlockIndex*> mapBlockPos;
for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
{
if (fRequestShutdown || pindex->nHeight < nBestHeight-nCheckDepth)
if (!block.ReadFromDisk(pindex))
return error("LoadBlockIndex() : block.ReadFromDisk failed");
// check level 1: verify block validity
- // check level 7: verify block signature too
- if (nCheckLevel>0 && !block.CheckBlock(true, true, (nCheckLevel>6)))
+ if (nCheckLevel>0 && !block.CheckBlock())
{
printf("LoadBlockIndex() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
pindexFork = pindex->pprev;
}
- // check level 2: verify transaction index validity
- if (nCheckLevel>1)
- {
- pair<unsigned int, unsigned int> pos = make_pair(pindex->nFile, pindex->nBlockPos);
- mapBlockPos[pos] = pindex;
- BOOST_FOREACH(const CTransaction &tx, block.vtx)
- {
- uint256 hashTx = tx.GetHash();
- CTxIndex txindex;
- if (ReadTxIndex(hashTx, txindex))
- {
- // check level 3: checker transaction hashes
- if (nCheckLevel>2 || pindex->nFile != txindex.pos.nFile || pindex->nBlockPos != txindex.pos.nBlockPos)
- {
- // either an error or a duplicate transaction
- CTransaction txFound;
- if (!txFound.ReadFromDisk(txindex.pos))
- {
- printf("LoadBlockIndex() : *** cannot read mislocated transaction %s\n", hashTx.ToString().c_str());
- pindexFork = pindex->pprev;
- }
- else
- if (txFound.GetHash() != hashTx) // not a duplicate tx
- {
- printf("LoadBlockIndex(): *** invalid tx position for %s\n", hashTx.ToString().c_str());
- pindexFork = pindex->pprev;
- }
- }
- // check level 4: check whether spent txouts were spent within the main chain
- unsigned int nOutput = 0;
- if (nCheckLevel>3)
- {
- BOOST_FOREACH(const CDiskTxPos &txpos, txindex.vSpent)
- {
- if (!txpos.IsNull())
- {
- pair<unsigned int, unsigned int> posFind = make_pair(txpos.nFile, txpos.nBlockPos);
- if (!mapBlockPos.count(posFind))
- {
- printf("LoadBlockIndex(): *** found bad spend at %d, hashBlock=%s, hashTx=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str(), hashTx.ToString().c_str());
- pindexFork = pindex->pprev;
- }
- // check level 6: check whether spent txouts were spent by a valid transaction that consume them
- if (nCheckLevel>5)
- {
- CTransaction txSpend;
- if (!txSpend.ReadFromDisk(txpos))
- {
- printf("LoadBlockIndex(): *** cannot read spending transaction of %s:%i from disk\n", hashTx.ToString().c_str(), nOutput);
- pindexFork = pindex->pprev;
- }
- else if (!txSpend.CheckTransaction())
- {
- printf("LoadBlockIndex(): *** spending transaction of %s:%i is invalid\n", hashTx.ToString().c_str(), nOutput);
- pindexFork = pindex->pprev;
- }
- else
- {
- bool fFound = false;
- BOOST_FOREACH(const CTxIn &txin, txSpend.vin)
- if (txin.prevout.hash == hashTx && txin.prevout.n == nOutput)
- fFound = true;
- if (!fFound)
- {
- printf("LoadBlockIndex(): *** spending transaction of %s:%i does not spend it\n", hashTx.ToString().c_str(), nOutput);
- pindexFork = pindex->pprev;
- }
- }
- }
- }
- nOutput++;
- }
- }
- }
- // check level 5: check whether all prevouts are marked spent
- if (nCheckLevel>4)
- {
- BOOST_FOREACH(const CTxIn &txin, tx.vin)
- {
- CTxIndex txindex;
- if (ReadTxIndex(txin.prevout.hash, txindex))
- if (txindex.vSpent.size()-1 < txin.prevout.n || txindex.vSpent[txin.prevout.n].IsNull())
- {
- printf("LoadBlockIndex(): *** found unspent prevout %s:%i in %s\n", txin.prevout.hash.ToString().c_str(), txin.prevout.n, hashTx.ToString().c_str());
- pindexFork = pindex->pprev;
- }
- }
- }
- }
- }
+ // TODO: stronger verifications
}
if (pindexFork && !fRequestShutdown)
{
- // Reorg back to the fork
- printf("LoadBlockIndex() : *** moving best chain pointer back to block %d\n", pindexFork->nHeight);
- CBlock block;
- if (!block.ReadFromDisk(pindexFork))
- return error("LoadBlockIndex() : block.ReadFromDisk failed");
- CTxDB txdb;
- block.SetBestChain(txdb, pindexFork);
+ // TODO: reorg back
+ return error("LoadBlockIndex(): chain database corrupted");
}
return true;
-bool CTxDB::LoadBlockIndexGuts()
+bool CBlockTreeDB::LoadBlockIndexGuts()
{
// Get database cursor
Dbc* pcursor = GetCursor();
// Load mapBlockIndex
unsigned int fFlags = DB_SET_RANGE;
- loop
+ while (true)
{
// Read next record
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
if (fFlags == DB_SET_RANGE)
- ssKey << make_pair(string("blockindex"), uint256(0));
+ ssKey << make_pair('b', uint256(0));
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags);
fFlags = DB_NEXT;
// Unserialize
try {
- string strType;
- ssKey >> strType;
- if (strType == "blockindex" && !fRequestShutdown)
+ char chType;
+ ssKey >> chType;
+ if (chType == 'b' && !fRequestShutdown)
{
CDiskBlockIndex diskindex;
ssValue >> diskindex;
+ uint256 blockHash = diskindex.GetBlockHash();
+
// Construct block index object
- CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
+ CBlockIndex* pindexNew = InsertBlockIndex(blockHash);
pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev);
- pindexNew->pnext = InsertBlockIndex(diskindex.hashNext);
- pindexNew->nFile = diskindex.nFile;
- pindexNew->nBlockPos = diskindex.nBlockPos;
pindexNew->nHeight = diskindex.nHeight;
+ pindexNew->nFile = diskindex.nFile;
+ pindexNew->nDataPos = diskindex.nDataPos;
+ pindexNew->nUndoPos = diskindex.nUndoPos;
pindexNew->nMint = diskindex.nMint;
pindexNew->nMoneySupply = diskindex.nMoneySupply;
pindexNew->nFlags = diskindex.nFlags;
pindexNew->nTime = diskindex.nTime;
pindexNew->nBits = diskindex.nBits;
pindexNew->nNonce = diskindex.nNonce;
+ pindexNew->nStatus = diskindex.nStatus;
+ pindexNew->nTx = diskindex.nTx;
// Watch for genesis block
- if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet))
+ if (pindexGenesisBlock == NULL && blockHash == (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet))
pindexGenesisBlock = pindexNew;
if (!pindexNew->CheckIndex())
- return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight);
+ return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString().c_str());
- // ppcoin: build setStakeSeen
+ // Build setStakeSeen
if (pindexNew->IsProofOfStake())
setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime));
}
// use file size to size memory buffer
int fileSize = GetFilesize(filein);
int dataSize = fileSize - sizeof(uint256);
- //Don't try to resize to a negative number if file is small
- if ( dataSize < 0 ) dataSize = 0;
vector<unsigned char> vchData;
vchData.resize(dataSize);
uint256 hashIn;
if (hashIn != hashTmp)
return error("CAddrman::Read() : checksum mismatch; data corrupted");
+ // de-serialize address data
unsigned char pchMsgTmp[4];
try {
- // de-serialize file header (pchMessageStart magic number) and
ssPeers >> FLATDATA(pchMsgTmp);
-
- // verify the network matches ours
- if (memcmp(pchMsgTmp, pchMessageStart, sizeof(pchMsgTmp)))
- return error("CAddrman::Read() : invalid network magic number");
-
- // de-serialize address data into one CAddrMan object
ssPeers >> addr;
}
catch (std::exception &e) {
return error("CAddrman::Read() : I/O error or stream data corrupted");
}
+ // finally, verify the network matches ours
+ if (memcmp(pchMsgTmp, pchMessageStart, sizeof(pchMsgTmp)))
+ return error("CAddrman::Read() : invalid network magic number");
+
return true;
}