From c37ffd1eb308a6dcca73eecc20e93e5ce9d46e88 Mon Sep 17 00:00:00 2001 From: alexhz Date: Wed, 15 Jan 2014 16:50:06 +0000 Subject: [PATCH] One file per block Block database now stores one file per block. --- src/db.cpp | 2 - src/kernel.cpp | 4 +- src/main.cpp | 95 ++++++++++-------------------- src/main.h | 161 +++++++++++++++++++++++++++++++++++-------------- src/miner.cpp | 4 +- src/txdb-leveldb.cpp | 15 +---- src/wallet.cpp | 4 +- 7 files changed, 155 insertions(+), 130 deletions(-) diff --git a/src/db.cpp b/src/db.cpp index cc069e1..7da754f 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -21,8 +21,6 @@ using namespace boost; unsigned int nWalletDBUpdated; - - // // CDB // diff --git a/src/kernel.cpp b/src/kernel.cpp index 5a8d3d6..fb8216c 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -357,10 +357,10 @@ bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits, uint256& hash // Read block header CBlock block; - if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) + if (!block.ReadFromDisk(txindex.pos.blockPos, false)) return fDebug? error("CheckProofOfStake() : read block failed") : false; // unable to read block of previous transaction - if (!CheckStakeKernelHash(nBits, block, txindex.pos.nTxPos - txindex.pos.nBlockPos, txPrev, txin.prevout, tx.nTime, hashProofOfStake, targetProofOfStake, fDebug)) + if (!CheckStakeKernelHash(nBits, block, txindex.pos.nTxPos, txPrev, txin.prevout, tx.nTime, hashProofOfStake, targetProofOfStake, fDebug)) return tx.DoS(1, error("CheckProofOfStake() : INFO: check kernel failed on coinstake %s, hashProof=%s", tx.GetHash().ToString().c_str(), hashProofOfStake.ToString().c_str())); // may occur during initial download or if behind on block chain sync return true; diff --git a/src/main.cpp b/src/main.cpp index 54c17c3..55a09d7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -416,7 +416,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock) CTxIndex txindex; if (!CTxDB("r").ReadTxIndex(GetHash(), txindex)) return 0; - if (!blockTmp.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos)) + if (!blockTmp.ReadFromDisk(txindex.pos.blockPos)) return 0; pblock = &blockTmp; } @@ -665,7 +665,7 @@ bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx, bool fCheckInputs, // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. - if (!tx.ConnectInputs(txdb, mapInputs, mapUnused, CDiskTxPos(1,1,1), pindexBest, false, false)) + if (!tx.ConnectInputs(txdb, mapInputs, mapUnused, CDiskTxPos(true), pindexBest, false, false)) { return error("CTxMemPool::accept() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str()); } @@ -836,7 +836,7 @@ int CTxIndex::GetDepthInMainChain() const { // Read block header CBlock block; - if (!block.ReadFromDisk(pos.nFile, pos.nBlockPos, false)) + if (!block.ReadFromDisk(pos.blockPos, false)) return 0; // Find the block in the index map::iterator mi = mapBlockIndex.find(block.GetHash()); @@ -866,7 +866,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock) if (tx.ReadFromDisk(txdb, COutPoint(hash, 0), txindex)) { CBlock block; - if (block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) + if (block.ReadFromDisk(txindex.pos.blockPos, false)) hashBlock = block.GetHash(); return true; } @@ -911,7 +911,7 @@ bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions) *this = pindex->GetBlockHeader(); return true; } - if (!ReadFromDisk(pindex->nFile, pindex->nBlockPos, fReadTransactions)) + if (!ReadFromDisk(pindex->GetBlockPos(), fReadTransactions)) return false; if (GetHash() != pindex->GetBlockHash()) return error("CBlock::ReadFromDisk() : GetHash() doesn't match index"); @@ -1318,7 +1318,7 @@ bool CTransaction::FetchInputs(CTxDB& txdb, const map& mapTes // Read txPrev CTransaction& txPrev = inputsRet[prevout.hash].second; - if (!fFound || txindex.pos == CDiskTxPos(1,1,1)) + if (!fFound || txindex.pos.IsMemPool()) { // Get prev tx from single transactions in memory { @@ -1423,7 +1423,7 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, MapPrevTx inputs, mapnHeight - pindex->nHeight < nCoinbaseMaturity; pindex = pindex->pprev) - if (pindex->nBlockPos == txindex.pos.nBlockPos && pindex->nFile == txindex.pos.nFile) + if (pindex->GetBlockPos() == txindex.pos.blockPos) return error("ConnectInputs() : tried to spend %s at depth %d", txPrev.IsCoinBase() ? "coinbase" : "coinstake", pindexBlock->nHeight - pindex->nHeight); // ppcoin: check transaction timestamp @@ -1613,11 +1613,10 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) //// issue here: it doesn't know the version unsigned int nTxPos; if (fJustCheck) - // FetchInputs treats CDiskTxPos(1,1,1) as a special "refer to memorypool" indicator // Since we're just checking the block and not actually connecting it, it might not (and probably shouldn't) be on the disk to get the transaction from nTxPos = 1; else - nTxPos = pindex->nBlockPos + ::GetSerializeSize(CBlock(), SER_DISK, CLIENT_VERSION) - (2 * GetSizeOfCompactSize(0)) + GetSizeOfCompactSize(vtx.size()); + nTxPos = ::GetSerializeSize(CBlock(), SER_DISK, CLIENT_VERSION) - (2 * GetSizeOfCompactSize(0)) + GetSizeOfCompactSize(vtx.size()); map mapQueuedChanges; int64 nFees = 0; @@ -1641,7 +1640,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) if (nSigOps > MAX_BLOCK_SIGOPS) return DoS(100, error("ConnectBlock() : too many sigops")); - CDiskTxPos posThisTx(pindex->nFile, pindex->nBlockPos, nTxPos); + CDiskTxPos posThisTx(pindex->GetBlockPos(), nTxPos); if (!fJustCheck) nTxPos += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); @@ -1984,7 +1983,7 @@ bool CTransaction::GetCoinAge(CTxDB& txdb, uint64& nCoinAge) const // Read block header CBlock block; - if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) + if (!block.ReadFromDisk(txindex.pos.blockPos, false)) return false; // unable to read block of previous transaction if (block.GetBlockTime() + nStakeMinAge > nTime) continue; // only count coins meeting min age requirement @@ -2025,7 +2024,7 @@ bool CBlock::GetCoinAge(uint64& nCoinAge) const return true; } -bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) +bool CBlock::AddToBlockIndex(const CDiskBlockPos &pos) { // Check for duplicate uint256 hash = GetHash(); @@ -2033,7 +2032,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) return error("AddToBlockIndex() : %s already exists", hash.ToString().substr(0,20).c_str()); // Construct new block index object - CBlockIndex* pindexNew = new CBlockIndex(nFile, nBlockPos, *this); + CBlockIndex* pindexNew = new CBlockIndex(*this); if (!pindexNew) return error("AddToBlockIndex() : new CBlockIndex failed"); pindexNew->phashBlock = &hash; @@ -2047,6 +2046,9 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) // ppcoin: compute chain trust score pindexNew->nChainTrust = (pindexNew->pprev ? pindexNew->pprev->nChainTrust : 0) + pindexNew->GetBlockTrust(); + assert(pos.nHeight == pindexNew->nHeight); + pindexNew->nAlternative = pos.nAlternative; + // ppcoin: compute stake entropy bit for stake modifier if (!pindexNew->SetStakeEntropyBit(GetStakeEntropyBit(pindexNew->nTime))) return error("AddToBlockIndex() : SetStakeEntropyBit() failed"); @@ -2261,13 +2263,12 @@ bool CBlock::AcceptBlock() return DoS(100, error("AcceptBlock() : block height mismatch in coinbase")); // Write block to history file + CDiskBlockPos blockPos = CDiskBlockPos(nHeight); if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK, CLIENT_VERSION))) return error("AcceptBlock() : out of disk space"); - unsigned int nFile = -1; - unsigned int nBlockPos = 0; - if (!WriteToDisk(nFile, nBlockPos)) + if (!WriteToDisk(blockPos)) return error("AcceptBlock() : WriteToDisk failed"); - if (!AddToBlockIndex(nFile, nBlockPos)) + if (!AddToBlockIndex(blockPos)) return error("AcceptBlock() : AddToBlockIndex failed"); // Relay inventory, but don't relay old inventory during initial block download @@ -2625,53 +2626,19 @@ bool CheckDiskSpace(uint64 nAdditionalBytes) return true; } -static filesystem::path BlockFilePath(unsigned int nFile) -{ - string strBlockFn = strprintf("blk%04u.dat", nFile); - return GetDataDir() / strBlockFn; -} -FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode) +FILE* OpenBlockFile(const CDiskBlockPos &pos, const char* pszMode) { - if ((nFile < 1) || (nFile == (unsigned int) -1)) + boost::filesystem::path path = pos.GetFileName(GetDataDir()); + boost::filesystem::create_directories(path.parent_path()); + if (pos.IsNull() || pos.IsMemPool()) return NULL; - FILE* file = fopen(BlockFilePath(nFile).string().c_str(), pszMode); + FILE* file = fopen(path.string().c_str(), pszMode); if (!file) return NULL; - if (nBlockPos != 0 && !strchr(pszMode, 'a') && !strchr(pszMode, 'w')) - { - if (fseek(file, nBlockPos, SEEK_SET) != 0) - { - fclose(file); - return NULL; - } - } return file; } -static unsigned int nCurrentBlockFile = 1; - -FILE* AppendBlockFile(unsigned int& nFileRet) -{ - nFileRet = 0; - while (true) - { - FILE* file = OpenBlockFile(nCurrentBlockFile, 0, "ab"); - if (!file) - return NULL; - if (fseek(file, 0, SEEK_END) != 0) - return NULL; - // FAT32 file size max 4GB, fseek and ftell max 2GB, so we must stay under 2GB - if (ftell(file) < (long)(0x7F000000 - MAX_SIZE)) - { - nFileRet = nCurrentBlockFile; - return file; - } - fclose(file); - nCurrentBlockFile++; - } -} - bool LoadBlockIndex(bool fAllowNew) { CBigNum bnTrustedModulus; @@ -2748,17 +2715,18 @@ bool LoadBlockIndex(bool fAllowNew) block.nNonce = !fTestNet ? 1575379 : 46534; //// debug print + uint256 hash = block.GetHash(); + printf("%s\n", hash.ToString().c_str()); assert(block.hashMerkleRoot == uint256("0x4cb33b3b6a861dcbc685d3e614a9cafb945738d6833f182855679f2fad02057b")); block.print(); - assert(block.GetHash() == (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet)); + assert(hash == (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet)); assert(block.CheckBlock()); // Start new block file - unsigned int nFile; - unsigned int nBlockPos; - if (!block.WriteToDisk(nFile, nBlockPos)) + CDiskBlockPos blockPos(0); + if (!block.WriteToDisk(blockPos)) return error("LoadBlockIndex() : writing genesis block to disk failed"); - if (!block.AddToBlockIndex(nFile, nBlockPos)) + if (!block.AddToBlockIndex(blockPos)) return error("LoadBlockIndex() : genesis block not accepted"); // ppcoin: initialize synchronized checkpoint @@ -2831,10 +2799,9 @@ void PrintBlockTree() // print item CBlock block; block.ReadFromDisk(pindex); - printf("%d (%u,%u) %s %08x %s mint %7s tx %"PRIszu"", + printf("%d (%s) %s %08x %s mint %7s tx %"PRIszu"", pindex->nHeight, - pindex->nFile, - pindex->nBlockPos, + pindex->GetBlockPos().GetFileName("").string().c_str(), block.GetHash().ToString().c_str(), block.nBits, DateTimeStrFormat("%x %H:%M:%S", block.GetBlockTime()).c_str(), diff --git a/src/main.h b/src/main.h index 9db3dc6..beeba3d 100644 --- a/src/main.h +++ b/src/main.h @@ -99,14 +99,14 @@ static const uint64 nMinDiskSpace = 52428800; class CReserveKey; class CTxDB; class CTxIndex; +class CDiskBlockPos; void RegisterWallet(CWallet* pwalletIn); void UnregisterWallet(CWallet* pwalletIn); void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false, bool fConnect = true); bool ProcessBlock(CNode* pfrom, CBlock* pblock); bool CheckDiskSpace(uint64 nAdditionalBytes=0); -FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb"); -FILE* AppendBlockFile(unsigned int& nFileRet); +FILE* OpenBlockFile(const CDiskBlockPos &pos, const char* pszMode="rb"); bool LoadBlockIndex(bool fAllowNew=true); void PrintBlockTree(); CBlockIndex* FindBlockByHeight(int nHeight); @@ -129,46 +129,120 @@ const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfSta void StakeMiner(CWallet *pwallet); void ResendWalletTransactions(); +bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut); + +class CDiskBlockPos +{ +public: + int nHeight; + int nAlternative; + CDiskBlockPos() { + SetNull(); + } + CDiskBlockPos(int nHeightIn, int nAlternativeIn = 0) { + nHeight = nHeightIn; + nAlternative = nAlternativeIn; + } + std::string GetAlternative() const { + char c[9]={0,0,0,0,0,0,0,0,0}; + char *cp = &c[8]; + unsigned int n = nAlternative; + while (n > 0 && cp>c) { + n--; + *(--cp) = 'a' + (n % 26); + n /= 26; + } + return std::string(cp); + } + boost::filesystem::path GetDirectory(const boost::filesystem::path &base) const { + assert(nHeight != -1); + return base / strprintf("era%02u", nHeight / 210000) / + strprintf("cycle%04u", nHeight / 2016); + } + + boost::filesystem::path GetFileName(const boost::filesystem::path &base) const { + return GetDirectory(base) / strprintf("%08u%s.blk", nHeight, GetAlternative().c_str()); + } + + // TODO: make thread-safe (lockfile, atomic file creation, ...?) + void MakeUnique(const boost::filesystem::path &base) { + while (boost::filesystem::exists(GetFileName(base))) + nAlternative++; + } + + IMPLEMENT_SERIALIZE(({ + CDiskBlockPos *me = const_cast(this); + if (!fRead) { + unsigned int nCode = (nHeight + 1) * 2 + (nAlternative > 0); + READWRITE(VARINT(nCode)); + if (nAlternative > 0) { + unsigned int nAlt = nAlternative - 1; + READWRITE(VARINT(nAlt)); + } + } else { + unsigned int nCode = 0; + READWRITE(VARINT(nCode)); + me->nHeight = (nCode / 2) - 1; + if (nCode & 1) { + unsigned int nAlt = 0; + READWRITE(VARINT(nAlt)); + me->nAlternative = 1 + nAlt; + } else { + me->nAlternative = 0; + } + } + });) + friend bool operator==(const CDiskBlockPos &a, const CDiskBlockPos &b) { + return ((a.nHeight == b.nHeight) && (a.nAlternative == b.nAlternative)); + } + friend bool operator!=(const CDiskBlockPos &a, const CDiskBlockPos &b) { + return !(a == b); + } + void SetNull() { nHeight = -1; nAlternative = 0; } + bool IsNull() const { return ((nHeight == -1) && (nAlternative == 0)); } + void SetMemPool() { nHeight = -1; nAlternative = -1; } + bool IsMemPool() const { return ((nHeight == -1) && (nAlternative == -1)); } +}; -bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut); /** Position on disk for a particular transaction. */ class CDiskTxPos { public: - unsigned int nFile; - unsigned int nBlockPos; + CDiskBlockPos blockPos; unsigned int nTxPos; - CDiskTxPos() + CDiskTxPos(bool fInMemPool = false) { SetNull(); - } + if (fInMemPool) + blockPos.SetMemPool(); - CDiskTxPos(unsigned int nFileIn, unsigned int nBlockPosIn, unsigned int nTxPosIn) - { - nFile = nFileIn; - nBlockPos = nBlockPosIn; - nTxPos = nTxPosIn; } - IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); ) - void SetNull() { nFile = (unsigned int) -1; nBlockPos = 0; nTxPos = 0; } - bool IsNull() const { return (nFile == (unsigned int) -1); } + CDiskTxPos(const CDiskBlockPos &block, unsigned int nTxPosIn) : blockPos(block), nTxPos(nTxPosIn) { } + + IMPLEMENT_SERIALIZE( + READWRITE(blockPos); + READWRITE(VARINT(nTxPos)); + ) + + void SetNull() { blockPos.SetNull(); nTxPos = 0; } + bool IsNull() const { return blockPos.IsNull(); } + bool IsMemPool() const { return blockPos.IsMemPool(); } friend bool operator==(const CDiskTxPos& a, const CDiskTxPos& b) { - return (a.nFile == b.nFile && - a.nBlockPos == b.nBlockPos && - a.nTxPos == b.nTxPos); + return (a.blockPos == b.blockPos && + a.nTxPos == b.nTxPos); } friend bool operator!=(const CDiskTxPos& a, const CDiskTxPos& b) @@ -181,8 +255,10 @@ public: { if (IsNull()) return "null"; + else if (blockPos.IsMemPool()) + return "mempool"; else - return strprintf("(nFile=%u, nBlockPos=%u, nTxPos=%u)", nFile, nBlockPos, nTxPos); + return strprintf("(%s, nTxPos=%u)", blockPos.GetFileName("").string().c_str(), nTxPos); } void print() const @@ -599,7 +675,7 @@ public: bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL) { - CAutoFile filein = CAutoFile(OpenBlockFile(pos.nFile, 0, pfileRet ? "rb+" : "rb"), SER_DISK, CLIENT_VERSION); + CAutoFile filein = CAutoFile(OpenBlockFile(pos.blockPos, pfileRet ? "rb+" : "rb"), SER_DISK, CLIENT_VERSION); if (!filein) return error("CTransaction::ReadFromDisk() : OpenBlockFile failed"); @@ -1338,22 +1414,15 @@ public: } - bool WriteToDisk(unsigned int& nFileRet, unsigned int& nBlockPosRet) + bool WriteToDisk(CDiskBlockPos &pos) { // Open history file to append - CAutoFile fileout = CAutoFile(AppendBlockFile(nFileRet), SER_DISK, CLIENT_VERSION); + pos.MakeUnique(GetDataDir()); + CAutoFile fileout = CAutoFile(OpenBlockFile(pos, "ab"), SER_DISK, CLIENT_VERSION); if (!fileout) return error("CBlock::WriteToDisk() : AppendBlockFile failed"); - // Write index header - unsigned int nSize = fileout.GetSerializeSize(*this); - fileout << FLATDATA(pchMessageStart) << nSize; - // Write block - long fileOutPos = ftell(fileout); - if (fileOutPos < 0) - return error("CBlock::WriteToDisk() : ftell failed"); - nBlockPosRet = fileOutPos; fileout << *this; // Flush stdio buffers and commit to disk before returning @@ -1364,12 +1433,12 @@ public: return true; } - bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions=true) + bool ReadFromDisk(const CDiskBlockPos &pos, bool fReadTransactions = true) { SetNull(); // Open history file to read - CAutoFile filein = CAutoFile(OpenBlockFile(nFile, nBlockPos, "rb"), SER_DISK, CLIENT_VERSION); + CAutoFile filein = CAutoFile(OpenBlockFile(pos, "rb"), SER_DISK, CLIENT_VERSION); if (!filein) return error("CBlock::ReadFromDisk() : OpenBlockFile failed"); if (!fReadTransactions) @@ -1418,7 +1487,7 @@ public: bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck=false); bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true); bool SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew); - bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos); + bool AddToBlockIndex(const CDiskBlockPos &pos); bool CheckBlock(bool fCheckPOW=true, bool fCheckMerkleRoot=true, bool fCheckSig=true) const; bool AcceptBlock(); bool GetCoinAge(uint64& nCoinAge) const; // ppcoin: calculate total coin age spent in block @@ -1447,16 +1516,15 @@ public: const uint256* phashBlock; CBlockIndex* pprev; CBlockIndex* pnext; - unsigned int nFile; - unsigned int nBlockPos; uint256 nChainTrust; // ppcoin: trust score of block chain int nHeight; + unsigned int nAlternative; int64 nMint; int64 nMoneySupply; - unsigned int nFlags; // ppcoin: block index flags - enum + unsigned int nFlags; + enum { BLOCK_PROOF_OF_STAKE = (1 << 0), // is proof-of-stake block BLOCK_STAKE_ENTROPY = (1 << 1), // entropy bit for stake modifier @@ -1483,8 +1551,6 @@ public: phashBlock = NULL; pprev = NULL; pnext = NULL; - nFile = 0; - nBlockPos = 0; nHeight = 0; nChainTrust = 0; nMint = 0; @@ -1495,6 +1561,7 @@ public: hashProofOfStake = 0; prevoutStake.SetNull(); nStakeTime = 0; + nAlternative = 0; nVersion = 0; hashMerkleRoot = 0; @@ -1503,13 +1570,11 @@ public: nNonce = 0; } - CBlockIndex(unsigned int nFileIn, unsigned int nBlockPosIn, CBlock& block) + CBlockIndex(CBlock& block) { phashBlock = NULL; pprev = NULL; pnext = NULL; - nFile = nFileIn; - nBlockPos = nBlockPosIn; nHeight = 0; nChainTrust = 0; nMint = 0; @@ -1529,6 +1594,7 @@ public: prevoutStake.SetNull(); nStakeTime = 0; } + nAlternative = 0; nVersion = block.nVersion; hashMerkleRoot = block.hashMerkleRoot; @@ -1537,6 +1603,10 @@ public: nNonce = block.nNonce; } + CDiskBlockPos GetBlockPos() const { + return CDiskBlockPos(nHeight, nAlternative); + } + CBlock GetBlockHeader() const { CBlock block; @@ -1650,8 +1720,8 @@ public: std::string ToString() const { - return strprintf("CBlockIndex(nprev=%p, pnext=%p, nFile=%u, nBlockPos=%-6d nHeight=%d, nMint=%s, nMoneySupply=%s, nFlags=(%s)(%d)(%s), nStakeModifier=%016"PRI64x", nStakeModifierChecksum=%08x, hashProofOfStake=%s, prevoutStake=(%s), nStakeTime=%d merkle=%s, hashBlock=%s)", - pprev, pnext, nFile, nBlockPos, nHeight, + return strprintf("CBlockIndex(nprev=%p, pnext=%p nHeight=%d, nMint=%s, nMoneySupply=%s, nFlags=(%s)(%d)(%s), nStakeModifier=%016"PRI64x", nStakeModifierChecksum=%08x, hashProofOfStake=%s, prevoutStake=(%s), nStakeTime=%d merkle=%s, hashBlock=%s)", + pprev, pnext, nHeight, FormatMoney(nMint).c_str(), FormatMoney(nMoneySupply).c_str(), GeneratedStakeModifier() ? "MOD" : "-", GetStakeEntropyBit(), IsProofOfStake()? "PoS" : "PoW", nStakeModifier, nStakeModifierChecksum, @@ -1698,9 +1768,8 @@ public: READWRITE(nVersion); READWRITE(hashNext); - READWRITE(nFile); - READWRITE(nBlockPos); READWRITE(nHeight); + READWRITE(nAlternative); READWRITE(nMint); READWRITE(nMoneySupply); READWRITE(nFlags); diff --git a/src/miner.cpp b/src/miner.cpp index 92ade15..6f1e9f0 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -311,9 +311,9 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake) if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) continue; - if (!tx.ConnectInputs(txdb, mapInputs, mapTestPoolTmp, CDiskTxPos(1,1,1), pindexPrev, false, true)) + if (!tx.ConnectInputs(txdb, mapInputs, mapTestPoolTmp, CDiskTxPos(true), pindexPrev, false, true)) continue; - mapTestPoolTmp[tx.GetHash()] = CTxIndex(CDiskTxPos(1,1,1), tx.vout.size()); + mapTestPoolTmp[tx.GetHash()] = CTxIndex(CDiskTxPos(true), tx.vout.size()); swap(mapTestPool, mapTestPoolTmp); // Added diff --git a/src/txdb-leveldb.cpp b/src/txdb-leveldb.cpp index 8367665..97f23cc 100644 --- a/src/txdb-leveldb.cpp +++ b/src/txdb-leveldb.cpp @@ -361,9 +361,8 @@ bool CTxDB::LoadBlockIndex() 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->nAlternative = diskindex.nAlternative; pindexNew->nMint = diskindex.nMint; pindexNew->nMoneySupply = diskindex.nMoneySupply; pindexNew->nFlags = diskindex.nFlags; @@ -452,12 +451,12 @@ bool CTxDB::LoadBlockIndex() nCheckDepth = nBestHeight; printf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel); CBlockIndex* pindexFork = NULL; - map, CBlockIndex*> mapBlockPos; for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev) { if (fRequestShutdown || pindex->nHeight < nBestHeight-nCheckDepth) break; CBlock block; + CDiskBlockPos blockPos = pindex->GetBlockPos(); if (!block.ReadFromDisk(pindex)) return error("LoadBlockIndex() : block.ReadFromDisk failed"); // check level 1: verify block validity @@ -470,8 +469,6 @@ bool CTxDB::LoadBlockIndex() // check level 2: verify transaction index validity if (nCheckLevel>1) { - pair pos = make_pair(pindex->nFile, pindex->nBlockPos); - mapBlockPos[pos] = pindex; BOOST_FOREACH(const CTransaction &tx, block.vtx) { uint256 hashTx = tx.GetHash(); @@ -479,7 +476,7 @@ bool CTxDB::LoadBlockIndex() if (ReadTxIndex(hashTx, txindex)) { // check level 3: checker transaction hashes - if (nCheckLevel>2 || pindex->nFile != txindex.pos.nFile || pindex->nBlockPos != txindex.pos.nBlockPos) + if (nCheckLevel>2 || blockPos != txindex.pos.blockPos) { // either an error or a duplicate transaction CTransaction txFound; @@ -503,12 +500,6 @@ bool CTxDB::LoadBlockIndex() { if (!txpos.IsNull()) { - pair 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) { diff --git a/src/wallet.cpp b/src/wallet.cpp index ca33136..9d95493 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1613,7 +1613,7 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int CBlock block; { LOCK2(cs_main, cs_wallet); - if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) + if (!block.ReadFromDisk(txindex.pos.blockPos, false)) continue; } @@ -1628,7 +1628,7 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int // Search nSearchInterval seconds back up to nMaxStakeSearchInterval uint256 hashProofOfStake = 0, targetProofOfStake = 0; COutPoint prevoutStake = COutPoint(pcoin.first->GetHash(), pcoin.second); - if (CheckStakeKernelHash(nBits, block, txindex.pos.nTxPos - txindex.pos.nBlockPos, *pcoin.first, prevoutStake, txNew.nTime - n, hashProofOfStake, targetProofOfStake)) + if (CheckStakeKernelHash(nBits, block, txindex.pos.nTxPos, *pcoin.first, prevoutStake, txNew.nTime - n, hashProofOfStake, targetProofOfStake)) { // Found a kernel if (fDebug && GetBoolArg("-printcoinstake")) -- 1.7.1