auxpow final fixes

This commit is contained in:
nzsquirrell
2015-07-12 13:22:37 +12:00
parent 35d6a558fa
commit fc0af636d7
6 changed files with 163 additions and 79 deletions
+100 -47
View File
@@ -1135,17 +1135,6 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
// CBlock and CBlockIndex
//
std::string CDiskBlockIndex::ToString() const
{
std::string str = "CDiskBlockIndex(";
str += CBlockIndex::ToString();
str += strprintf("\n hashBlock=%s, hashPrev=%s, hashParentBlock=%s)",
GetBlockHash().ToString().c_str(),
hashPrev.ToString().c_str(),
(auxpow.get() != NULL) ? auxpow->GetParentBlockHash(GetAlgo()).ToString().substr(0,20).c_str() : "-");
return str;
}
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos)
{
// Open history file to append
@@ -1190,7 +1179,8 @@ bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
}
// Check the header
if (!CheckProofOfWork(block.GetPoWHash(block.GetAlgo()), block.nBits, block.GetAlgo()))
//if (!CheckProofOfWork(block.GetPoWHash(block.GetAlgo()), block.nBits, block.GetAlgo()))
if (!block.CheckProofOfWork(mapBlockIndex[block.GetHash()]->nHeight))
return error("ReadBlockFromDisk : Errors in block header");
return true;
@@ -1999,7 +1989,8 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
{
AssertLockHeld(cs_main);
// Check it again in case a previous version let a bad block in
if (!CheckBlock(block, state, !fJustCheck, !fJustCheck))
//if (!CheckBlock(block, state, !fJustCheck, !fJustCheck))
if (!CheckBlock(block, state, pindex->nHeight, !fJustCheck, !fJustCheck))
return false;
// verify that the view's current state corresponds to the previous block
@@ -2409,27 +2400,6 @@ bool ActivateBestChain(CValidationState &state) {
return true;
}
CBlockHeader CBlockIndex::GetBlockHeader() const
{
CBlockHeader block;
if (nVersion & BLOCK_VERSION_AUXPOW) {
CDiskBlockIndex diskblockindex;
// auxpow is not in memory, load CDiskBlockHeader
// from database to get it
pblocktree->ReadDiskBlockIndex(*phashBlock, diskblockindex);
block.auxpow = diskblockindex.auxpow;
}
block.nVersion = nVersion;
if (pprev)
block.hashPrevBlock = pprev->GetBlockHash();
block.hashMerkleRoot = hashMerkleRoot;
block.nTime = nTime;
block.nBits = nBits;
block.nNonce = nNonce;
return block;
}
bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos)
{
// Check for duplicate
@@ -2466,10 +2436,8 @@ bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos
pindexNew->nStatus = BLOCK_VALID_TRANSACTIONS | BLOCK_HAVE_DATA;
setBlockIndexValid.insert(pindexNew);
//if (!pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew, block.auxpow)) || !pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew)))
if (!pblocktree->WriteDiskBlockIndex(CDiskBlockIndex(pindexNew, block.auxpow)) || !pblocktree->WriteBlockIndex(*pindexNew))
/* write both the immutible data (CDiskBlockIndex) and the mutable data (BlockIndex) */
//if (!pblocktree->WriteDiskBlockIndex(CDiskBlockIndex(pindexNew, block.auxpow)) || !pblocktree->WriteBlockIndex(*pindexNew))
if (!pblocktree->WriteDiskBlockIndex(CDiskBlockIndex(pindexNew, block.auxpow)) || !pblocktree->WriteBlockIndex(*pindexNew))
return state.Abort(_("Failed to write block index"));
// New best?
@@ -2590,26 +2558,66 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
return true;
}
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, int nHeight, bool fCheckPOW)
{
// Check proof of work matches claimed amount
if (fCheckPOW && !block.CheckProofOfWork(nHeight))
//if (fCheckPOW && !CheckProofOfWork(block.GetPoWHash(block.GetAlgo()), block.nBits, block.GetAlgo()))
return state.DoS(50, error("CheckBlockHeader() : proof of work failed"),
REJECT_INVALID, "high-hash");
bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bool fCheckMerkleRoot)
// Check timestamp
if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
return state.Invalid(error("CheckBlockHeader() : block timestamp too far in the future"),
REJECT_INVALID, "time-too-new");
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex);
if (pcheckpoint && block.hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0)))
{
// Extra checks to prevent "fill up memory by spamming with bogus blocks"
int64_t deltaTime = block.GetBlockTime() - pcheckpoint->nTime;
if (deltaTime < 0)
{
LogPrintf("CheckBlockHeader(): Height=%d, hash=%s, BlockTime=%d, Checkpoint=%d\n", nHeight, block.GetHash().GetHex().c_str(), block.GetBlockTime(), pcheckpoint->nTime);
return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"),
REJECT_CHECKPOINT, "time-too-old");
}
CBigNum bnNewBlock;
bnNewBlock.SetCompact(block.nBits);
CBigNum bnRequired;
bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime));
if (bnNewBlock > bnRequired)
{
return state.DoS(100, error("CheckBlockHeader() : block with too little proof-of-work"),
REJECT_INVALID, "bad-diffbits");
}
}
return true;
}
bool CheckBlock(const CBlock& block, CValidationState& state, int nHeight, bool fCheckPOW, bool fCheckMerkleRoot)
{
// These are checks that are independent of context
// that can be verified before saving an orphan block.
if (!CheckBlockHeader(block, state, nHeight, fCheckPOW))
return false;
// Size limits
if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
return state.DoS(100, error("CheckBlock() : size limits failed"),
REJECT_INVALID, "bad-blk-length");
// Check proof of work matches claimed amount
if (fCheckPOW && !CheckProofOfWork(block.GetPoWHash(block.GetAlgo()), block.nBits, block.GetAlgo()))
return state.DoS(50, error("CheckBlock() : proof of work failed"),
REJECT_INVALID, "high-hash");
// if (fCheckPOW && !CheckProofOfWork(block.GetPoWHash(block.GetAlgo()), block.nBits, block.GetAlgo()))
// return state.DoS(50, error("CheckBlock() : proof of work failed"),
// REJECT_INVALID, "high-hash");
// Check timestamp
if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
return state.Invalid(error("CheckBlock() : block timestamp too far in the future"),
REJECT_INVALID, "time-too-new");
// if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
// return state.Invalid(error("CheckBlock() : block timestamp too far in the future"),
// REJECT_INVALID, "time-too-new");
// First transaction must be coinbase, the rest must not be
if (block.vtx.empty() || !block.vtx[0].IsCoinBase())
@@ -2812,6 +2820,48 @@ int64_t CBlockIndex::GetMedianTime() const
return pindex->GetMedianTimePast();
}
std::string CBlockIndex::ToString() const
{
return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
pprev, nHeight,
hashMerkleRoot.ToString().substr(0,10).c_str(),
GetBlockHash().ToString().c_str());
}
std::string CDiskBlockIndex::ToString() const
{
std::string str = "CDiskBlockIndex(";
str += CBlockIndex::ToString();
str += strprintf("\n hashBlock=%s, hashPrev=%s, hashParentBlock=%s)",
GetBlockHash().ToString().c_str(),
hashPrev.ToString().c_str(),
(auxpow.get() != NULL) ? auxpow->GetParentBlockHash(GetAlgo()).ToString().substr(0,20).c_str() : "-");
return str;
}
CBlockHeader CBlockIndex::GetBlockHeader() const
{
CBlockHeader block;
if (nVersion & BLOCK_VERSION_AUXPOW) {
CDiskBlockIndex diskblockindex;
// auxpow is not in memory, load CDiskBlockHeader
// from database to get it
pblocktree->ReadDiskBlockIndex(*phashBlock, diskblockindex);
block.auxpow = diskblockindex.auxpow;
}
block.nVersion = nVersion;
if (pprev)
block.hashPrevBlock = pprev->GetBlockHash();
block.hashMerkleRoot = hashMerkleRoot;
block.nTime = nTime;
block.nBits = nBits;
block.nNonce = nNonce;
return block;
}
void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd)
{
AssertLockHeld(cs_main);
@@ -2835,9 +2885,12 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
if (mapOrphanBlocks.count(hash))
return state.Invalid(error("ProcessBlock() : already have block (orphan) %s", hash.ToString()), 0, "duplicate");
// Preliminary checks
if (!CheckBlock(*pblock, state))
if (!CheckBlock(*pblock, state, INT_MAX))
{
if (state.CorruptionPossible())
mapAlreadyAskedFor.erase(CInv(MSG_BLOCK, hash));
return error("ProcessBlock() : CheckBlock FAILED");
}
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex);
if (pcheckpoint && pblock->hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0)))
@@ -3235,7 +3288,7 @@ bool VerifyDB(int nCheckLevel, int nCheckDepth)
if (!ReadBlockFromDisk(block, pindex))
return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
// check level 1: verify block validity
if (nCheckLevel >= 1 && !CheckBlock(block, state))
if (nCheckLevel >= 1 && !CheckBlock(block, state, pindex->nHeight))
return error("VerifyDB() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
// check level 2: verify undo validity
if (nCheckLevel >= 2 && pindex) {