block index checking on load, extra redundant checks, misc refactoring
This commit is contained in:
parent
43deefa435
commit
7a37c906a1
11
db.cpp
11
db.cpp
@ -419,6 +419,9 @@ bool CTxDB::LoadBlockIndex()
|
|||||||
// Watch for genesis block
|
// Watch for genesis block
|
||||||
if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
|
if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
|
||||||
pindexGenesisBlock = pindexNew;
|
pindexGenesisBlock = pindexNew;
|
||||||
|
|
||||||
|
if (!pindexNew->CheckIndex())
|
||||||
|
return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -454,7 +457,7 @@ bool CTxDB::LoadBlockIndex()
|
|||||||
pindexBest = mapBlockIndex[hashBestChain];
|
pindexBest = mapBlockIndex[hashBestChain];
|
||||||
nBestHeight = pindexBest->nHeight;
|
nBestHeight = pindexBest->nHeight;
|
||||||
bnBestChainWork = pindexBest->bnChainWork;
|
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
|
// Load bnBestInvalidWork, OK if it doesn't exist
|
||||||
ReadBestInvalidWork(bnBestInvalidWork);
|
ReadBestInvalidWork(bnBestInvalidWork);
|
||||||
@ -463,6 +466,8 @@ bool CTxDB::LoadBlockIndex()
|
|||||||
CBlockIndex* pindexFork = NULL;
|
CBlockIndex* pindexFork = NULL;
|
||||||
for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
|
for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
|
||||||
{
|
{
|
||||||
|
if (pindex->nHeight < 74000 && !mapArgs.count("-checkblocks"))
|
||||||
|
break;
|
||||||
CBlock block;
|
CBlock block;
|
||||||
if (!block.ReadFromDisk(pindex))
|
if (!block.ReadFromDisk(pindex))
|
||||||
return error("LoadBlockIndex() : block.ReadFromDisk failed");
|
return error("LoadBlockIndex() : block.ReadFromDisk failed");
|
||||||
@ -629,8 +634,8 @@ bool CWalletDB::LoadWallet()
|
|||||||
//printf("LoadWallet %s\n", wtx.GetHash().ToString().c_str());
|
//printf("LoadWallet %s\n", wtx.GetHash().ToString().c_str());
|
||||||
//printf(" %12I64d %s %s %s\n",
|
//printf(" %12I64d %s %s %s\n",
|
||||||
// wtx.vout[0].nValue,
|
// wtx.vout[0].nValue,
|
||||||
// DateTimeStrFormat("%x %H:%M:%S", wtx.nTime).c_str(),
|
// DateTimeStrFormat("%x %H:%M:%S", wtx.GetBlockTime()).c_str(),
|
||||||
// wtx.hashBlock.ToString().substr(0,16).c_str(),
|
// wtx.hashBlock.ToString().substr(0,20).c_str(),
|
||||||
// wtx.mapValue["message"].c_str());
|
// wtx.mapValue["message"].c_str());
|
||||||
}
|
}
|
||||||
else if (strType == "key" || strType == "wkey")
|
else if (strType == "key" || strType == "wkey")
|
||||||
|
98
main.cpp
98
main.cpp
@ -500,8 +500,8 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis
|
|||||||
return error("AcceptTransaction() : CheckTransaction failed");
|
return error("AcceptTransaction() : CheckTransaction failed");
|
||||||
|
|
||||||
// To help v0.1.5 clients who would see it as a negative number
|
// To help v0.1.5 clients who would see it as a negative number
|
||||||
if (nLockTime > INT_MAX)
|
if ((int64)nLockTime > INT_MAX)
|
||||||
return error("AcceptTransaction() : not accepting nLockTime beyond 2038");
|
return error("AcceptTransaction() : not accepting nLockTime beyond 2038 yet");
|
||||||
|
|
||||||
// Do we already have it?
|
// Do we already have it?
|
||||||
uint256 hash = GetHash();
|
uint256 hash = GetHash();
|
||||||
@ -519,6 +519,9 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis
|
|||||||
COutPoint outpoint = vin[i].prevout;
|
COutPoint outpoint = vin[i].prevout;
|
||||||
if (mapNextTx.count(outpoint))
|
if (mapNextTx.count(outpoint))
|
||||||
{
|
{
|
||||||
|
// Disable replacement feature for now
|
||||||
|
return false;
|
||||||
|
|
||||||
// Allow replacing with a newer version of the same transaction
|
// Allow replacing with a newer version of the same transaction
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
return false;
|
return false;
|
||||||
@ -550,8 +553,8 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis
|
|||||||
{
|
{
|
||||||
if (ptxOld)
|
if (ptxOld)
|
||||||
{
|
{
|
||||||
printf("mapTransaction.erase(%s) replacing with new version\n", ptxOld->GetHash().ToString().c_str());
|
printf("AcceptTransaction() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
|
||||||
mapTransactions.erase(ptxOld->GetHash());
|
ptxOld->RemoveFromMemoryPool();
|
||||||
}
|
}
|
||||||
AddToMemoryPool();
|
AddToMemoryPool();
|
||||||
}
|
}
|
||||||
@ -748,6 +751,12 @@ void ResendWalletTransactions()
|
|||||||
if (fFirst)
|
if (fFirst)
|
||||||
return;
|
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
|
// Rebroadcast any of our txes that aren't in a block yet
|
||||||
printf("ResendWalletTransactions()\n");
|
printf("ResendWalletTransactions()\n");
|
||||||
CTxDB txdb("r");
|
CTxDB txdb("r");
|
||||||
@ -785,9 +794,13 @@ void ResendWalletTransactions()
|
|||||||
// CBlock and CBlockIndex
|
// 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)
|
uint256 GetOrphanRoot(const CBlock* pblock)
|
||||||
@ -829,7 +842,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast)
|
|||||||
assert(pindexFirst);
|
assert(pindexFirst);
|
||||||
|
|
||||||
// Limit adjustment step
|
// Limit adjustment step
|
||||||
int64 nActualTimespan = (int64)pindexLast->nTime - (int64)pindexFirst->nTime;
|
int64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
|
||||||
printf(" nActualTimespan = %"PRI64d" before bounds\n", nActualTimespan);
|
printf(" nActualTimespan = %"PRI64d" before bounds\n", nActualTimespan);
|
||||||
if (nActualTimespan < nTargetTimespan/4)
|
if (nActualTimespan < nTargetTimespan/4)
|
||||||
nActualTimespan = nTargetTimespan/4;
|
nActualTimespan = nTargetTimespan/4;
|
||||||
@ -854,6 +867,22 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast)
|
|||||||
return bnNew.GetCompact();
|
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()
|
bool IsInitialBlockDownload()
|
||||||
{
|
{
|
||||||
if (pindexBest == NULL)
|
if (pindexBest == NULL)
|
||||||
@ -866,7 +895,7 @@ bool IsInitialBlockDownload()
|
|||||||
nLastUpdate = GetTime();
|
nLastUpdate = GetTime();
|
||||||
}
|
}
|
||||||
return (GetTime() - nLastUpdate < 10 &&
|
return (GetTime() - nLastUpdate < 10 &&
|
||||||
pindexBest->nTime < GetTime() - 24 * 60 * 60);
|
pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsLockdown()
|
bool IsLockdown()
|
||||||
@ -884,8 +913,8 @@ void Lockdown(CBlockIndex* pindexNew)
|
|||||||
CTxDB().WriteBestInvalidWork(bnBestInvalidWork);
|
CTxDB().WriteBestInvalidWork(bnBestInvalidWork);
|
||||||
MainFrameRepaint();
|
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: 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,22).c_str(), nBestHeight, bnBestChainWork.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));
|
printf("Lockdown: IsLockdown()=%d\n", (IsLockdown() ? 1 : 0));
|
||||||
if (IsLockdown())
|
if (IsLockdown())
|
||||||
printf("Lockdown: WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n");
|
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
|
|||||||
nValueIn += txPrev.vout[prevout.n].nValue;
|
nValueIn += txPrev.vout[prevout.n].nValue;
|
||||||
|
|
||||||
// Check for negative or overflow input values
|
// Check for negative or overflow input values
|
||||||
if (txPrev.vout[prevout.n].nValue < 0)
|
if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
|
||||||
return error("ConnectInputs() : txin.nValue negative");
|
return error("ConnectInputs() : txin values out of range");
|
||||||
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 (nValueIn < GetValueOut())
|
||||||
|
return error("ConnectInputs() : %s value in < value out", GetHash().ToString().substr(0,6).c_str());
|
||||||
|
|
||||||
// Tally transaction fees
|
// Tally transaction fees
|
||||||
int64 nTxFee = nValueIn - GetValueOut();
|
int64 nTxFee = nValueIn - GetValueOut();
|
||||||
if (nTxFee < 0)
|
if (nTxFee < 0)
|
||||||
@ -1180,7 +1208,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
|
|||||||
foreach(CBlockIndex* pindex, vDisconnect)
|
foreach(CBlockIndex* pindex, vDisconnect)
|
||||||
{
|
{
|
||||||
CBlock block;
|
CBlock block;
|
||||||
if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos))
|
if (!block.ReadFromDisk(pindex))
|
||||||
return error("Reorganize() : ReadFromDisk for disconnect failed");
|
return error("Reorganize() : ReadFromDisk for disconnect failed");
|
||||||
if (!block.DisconnectBlock(txdb, pindex))
|
if (!block.DisconnectBlock(txdb, pindex))
|
||||||
return error("Reorganize() : DisconnectBlock failed");
|
return error("Reorganize() : DisconnectBlock failed");
|
||||||
@ -1197,7 +1225,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
|
|||||||
{
|
{
|
||||||
CBlockIndex* pindex = vConnect[i];
|
CBlockIndex* pindex = vConnect[i];
|
||||||
CBlock block;
|
CBlock block;
|
||||||
if (!block.ReadFromDisk(pindex->nFile, pindex->nBlockPos))
|
if (!block.ReadFromDisk(pindex))
|
||||||
return error("Reorganize() : ReadFromDisk for connect failed");
|
return error("Reorganize() : ReadFromDisk for connect failed");
|
||||||
if (!block.ConnectBlock(txdb, pindex))
|
if (!block.ConnectBlock(txdb, pindex))
|
||||||
{
|
{
|
||||||
@ -1283,7 +1311,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
|
|||||||
bnBestChainWork = pindexNew->bnChainWork;
|
bnBestChainWork = pindexNew->bnChainWork;
|
||||||
nTimeBestReceived = GetTime();
|
nTimeBestReceived = GetTime();
|
||||||
nTransactionsUpdated++;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1294,7 +1322,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
|
|||||||
// Check for duplicate
|
// Check for duplicate
|
||||||
uint256 hash = GetHash();
|
uint256 hash = GetHash();
|
||||||
if (mapBlockIndex.count(hash))
|
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
|
// Construct new block index object
|
||||||
CBlockIndex* pindexNew = new CBlockIndex(nFile, nBlockPos, *this);
|
CBlockIndex* pindexNew = new CBlockIndex(nFile, nBlockPos, *this);
|
||||||
@ -1346,7 +1374,7 @@ bool CBlock::CheckBlock() const
|
|||||||
return error("CheckBlock() : size limits failed");
|
return error("CheckBlock() : size limits failed");
|
||||||
|
|
||||||
// Check timestamp
|
// Check timestamp
|
||||||
if (nTime > GetAdjustedTime() + 2 * 60 * 60)
|
if (GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
|
||||||
return error("CheckBlock() : block timestamp too far in the future");
|
return error("CheckBlock() : block timestamp too far in the future");
|
||||||
|
|
||||||
// First transaction must be coinbase, the rest must not be
|
// First transaction must be coinbase, the rest must not be
|
||||||
@ -1362,10 +1390,8 @@ bool CBlock::CheckBlock() const
|
|||||||
return error("CheckBlock() : CheckTransaction failed");
|
return error("CheckBlock() : CheckTransaction failed");
|
||||||
|
|
||||||
// Check proof of work matches claimed amount
|
// Check proof of work matches claimed amount
|
||||||
if (CBigNum().SetCompact(nBits) > bnProofOfWorkLimit)
|
if (!CheckProofOfWork(GetHash(), nBits))
|
||||||
return error("CheckBlock() : nBits below minimum work");
|
return error("CheckBlock() : proof of work failed");
|
||||||
if (GetHash() > CBigNum().SetCompact(nBits).getuint256())
|
|
||||||
return error("CheckBlock() : hash doesn't match nBits");
|
|
||||||
|
|
||||||
// Check merkleroot
|
// Check merkleroot
|
||||||
if (hashMerkleRoot != BuildMerkleTree())
|
if (hashMerkleRoot != BuildMerkleTree())
|
||||||
@ -1388,12 +1414,12 @@ bool CBlock::AcceptBlock()
|
|||||||
CBlockIndex* pindexPrev = (*mi).second;
|
CBlockIndex* pindexPrev = (*mi).second;
|
||||||
|
|
||||||
// Check timestamp against prev
|
// Check timestamp against prev
|
||||||
if (nTime <= pindexPrev->GetMedianTimePast())
|
if (GetBlockTime() <= pindexPrev->GetMedianTimePast())
|
||||||
return error("AcceptBlock() : block's timestamp is too early");
|
return error("AcceptBlock() : block's timestamp is too early");
|
||||||
|
|
||||||
// Check that all transactions are finalized
|
// Check that all transactions are finalized
|
||||||
foreach(const CTransaction& tx, vtx)
|
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");
|
return error("AcceptBlock() : contains a non-final transaction");
|
||||||
|
|
||||||
// Check proof of work
|
// Check proof of work
|
||||||
@ -1442,9 +1468,9 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock)
|
|||||||
// Check for duplicate
|
// Check for duplicate
|
||||||
uint256 hash = pblock->GetHash();
|
uint256 hash = pblock->GetHash();
|
||||||
if (mapBlockIndex.count(hash))
|
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))
|
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
|
// Preliminary checks
|
||||||
if (!pblock->CheckBlock())
|
if (!pblock->CheckBlock())
|
||||||
@ -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 don't already have its previous block, shunt it off to holding area until we get it
|
||||||
if (!mapBlockIndex.count(pblock->hashPrevBlock))
|
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));
|
mapOrphanBlocks.insert(make_pair(hash, pblock));
|
||||||
mapOrphanBlocksByPrev.insert(make_pair(pblock->hashPrevBlock, pblock));
|
mapOrphanBlocksByPrev.insert(make_pair(pblock->hashPrevBlock, pblock));
|
||||||
|
|
||||||
@ -1731,8 +1757,8 @@ void PrintBlockTree()
|
|||||||
pindex->nHeight,
|
pindex->nHeight,
|
||||||
pindex->nFile,
|
pindex->nFile,
|
||||||
pindex->nBlockPos,
|
pindex->nBlockPos,
|
||||||
block.GetHash().ToString().substr(0,16).c_str(),
|
block.GetHash().ToString().substr(0,20).c_str(),
|
||||||
DateTimeStrFormat("%x %H:%M:%S", block.nTime).c_str(),
|
DateTimeStrFormat("%x %H:%M:%S", block.GetBlockTime()).c_str(),
|
||||||
block.vtx.size());
|
block.vtx.size());
|
||||||
|
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
CRITICAL_BLOCK(cs_mapWallet)
|
||||||
@ -2157,12 +2183,12 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||||||
if (pindex)
|
if (pindex)
|
||||||
pindex = pindex->pnext;
|
pindex = pindex->pnext;
|
||||||
int nLimit = 500 + locator.GetDistanceBack();
|
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)
|
for (; pindex; pindex = pindex->pnext)
|
||||||
{
|
{
|
||||||
if (pindex->GetBlockHash() == hashStop)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash()));
|
pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash()));
|
||||||
@ -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
|
// When this block is requested, we'll send an inv that'll make them
|
||||||
// getblocks the next batch of inventory.
|
// 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();
|
pfrom->hashContinue = pindex->GetBlockHash();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2237,7 +2263,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||||||
vRecv >> *pblock;
|
vRecv >> *pblock;
|
||||||
|
|
||||||
//// debug print
|
//// 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();
|
// pblock->print();
|
||||||
|
|
||||||
CInv inv(MSG_BLOCK, pblock->GetHash());
|
CInv inv(MSG_BLOCK, pblock->GetHash());
|
||||||
|
68
main.h
68
main.h
@ -19,8 +19,8 @@ static const unsigned int MAX_BLOCK_SIZE = 1000000;
|
|||||||
static const int64 COIN = 100000000;
|
static const int64 COIN = 100000000;
|
||||||
static const int64 CENT = 1000000;
|
static const int64 CENT = 1000000;
|
||||||
static const int64 MAX_MONEY = 21000000 * COIN;
|
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 int COINBASE_MATURITY = 100;
|
||||||
|
|
||||||
static const CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
|
static const CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
|
||||||
|
|
||||||
|
|
||||||
@ -83,6 +83,7 @@ string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtx
|
|||||||
void GenerateBitcoins(bool fGenerate);
|
void GenerateBitcoins(bool fGenerate);
|
||||||
void ThreadBitcoinMiner(void* parg);
|
void ThreadBitcoinMiner(void* parg);
|
||||||
void BitcoinMiner();
|
void BitcoinMiner();
|
||||||
|
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
|
||||||
bool IsInitialBlockDownload();
|
bool IsInitialBlockDownload();
|
||||||
bool IsLockdown();
|
bool IsLockdown();
|
||||||
|
|
||||||
@ -338,6 +339,8 @@ public:
|
|||||||
|
|
||||||
int64 GetCredit() const
|
int64 GetCredit() const
|
||||||
{
|
{
|
||||||
|
if (!MoneyRange(nValue))
|
||||||
|
throw runtime_error("CTxOut::GetCredit() : value out of range");
|
||||||
if (IsMine())
|
if (IsMine())
|
||||||
return nValue;
|
return nValue;
|
||||||
return 0;
|
return 0;
|
||||||
@ -424,7 +427,7 @@ public:
|
|||||||
nBlockHeight = nBestHeight;
|
nBlockHeight = nBestHeight;
|
||||||
if (nBlockTime == 0)
|
if (nBlockTime == 0)
|
||||||
nBlockTime = GetAdjustedTime();
|
nBlockTime = GetAdjustedTime();
|
||||||
if (nLockTime < (nLockTime < 500000000 ? nBlockHeight : nBlockTime))
|
if ((int64)nLockTime < (nLockTime < 500000000 ? (int64)nBlockHeight : nBlockTime))
|
||||||
return true;
|
return true;
|
||||||
foreach(const CTxIn& txin, vin)
|
foreach(const CTxIn& txin, vin)
|
||||||
if (!txin.IsFinal())
|
if (!txin.IsFinal())
|
||||||
@ -481,8 +484,8 @@ public:
|
|||||||
if (txout.nValue > MAX_MONEY)
|
if (txout.nValue > MAX_MONEY)
|
||||||
return error("CTransaction::CheckTransaction() : txout.nValue too high");
|
return error("CTransaction::CheckTransaction() : txout.nValue too high");
|
||||||
nValueOut += txout.nValue;
|
nValueOut += txout.nValue;
|
||||||
if (nValueOut > MAX_MONEY)
|
if (!MoneyRange(nValueOut))
|
||||||
return error("CTransaction::CheckTransaction() : txout total too high");
|
return error("CTransaction::CheckTransaction() : txout total out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsCoinBase())
|
if (IsCoinBase())
|
||||||
@ -512,7 +515,11 @@ public:
|
|||||||
{
|
{
|
||||||
int64 nDebit = 0;
|
int64 nDebit = 0;
|
||||||
foreach(const CTxIn& txin, vin)
|
foreach(const CTxIn& txin, vin)
|
||||||
|
{
|
||||||
nDebit += txin.GetDebit();
|
nDebit += txin.GetDebit();
|
||||||
|
if (!MoneyRange(nDebit))
|
||||||
|
throw runtime_error("CTransaction::GetDebit() : value out of range");
|
||||||
|
}
|
||||||
return nDebit;
|
return nDebit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,7 +527,11 @@ public:
|
|||||||
{
|
{
|
||||||
int64 nCredit = 0;
|
int64 nCredit = 0;
|
||||||
foreach(const CTxOut& txout, vout)
|
foreach(const CTxOut& txout, vout)
|
||||||
|
{
|
||||||
nCredit += txout.GetCredit();
|
nCredit += txout.GetCredit();
|
||||||
|
if (!MoneyRange(nCredit))
|
||||||
|
throw runtime_error("CTransaction::GetCredit() : value out of range");
|
||||||
|
}
|
||||||
return nCredit;
|
return nCredit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,9 +540,9 @@ public:
|
|||||||
int64 nValueOut = 0;
|
int64 nValueOut = 0;
|
||||||
foreach(const CTxOut& txout, vout)
|
foreach(const CTxOut& txout, vout)
|
||||||
{
|
{
|
||||||
if (txout.nValue < 0)
|
|
||||||
throw runtime_error("CTransaction::GetValueOut() : negative value");
|
|
||||||
nValueOut += txout.nValue;
|
nValueOut += txout.nValue;
|
||||||
|
if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut))
|
||||||
|
throw runtime_error("CTransaction::GetValueOut() : value out of range");
|
||||||
}
|
}
|
||||||
return nValueOut;
|
return nValueOut;
|
||||||
}
|
}
|
||||||
@ -930,6 +941,11 @@ public:
|
|||||||
return Hash(BEGIN(nVersion), END(nNonce));
|
return Hash(BEGIN(nVersion), END(nNonce));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64 GetBlockTime() const
|
||||||
|
{
|
||||||
|
return (int64)nTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint256 BuildMerkleTree() const
|
uint256 BuildMerkleTree() const
|
||||||
{
|
{
|
||||||
@ -1030,10 +1046,8 @@ public:
|
|||||||
filein >> *this;
|
filein >> *this;
|
||||||
|
|
||||||
// Check the header
|
// Check the header
|
||||||
if (CBigNum().SetCompact(nBits) > bnProofOfWorkLimit)
|
if (!CheckProofOfWork(GetHash(), nBits))
|
||||||
return error("CBlock::ReadFromDisk() : nBits errors in block header");
|
return error("CBlock::ReadFromDisk() : errors in block header");
|
||||||
if (GetHash() > CBigNum().SetCompact(nBits).getuint256())
|
|
||||||
return error("CBlock::ReadFromDisk() : GetHash() errors in block header");
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1043,9 +1057,9 @@ public:
|
|||||||
void print() const
|
void print() const
|
||||||
{
|
{
|
||||||
printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%d)\n",
|
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,
|
nVersion,
|
||||||
hashPrevBlock.ToString().substr(0,16).c_str(),
|
hashPrevBlock.ToString().substr(0,20).c_str(),
|
||||||
hashMerkleRoot.ToString().substr(0,6).c_str(),
|
hashMerkleRoot.ToString().substr(0,6).c_str(),
|
||||||
nTime, nBits, nNonce,
|
nTime, nBits, nNonce,
|
||||||
vtx.size());
|
vtx.size());
|
||||||
@ -1064,7 +1078,7 @@ public:
|
|||||||
int64 GetBlockValue(int nHeight, int64 nFees) const;
|
int64 GetBlockValue(int nHeight, int64 nFees) const;
|
||||||
bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);
|
bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);
|
||||||
bool ConnectBlock(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 SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew);
|
||||||
bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);
|
bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);
|
||||||
bool CheckBlock() const;
|
bool CheckBlock() const;
|
||||||
@ -1142,8 +1156,15 @@ public:
|
|||||||
return *phashBlock;
|
return *phashBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64 GetBlockTime() const
|
||||||
|
{
|
||||||
|
return (int64)nTime;
|
||||||
|
}
|
||||||
|
|
||||||
CBigNum GetBlockWork() const
|
CBigNum GetBlockWork() const
|
||||||
{
|
{
|
||||||
|
if (CBigNum().SetCompact(nBits) <= 0)
|
||||||
|
return 0;
|
||||||
return (CBigNum(1)<<256) / (CBigNum().SetCompact(nBits)+1);
|
return (CBigNum(1)<<256) / (CBigNum().SetCompact(nBits)+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1152,6 +1173,11 @@ public:
|
|||||||
return (pnext || this == pindexBest);
|
return (pnext || this == pindexBest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CheckIndex() const
|
||||||
|
{
|
||||||
|
return CheckProofOfWork(GetBlockHash(), nBits);
|
||||||
|
}
|
||||||
|
|
||||||
bool EraseBlockFromDisk()
|
bool EraseBlockFromDisk()
|
||||||
{
|
{
|
||||||
// Open history file
|
// Open history file
|
||||||
@ -1171,13 +1197,13 @@ public:
|
|||||||
|
|
||||||
int64 GetMedianTimePast() const
|
int64 GetMedianTimePast() const
|
||||||
{
|
{
|
||||||
unsigned int pmedian[nMedianTimeSpan];
|
int64 pmedian[nMedianTimeSpan];
|
||||||
unsigned int* pbegin = &pmedian[nMedianTimeSpan];
|
int64* pbegin = &pmedian[nMedianTimeSpan];
|
||||||
unsigned int* pend = &pmedian[nMedianTimeSpan];
|
int64* pend = &pmedian[nMedianTimeSpan];
|
||||||
|
|
||||||
const CBlockIndex* pindex = this;
|
const CBlockIndex* pindex = this;
|
||||||
for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
|
for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
|
||||||
*(--pbegin) = pindex->nTime;
|
*(--pbegin) = pindex->GetBlockTime();
|
||||||
|
|
||||||
sort(pbegin, pend);
|
sort(pbegin, pend);
|
||||||
return pbegin[(pend - pbegin)/2];
|
return pbegin[(pend - pbegin)/2];
|
||||||
@ -1189,7 +1215,7 @@ public:
|
|||||||
for (int i = 0; i < nMedianTimeSpan/2; i++)
|
for (int i = 0; i < nMedianTimeSpan/2; i++)
|
||||||
{
|
{
|
||||||
if (!pindex->pnext)
|
if (!pindex->pnext)
|
||||||
return nTime;
|
return GetBlockTime();
|
||||||
pindex = pindex->pnext;
|
pindex = pindex->pnext;
|
||||||
}
|
}
|
||||||
return pindex->GetMedianTimePast();
|
return pindex->GetMedianTimePast();
|
||||||
@ -1202,7 +1228,7 @@ public:
|
|||||||
return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)",
|
return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)",
|
||||||
pprev, pnext, nFile, nBlockPos, nHeight,
|
pprev, pnext, nFile, nBlockPos, nHeight,
|
||||||
hashMerkleRoot.ToString().substr(0,6).c_str(),
|
hashMerkleRoot.ToString().substr(0,6).c_str(),
|
||||||
GetBlockHash().ToString().substr(0,16).c_str());
|
GetBlockHash().ToString().substr(0,20).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void print() const
|
void print() const
|
||||||
@ -1272,8 +1298,8 @@ public:
|
|||||||
str += CBlockIndex::ToString();
|
str += CBlockIndex::ToString();
|
||||||
str += strprintf("\n hashBlock=%s, hashPrev=%s, hashNext=%s)",
|
str += strprintf("\n hashBlock=%s, hashPrev=%s, hashNext=%s)",
|
||||||
GetBlockHash().ToString().c_str(),
|
GetBlockHash().ToString().c_str(),
|
||||||
hashPrev.ToString().substr(0,16).c_str(),
|
hashPrev.ToString().substr(0,20).c_str(),
|
||||||
hashNext.ToString().substr(0,16).c_str());
|
hashNext.ToString().substr(0,20).c_str());
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
net.h
2
net.h
@ -424,7 +424,7 @@ public:
|
|||||||
|
|
||||||
string ToString() const
|
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
|
void print() const
|
||||||
|
@ -20,7 +20,7 @@ class CDataStream;
|
|||||||
class CAutoFile;
|
class CAutoFile;
|
||||||
|
|
||||||
static const int VERSION = 310;
|
static const int VERSION = 310;
|
||||||
static const char* pszSubVer = ".3";
|
static const char* pszSubVer = ".4";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -81,6 +81,13 @@ enum
|
|||||||
|
|
||||||
#define READWRITE(obj) (nSerSize += ::SerReadWrite(s, (obj), nType, nVersion, ser_action))
|
#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…
Reference in New Issue
Block a user