Browse Source

block index checking on load, extra redundant checks, misc refactoring

0.8
Satoshi Nakamoto 14 years ago committed by Gavin Andresen
parent
commit
7a37c906a1
  1. 11
      db.cpp
  2. 98
      main.cpp
  3. 68
      main.h
  4. 2
      net.h
  5. 9
      serialize.h

11
db.cpp

@ -419,6 +419,9 @@ bool CTxDB::LoadBlockIndex() @@ -419,6 +419,9 @@ bool CTxDB::LoadBlockIndex()
// Watch for genesis block
if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
pindexGenesisBlock = pindexNew;
if (!pindexNew->CheckIndex())
return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight);
}
else
{
@ -454,7 +457,7 @@ bool CTxDB::LoadBlockIndex() @@ -454,7 +457,7 @@ bool CTxDB::LoadBlockIndex()
pindexBest = mapBlockIndex[hashBestChain];
nBestHeight = pindexBest->nHeight;
bnBestChainWork = pindexBest->bnChainWork;
printf("LoadBlockIndex(): hashBestChain=%s height=%d\n", hashBestChain.ToString().substr(0,16).c_str(), nBestHeight);
printf("LoadBlockIndex(): hashBestChain=%s height=%d\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight);
// Load bnBestInvalidWork, OK if it doesn't exist
ReadBestInvalidWork(bnBestInvalidWork);
@ -463,6 +466,8 @@ bool CTxDB::LoadBlockIndex() @@ -463,6 +466,8 @@ bool CTxDB::LoadBlockIndex()
CBlockIndex* pindexFork = NULL;
for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
{
if (pindex->nHeight < 74000 && !mapArgs.count("-checkblocks"))
break;
CBlock block;
if (!block.ReadFromDisk(pindex))
return error("LoadBlockIndex() : block.ReadFromDisk failed");
@ -629,8 +634,8 @@ bool CWalletDB::LoadWallet() @@ -629,8 +634,8 @@ bool CWalletDB::LoadWallet()
//printf("LoadWallet %s\n", wtx.GetHash().ToString().c_str());
//printf(" %12I64d %s %s %s\n",
// wtx.vout[0].nValue,
// DateTimeStrFormat("%x %H:%M:%S", wtx.nTime).c_str(),
// wtx.hashBlock.ToString().substr(0,16).c_str(),
// DateTimeStrFormat("%x %H:%M:%S", wtx.GetBlockTime()).c_str(),
// wtx.hashBlock.ToString().substr(0,20).c_str(),
// wtx.mapValue["message"].c_str());
}
else if (strType == "key" || strType == "wkey")

98
main.cpp

@ -500,8 +500,8 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis @@ -500,8 +500,8 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis
return error("AcceptTransaction() : CheckTransaction failed");
// To help v0.1.5 clients who would see it as a negative number
if (nLockTime > INT_MAX)
return error("AcceptTransaction() : not accepting nLockTime beyond 2038");
if ((int64)nLockTime > INT_MAX)
return error("AcceptTransaction() : not accepting nLockTime beyond 2038 yet");
// Do we already have it?
uint256 hash = GetHash();
@ -519,6 +519,9 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis @@ -519,6 +519,9 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis
COutPoint outpoint = vin[i].prevout;
if (mapNextTx.count(outpoint))
{
// Disable replacement feature for now
return false;
// Allow replacing with a newer version of the same transaction
if (i != 0)
return false;
@ -550,8 +553,8 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis @@ -550,8 +553,8 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis
{
if (ptxOld)
{
printf("mapTransaction.erase(%s) replacing with new version\n", ptxOld->GetHash().ToString().c_str());
mapTransactions.erase(ptxOld->GetHash());
printf("AcceptTransaction() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
ptxOld->RemoveFromMemoryPool();
}
AddToMemoryPool();
}
@ -748,6 +751,12 @@ void ResendWalletTransactions() @@ -748,6 +751,12 @@ void ResendWalletTransactions()
if (fFirst)
return;
// Only do it if there's been a new block since last time
static int64 nLastTime;
if (nTimeBestReceived < nLastTime)
return;
nLastTime = GetTime();
// Rebroadcast any of our txes that aren't in a block yet
printf("ResendWalletTransactions()\n");
CTxDB txdb("r");
@ -785,9 +794,13 @@ void ResendWalletTransactions() @@ -785,9 +794,13 @@ void ResendWalletTransactions()
// CBlock and CBlockIndex
//
bool CBlock::ReadFromDisk(const CBlockIndex* pblockindex, bool fReadTransactions)
bool CBlock::ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions)
{
return ReadFromDisk(pblockindex->nFile, pblockindex->nBlockPos, fReadTransactions);
if (!ReadFromDisk(pindex->nFile, pindex->nBlockPos, fReadTransactions))
return false;
if (GetHash() != pindex->GetBlockHash())
return error("CBlock::ReadFromDisk() : GetHash() doesn't match index");
return true;
}
uint256 GetOrphanRoot(const CBlock* pblock)
@ -829,7 +842,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast) @@ -829,7 +842,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast)
assert(pindexFirst);
// Limit adjustment step
int64 nActualTimespan = (int64)pindexLast->nTime - (int64)pindexFirst->nTime;
int64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
printf(" nActualTimespan = %"PRI64d" before bounds\n", nActualTimespan);
if (nActualTimespan < nTargetTimespan/4)
nActualTimespan = nTargetTimespan/4;
@ -854,6 +867,22 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast) @@ -854,6 +867,22 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast)
return bnNew.GetCompact();
}
bool CheckProofOfWork(uint256 hash, unsigned int nBits)
{
CBigNum bnTarget;
bnTarget.SetCompact(nBits);
// Check range
if (bnTarget <= 0 || bnTarget > bnProofOfWorkLimit)
return error("CheckProofOfWork() : nBits below minimum work");
// Check proof of work matches claimed amount
if (hash > bnTarget.getuint256())
return error("CheckProofOfWork() : hash doesn't match nBits");
return true;
}
bool IsInitialBlockDownload()
{
if (pindexBest == NULL)
@ -866,7 +895,7 @@ bool IsInitialBlockDownload() @@ -866,7 +895,7 @@ bool IsInitialBlockDownload()
nLastUpdate = GetTime();
}
return (GetTime() - nLastUpdate < 10 &&
pindexBest->nTime < GetTime() - 24 * 60 * 60);
pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60);
}
bool IsLockdown()
@ -884,8 +913,8 @@ void Lockdown(CBlockIndex* pindexNew) @@ -884,8 +913,8 @@ void Lockdown(CBlockIndex* pindexNew)
CTxDB().WriteBestInvalidWork(bnBestInvalidWork);
MainFrameRepaint();
}
printf("Lockdown: invalid block=%s height=%d work=%s\n", pindexNew->GetBlockHash().ToString().substr(0,22).c_str(), pindexNew->nHeight, pindexNew->bnChainWork.ToString().c_str());
printf("Lockdown: current best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,22).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());
printf("Lockdown: invalid block=%s height=%d work=%s\n", pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight, pindexNew->bnChainWork.ToString().c_str());
printf("Lockdown: current best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());
printf("Lockdown: IsLockdown()=%d\n", (IsLockdown() ? 1 : 0));
if (IsLockdown())
printf("Lockdown: WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n");
@ -1008,14 +1037,13 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPoo @@ -1008,14 +1037,13 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPoo
nValueIn += txPrev.vout[prevout.n].nValue;
// Check for negative or overflow input values
if (txPrev.vout[prevout.n].nValue < 0)
return error("ConnectInputs() : txin.nValue negative");
if (txPrev.vout[prevout.n].nValue > MAX_MONEY)
return error("ConnectInputs() : txin.nValue too high");
if (nValueIn > MAX_MONEY)
return error("ConnectInputs() : txin total too high");
if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
return error("ConnectInputs() : txin values out of range");
}
if (nValueIn < GetValueOut())
return error("ConnectInputs() : %s value in < value out", GetHash().ToString().substr(0,6).c_str());
// Tally transaction fees
int64 nTxFee = nValueIn - GetValueOut();
if (nTxFee < 0)
@ -1180,7 +1208,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) @@ -1180,7 +1208,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
foreach(CBlockIndex* pindex, vDisconnect)
{
CBlock block;
if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos))
if (!block.ReadFromDisk(pindex))
return error("Reorganize() : ReadFromDisk for disconnect failed");
if (!block.DisconnectBlock(txdb, pindex))
return error("Reorganize() : DisconnectBlock failed");
@ -1197,7 +1225,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) @@ -1197,7 +1225,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
{
CBlockIndex* pindex = vConnect[i];
CBlock block;
if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos))
if (!block.ReadFromDisk(pindex))
return error("Reorganize() : ReadFromDisk for connect failed");
if (!block.ConnectBlock(txdb, pindex))
{
@ -1283,7 +1311,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) @@ -1283,7 +1311,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
bnBestChainWork = pindexNew->bnChainWork;
nTimeBestReceived = GetTime();
nTransactionsUpdated++;
printf("SetBestChain: new best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,22).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());
printf("SetBestChain: new best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());
return true;
}
@ -1294,7 +1322,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos) @@ -1294,7 +1322,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
// Check for duplicate
uint256 hash = GetHash();
if (mapBlockIndex.count(hash))
return error("AddToBlockIndex() : %s already exists", hash.ToString().substr(0,16).c_str());
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);
@ -1346,7 +1374,7 @@ bool CBlock::CheckBlock() const @@ -1346,7 +1374,7 @@ bool CBlock::CheckBlock() const
return error("CheckBlock() : size limits failed");
// Check timestamp
if (nTime > GetAdjustedTime() + 2 * 60 * 60)
if (GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
return error("CheckBlock() : block timestamp too far in the future");
// First transaction must be coinbase, the rest must not be
@ -1362,10 +1390,8 @@ bool CBlock::CheckBlock() const @@ -1362,10 +1390,8 @@ bool CBlock::CheckBlock() const
return error("CheckBlock() : CheckTransaction failed");
// Check proof of work matches claimed amount
if (CBigNum().SetCompact(nBits) > bnProofOfWorkLimit)
return error("CheckBlock() : nBits below minimum work");
if (GetHash() > CBigNum().SetCompact(nBits).getuint256())
return error("CheckBlock() : hash doesn't match nBits");
if (!CheckProofOfWork(GetHash(), nBits))
return error("CheckBlock() : proof of work failed");
// Check merkleroot
if (hashMerkleRoot != BuildMerkleTree())
@ -1388,12 +1414,12 @@ bool CBlock::AcceptBlock() @@ -1388,12 +1414,12 @@ bool CBlock::AcceptBlock()
CBlockIndex* pindexPrev = (*mi).second;
// Check timestamp against prev
if (nTime <= pindexPrev->GetMedianTimePast())
if (GetBlockTime() <= pindexPrev->GetMedianTimePast())
return error("AcceptBlock() : block's timestamp is too early");
// Check that all transactions are finalized
foreach(const CTransaction& tx, vtx)
if (!tx.IsFinal(pindexPrev->nHeight+1, nTime))
if (!tx.IsFinal(pindexPrev->nHeight+1, GetBlockTime()))
return error("AcceptBlock() : contains a non-final transaction");
// Check proof of work
@ -1442,9 +1468,9 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock) @@ -1442,9 +1468,9 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock)
// Check for duplicate
uint256 hash = pblock->GetHash();
if (mapBlockIndex.count(hash))
return error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString().substr(0,16).c_str());
return error("ProcessBlock() : already have block %d %s", mapBlockIndex[hash]->nHeight, hash.ToString().substr(0,20).c_str());
if (mapOrphanBlocks.count(hash))
return error("ProcessBlock() : already have block (orphan) %s", hash.ToString().substr(0,16).c_str());
return error("ProcessBlock() : already have block (orphan) %s", hash.ToString().substr(0,20).c_str());
// Preliminary checks
if (!pblock->CheckBlock())
@ -1456,7 +1482,7 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock) @@ -1456,7 +1482,7 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock)
// If don't already have its previous block, shunt it off to holding area until we get it
if (!mapBlockIndex.count(pblock->hashPrevBlock))
{
printf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", pblock->hashPrevBlock.ToString().substr(0,16).c_str());
printf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", pblock->hashPrevBlock.ToString().substr(0,20).c_str());
mapOrphanBlocks.insert(make_pair(hash, pblock));
mapOrphanBlocksByPrev.insert(make_pair(pblock->hashPrevBlock, pblock));
@ -1731,8 +1757,8 @@ void PrintBlockTree() @@ -1731,8 +1757,8 @@ void PrintBlockTree()
pindex->nHeight,
pindex->nFile,
pindex->nBlockPos,
block.GetHash().ToString().substr(0,16).c_str(),
DateTimeStrFormat("%x %H:%M:%S", block.nTime).c_str(),
block.GetHash().ToString().substr(0,20).c_str(),
DateTimeStrFormat("%x %H:%M:%S", block.GetBlockTime()).c_str(),
block.vtx.size());
CRITICAL_BLOCK(cs_mapWallet)
@ -2157,12 +2183,12 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -2157,12 +2183,12 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (pindex)
pindex = pindex->pnext;
int nLimit = 500 + locator.GetDistanceBack();
printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,16).c_str(), nLimit);
printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().substr(0,20).c_str(), nLimit);
for (; pindex; pindex = pindex->pnext)
{
if (pindex->GetBlockHash() == hashStop)
{
printf(" getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,16).c_str());
printf(" getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str());
break;
}
pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash()));
@ -2170,7 +2196,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -2170,7 +2196,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
// When this block is requested, we'll send an inv that'll make them
// getblocks the next batch of inventory.
printf(" getblocks stopping at limit %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,16).c_str());
printf(" getblocks stopping at limit %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString().substr(0,20).c_str());
pfrom->hashContinue = pindex->GetBlockHash();
break;
}
@ -2237,7 +2263,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -2237,7 +2263,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vRecv >> *pblock;
//// debug print
printf("received block %s\n", pblock->GetHash().ToString().substr(0,16).c_str());
printf("received block %s\n", pblock->GetHash().ToString().substr(0,20).c_str());
// pblock->print();
CInv inv(MSG_BLOCK, pblock->GetHash());

68
main.h

@ -19,8 +19,8 @@ static const unsigned int MAX_BLOCK_SIZE = 1000000; @@ -19,8 +19,8 @@ static const unsigned int MAX_BLOCK_SIZE = 1000000;
static const int64 COIN = 100000000;
static const int64 CENT = 1000000;
static const int64 MAX_MONEY = 21000000 * COIN;
inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
static const int COINBASE_MATURITY = 100;
static const CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
@ -83,6 +83,7 @@ string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtx @@ -83,6 +83,7 @@ string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtx
void GenerateBitcoins(bool fGenerate);
void ThreadBitcoinMiner(void* parg);
void BitcoinMiner();
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
bool IsInitialBlockDownload();
bool IsLockdown();
@ -338,6 +339,8 @@ public: @@ -338,6 +339,8 @@ public:
int64 GetCredit() const
{
if (!MoneyRange(nValue))
throw runtime_error("CTxOut::GetCredit() : value out of range");
if (IsMine())
return nValue;
return 0;
@ -424,7 +427,7 @@ public: @@ -424,7 +427,7 @@ public:
nBlockHeight = nBestHeight;
if (nBlockTime == 0)
nBlockTime = GetAdjustedTime();
if (nLockTime < (nLockTime < 500000000 ? nBlockHeight : nBlockTime))
if ((int64)nLockTime < (nLockTime < 500000000 ? (int64)nBlockHeight : nBlockTime))
return true;
foreach(const CTxIn& txin, vin)
if (!txin.IsFinal())
@ -481,8 +484,8 @@ public: @@ -481,8 +484,8 @@ public:
if (txout.nValue > MAX_MONEY)
return error("CTransaction::CheckTransaction() : txout.nValue too high");
nValueOut += txout.nValue;
if (nValueOut > MAX_MONEY)
return error("CTransaction::CheckTransaction() : txout total too high");
if (!MoneyRange(nValueOut))
return error("CTransaction::CheckTransaction() : txout total out of range");
}
if (IsCoinBase())
@ -512,7 +515,11 @@ public: @@ -512,7 +515,11 @@ public:
{
int64 nDebit = 0;
foreach(const CTxIn& txin, vin)
{
nDebit += txin.GetDebit();
if (!MoneyRange(nDebit))
throw runtime_error("CTransaction::GetDebit() : value out of range");
}
return nDebit;
}
@ -520,7 +527,11 @@ public: @@ -520,7 +527,11 @@ public:
{
int64 nCredit = 0;
foreach(const CTxOut& txout, vout)
{
nCredit += txout.GetCredit();
if (!MoneyRange(nCredit))
throw runtime_error("CTransaction::GetCredit() : value out of range");
}
return nCredit;
}
@ -529,9 +540,9 @@ public: @@ -529,9 +540,9 @@ public:
int64 nValueOut = 0;
foreach(const CTxOut& txout, vout)
{
if (txout.nValue < 0)
throw runtime_error("CTransaction::GetValueOut() : negative value");
nValueOut += txout.nValue;
if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut))
throw runtime_error("CTransaction::GetValueOut() : value out of range");
}
return nValueOut;
}
@ -930,6 +941,11 @@ public: @@ -930,6 +941,11 @@ public:
return Hash(BEGIN(nVersion), END(nNonce));
}
int64 GetBlockTime() const
{
return (int64)nTime;
}
uint256 BuildMerkleTree() const
{
@ -1030,10 +1046,8 @@ public: @@ -1030,10 +1046,8 @@ public:
filein >> *this;
// Check the header
if (CBigNum().SetCompact(nBits) > bnProofOfWorkLimit)
return error("CBlock::ReadFromDisk() : nBits errors in block header");
if (GetHash() > CBigNum().SetCompact(nBits).getuint256())
return error("CBlock::ReadFromDisk() : GetHash() errors in block header");
if (!CheckProofOfWork(GetHash(), nBits))
return error("CBlock::ReadFromDisk() : errors in block header");
return true;
}
@ -1043,9 +1057,9 @@ public: @@ -1043,9 +1057,9 @@ public:
void print() const
{
printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%d)\n",
GetHash().ToString().substr(0,16).c_str(),
GetHash().ToString().substr(0,20).c_str(),
nVersion,
hashPrevBlock.ToString().substr(0,16).c_str(),
hashPrevBlock.ToString().substr(0,20).c_str(),
hashMerkleRoot.ToString().substr(0,6).c_str(),
nTime, nBits, nNonce,
vtx.size());
@ -1064,7 +1078,7 @@ public: @@ -1064,7 +1078,7 @@ public:
int64 GetBlockValue(int nHeight, int64 nFees) const;
bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);
bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex);
bool ReadFromDisk(const CBlockIndex* blockindex, bool fReadTransactions=true);
bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true);
bool SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew);
bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);
bool CheckBlock() const;
@ -1142,8 +1156,15 @@ public: @@ -1142,8 +1156,15 @@ public:
return *phashBlock;
}
int64 GetBlockTime() const
{
return (int64)nTime;
}
CBigNum GetBlockWork() const
{
if (CBigNum().SetCompact(nBits) <= 0)
return 0;
return (CBigNum(1)<<256) / (CBigNum().SetCompact(nBits)+1);
}
@ -1152,6 +1173,11 @@ public: @@ -1152,6 +1173,11 @@ public:
return (pnext || this == pindexBest);
}
bool CheckIndex() const
{
return CheckProofOfWork(GetBlockHash(), nBits);
}
bool EraseBlockFromDisk()
{
// Open history file
@ -1171,13 +1197,13 @@ public: @@ -1171,13 +1197,13 @@ public:
int64 GetMedianTimePast() const
{
unsigned int pmedian[nMedianTimeSpan];
unsigned int* pbegin = &pmedian[nMedianTimeSpan];
unsigned int* pend = &pmedian[nMedianTimeSpan];
int64 pmedian[nMedianTimeSpan];
int64* pbegin = &pmedian[nMedianTimeSpan];
int64* pend = &pmedian[nMedianTimeSpan];
const CBlockIndex* pindex = this;
for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
*(--pbegin) = pindex->nTime;
*(--pbegin) = pindex->GetBlockTime();
sort(pbegin, pend);
return pbegin[(pend - pbegin)/2];
@ -1189,7 +1215,7 @@ public: @@ -1189,7 +1215,7 @@ public:
for (int i = 0; i < nMedianTimeSpan/2; i++)
{
if (!pindex->pnext)
return nTime;
return GetBlockTime();
pindex = pindex->pnext;
}
return pindex->GetMedianTimePast();
@ -1202,7 +1228,7 @@ public: @@ -1202,7 +1228,7 @@ public:
return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)",
pprev, pnext, nFile, nBlockPos, nHeight,
hashMerkleRoot.ToString().substr(0,6).c_str(),
GetBlockHash().ToString().substr(0,16).c_str());
GetBlockHash().ToString().substr(0,20).c_str());
}
void print() const
@ -1272,8 +1298,8 @@ public: @@ -1272,8 +1298,8 @@ public:
str += CBlockIndex::ToString();
str += strprintf("\n hashBlock=%s, hashPrev=%s, hashNext=%s)",
GetBlockHash().ToString().c_str(),
hashPrev.ToString().substr(0,16).c_str(),
hashNext.ToString().substr(0,16).c_str());
hashPrev.ToString().substr(0,20).c_str(),
hashNext.ToString().substr(0,20).c_str());
return str;
}

2
net.h

@ -424,7 +424,7 @@ public: @@ -424,7 +424,7 @@ public:
string ToString() const
{
return strprintf("%s %s", GetCommand(), hash.ToString().substr(0,16).c_str());
return strprintf("%s %s", GetCommand(), hash.ToString().substr(0,20).c_str());
}
void print() const

9
serialize.h

@ -20,7 +20,7 @@ class CDataStream; @@ -20,7 +20,7 @@ class CDataStream;
class CAutoFile;
static const int VERSION = 310;
static const char* pszSubVer = ".3";
static const char* pszSubVer = ".4";
@ -81,6 +81,13 @@ enum @@ -81,6 +81,13 @@ enum
#define READWRITE(obj) (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action))
#define READWRITEVER(obj) \
do { \
READWRITE((obj)); \
if ((obj) == 10300) \
(obj) = 300; \
} while (false)

Loading…
Cancel
Save