aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2012-06-19 01:36:43 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2012-10-20 23:08:57 +0200
commit630fd8dcb6662ed167e967625f2715f97ddd2db5 (patch)
tree6cb32ecd892a2d2f0368e57ea424f7efcd601b1a /src
parent44ac1c0fe370ef4b7110af8d1fa1b6230f3658eb (diff)
downloadbitcoin-630fd8dcb6662ed167e967625f2715f97ddd2db5.tar.xz
One file per block
Refactor of the block storage code, which now stores one file per block. This will allow easier pruning, as blocks can be removed individually.
Diffstat (limited to 'src')
-rw-r--r--src/db.cpp15
-rw-r--r--src/main.cpp103
-rw-r--r--src/main.h161
3 files changed, 155 insertions, 124 deletions
diff --git a/src/db.cpp b/src/db.cpp
index 9ad67892f1..cef395c444 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -637,12 +637,12 @@ bool CTxDB::LoadBlockIndex()
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)
break;
CBlock block;
+ CDiskBlockPos blockPos = pindex->GetBlockPos();
if (!block.ReadFromDisk(pindex))
return error("LoadBlockIndex() : block.ReadFromDisk failed");
// check level 1: verify block validity
@@ -654,8 +654,6 @@ bool CTxDB::LoadBlockIndex()
// 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();
@@ -663,7 +661,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;
@@ -687,12 +685,6 @@ bool CTxDB::LoadBlockIndex()
{
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)
{
@@ -795,9 +787,8 @@ bool CTxDB::LoadBlockIndexGuts()
CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
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->nVersion = diskindex.nVersion;
pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot;
pindexNew->nTime = diskindex.nTime;
diff --git a/src/main.cpp b/src/main.cpp
index ed677f31c8..fa818bd053 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -389,7 +389,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;
}
@@ -646,7 +646,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(mapInputs, mapUnused, CDiskTxPos(1,1,1), pindexBest, false, false))
+ if (!tx.ConnectInputs(mapInputs, mapUnused, CDiskTxPos(true), pindexBest, false, false))
{
return error("CTxMemPool::accept() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str());
}
@@ -817,7 +817,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<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(block.GetHash());
@@ -847,7 +847,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;
}
@@ -892,7 +892,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");
@@ -1156,7 +1156,7 @@ bool CTransaction::FetchInputs(CTxDB& txdb, const map<uint256, CTxIndex>& 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
{
@@ -1262,7 +1262,7 @@ bool CTransaction::ConnectInputs(MapPrevTx inputs,
// If prev is coinbase, check that it's matured
if (txPrev.IsCoinBase())
for (const CBlockIndex* pindex = pindexBlock; pindex && pindexBlock->nHeight - pindex->nHeight < COINBASE_MATURITY; 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 coinbase at depth %d", pindexBlock->nHeight - pindex->nHeight);
// Check for negative or overflow input values
@@ -1427,11 +1427,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) - 1 + GetSizeOfCompactSize(vtx.size());
+ nTxPos = ::GetSerializeSize(CBlock(), SER_DISK, CLIENT_VERSION) - 1 + GetSizeOfCompactSize(vtx.size());
map<uint256, CTxIndex> mapQueuedChanges;
int64 nFees = 0;
@@ -1453,9 +1452,11 @@ 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);
+ else
+ posThisTx = CDiskTxPos(true);
MapPrevTx mapInputs;
if (!tx.IsCoinBase())
@@ -1750,7 +1751,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
}
-bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
+bool CBlock::AddToBlockIndex(const CDiskBlockPos &pos)
{
// Check for duplicate
uint256 hash = GetHash();
@@ -1758,7 +1759,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");
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
@@ -1770,6 +1771,8 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
}
pindexNew->bnChainWork = (pindexNew->pprev ? pindexNew->pprev->bnChainWork : 0) + pindexNew->GetBlockWork();
+ assert(pos.nHeight == pindexNew->nHeight);
+ pindexNew->nAlternative = pos.nAlternative;
CTxDB txdb;
if (!txdb.TxnBegin())
@@ -1908,13 +1911,12 @@ bool CBlock::AcceptBlock()
}
// 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
@@ -2048,53 +2050,18 @@ bool CheckDiskSpace(uint64 nAdditionalBytes)
return true;
}
-static filesystem::path BlockFilePath(unsigned int nFile)
+FILE* OpenBlockFile(const CDiskBlockPos &pos, const char* pszMode)
{
- string strBlockFn = strprintf("blk%04u.dat", nFile);
- return GetDataDir() / strBlockFn;
-}
-
-FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, 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;
- loop
- {
- 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)
{
if (fTestNet)
@@ -2153,19 +2120,19 @@ bool LoadBlockIndex(bool fAllowNew)
}
//// debug print
- printf("%s\n", block.GetHash().ToString().c_str());
+ uint256 hash = block.GetHash();
+ printf("%s\n", hash.ToString().c_str());
printf("%s\n", hashGenesisBlock.ToString().c_str());
printf("%s\n", block.hashMerkleRoot.ToString().c_str());
assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
block.print();
- assert(block.GetHash() == hashGenesisBlock);
+ assert(hash == hashGenesisBlock);
// 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");
}
@@ -2219,11 +2186,9 @@ void PrintBlockTree()
// print item
CBlock block;
block.ReadFromDisk(pindex);
- printf("%d (%u,%u) %s %s tx %"PRIszu"",
+ printf("%d (%s) %s tx %"PRIszu"",
pindex->nHeight,
- pindex->nFile,
- pindex->nBlockPos,
- block.GetHash().ToString().substr(0,20).c_str(),
+ pindex->GetBlockPos().GetFileName("").string().c_str(),
DateTimeStrFormat("%x %H:%M:%S", block.GetBlockTime()).c_str(),
block.vtx.size());
@@ -3693,9 +3658,9 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
continue;
- if (!tx.ConnectInputs(mapInputs, mapTestPoolTmp, CDiskTxPos(1,1,1), pindexPrev, false, true))
+ if (!tx.ConnectInputs(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
@@ -3743,7 +3708,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
pblock->nNonce = 0;
pblock->vtx[0].vin[0].scriptSig = scriptDummy;
- CBlockIndex indexDummy(1, 1, *pblock);
+ CBlockIndex indexDummy(*pblock);
indexDummy.pprev = pindexPrev;
indexDummy.nHeight = pindexPrev->nHeight + 1;
if (!pblock->ConnectBlock(txdb, &indexDummy, true))
diff --git a/src/main.h b/src/main.h
index 0c85286391..a1d6334746 100644
--- a/src/main.h
+++ b/src/main.h
@@ -80,14 +80,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 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);
@@ -118,34 +118,115 @@ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock);
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<CDiskBlockPos*>(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)); }
+};
+
/** 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;
- }
+ CDiskTxPos(const CDiskBlockPos &block, unsigned int nTxPosIn) : blockPos(block), 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); }
+ 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 &&
+ return (a.blockPos == b.blockPos &&
a.nTxPos == b.nTxPos);
}
@@ -158,8 +239,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
@@ -545,7 +628,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");
@@ -1215,22 +1298,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
@@ -1241,12 +1317,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)
@@ -1294,7 +1370,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) const;
bool AcceptBlock();
@@ -1320,9 +1396,8 @@ public:
const uint256* phashBlock;
CBlockIndex* pprev;
CBlockIndex* pnext;
- unsigned int nFile;
- unsigned int nBlockPos;
int nHeight;
+ unsigned int nAlternative;
CBigNum bnChainWork;
// block header
@@ -1338,10 +1413,9 @@ public:
phashBlock = NULL;
pprev = NULL;
pnext = NULL;
- nFile = 0;
- nBlockPos = 0;
nHeight = 0;
bnChainWork = 0;
+ nAlternative = 0;
nVersion = 0;
hashMerkleRoot = 0;
@@ -1350,15 +1424,14 @@ 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;
bnChainWork = 0;
+ nAlternative = 0;
nVersion = block.nVersion;
hashMerkleRoot = block.hashMerkleRoot;
@@ -1367,6 +1440,10 @@ public:
nNonce = block.nNonce;
}
+ CDiskBlockPos GetBlockPos() const {
+ return CDiskBlockPos(nHeight, nAlternative);
+ }
+
CBlock GetBlockHeader() const
{
CBlock block;
@@ -1444,11 +1521,10 @@ public:
static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart,
unsigned int nRequired, unsigned int nToCheck);
-
std::string ToString() const
{
- return strprintf("CBlockIndex(pprev=%p, pnext=%p, nFile=%u, nBlockPos=%-6u nHeight=%d, merkle=%s, hashBlock=%s)",
- pprev, pnext, nFile, nBlockPos, nHeight,
+ return strprintf("CBlockIndex(pprev=%p, pnext=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
+ pprev, pnext, nHeight,
hashMerkleRoot.ToString().substr(0,10).c_str(),
GetBlockHash().ToString().substr(0,20).c_str());
}
@@ -1486,9 +1562,8 @@ public:
READWRITE(nVersion);
READWRITE(hashNext);
- READWRITE(nFile);
- READWRITE(nBlockPos);
READWRITE(nHeight);
+ READWRITE(nAlternative);
// block header
READWRITE(this->nVersion);